Line data Source code
1 : // Copyright 2017 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #ifndef V8_OBJECTS_FIXED_ARRAY_INL_H_
6 : #define V8_OBJECTS_FIXED_ARRAY_INL_H_
7 :
8 : #include "src/objects/fixed-array.h"
9 :
10 : #include "src/base/tsan.h"
11 : #include "src/conversions.h"
12 : #include "src/handles-inl.h"
13 : #include "src/heap/heap-write-barrier-inl.h"
14 : #include "src/objects-inl.h"
15 : #include "src/objects/bigint.h"
16 : #include "src/objects/compressed-slots.h"
17 : #include "src/objects/heap-number-inl.h"
18 : #include "src/objects/map.h"
19 : #include "src/objects/maybe-object-inl.h"
20 : #include "src/objects/oddball.h"
21 : #include "src/objects/slots.h"
22 : #include "src/roots-inl.h"
23 :
24 : // Has to be the last include (doesn't have include guards):
25 : #include "src/objects/object-macros.h"
26 :
27 : namespace v8 {
28 : namespace internal {
29 :
30 : OBJECT_CONSTRUCTORS_IMPL(FixedArrayBase, HeapObject)
31 : OBJECT_CONSTRUCTORS_IMPL(FixedArray, FixedArrayBase)
32 : OBJECT_CONSTRUCTORS_IMPL(FixedDoubleArray, FixedArrayBase)
33 : OBJECT_CONSTRUCTORS_IMPL(FixedTypedArrayBase, FixedArrayBase)
34 : OBJECT_CONSTRUCTORS_IMPL(ArrayList, FixedArray)
35 : OBJECT_CONSTRUCTORS_IMPL(ByteArray, FixedArrayBase)
36 : OBJECT_CONSTRUCTORS_IMPL(TemplateList, FixedArray)
37 : OBJECT_CONSTRUCTORS_IMPL(WeakFixedArray, HeapObject)
38 : OBJECT_CONSTRUCTORS_IMPL(WeakArrayList, HeapObject)
39 :
40 : FixedArrayBase::FixedArrayBase(Address ptr, AllowInlineSmiStorage allow_smi)
41 : : HeapObject(ptr, allow_smi) {
42 : SLOW_DCHECK(
43 : (allow_smi == AllowInlineSmiStorage::kAllowBeingASmi && IsSmi()) ||
44 : IsFixedArrayBase());
45 : }
46 :
47 : ByteArray::ByteArray(Address ptr, AllowInlineSmiStorage allow_smi)
48 : : FixedArrayBase(ptr, allow_smi) {
49 : SLOW_DCHECK(
50 : (allow_smi == AllowInlineSmiStorage::kAllowBeingASmi && IsSmi()) ||
51 : IsByteArray());
52 : }
53 :
54 : NEVER_READ_ONLY_SPACE_IMPL(WeakArrayList)
55 :
56 : CAST_ACCESSOR(ArrayList)
57 : CAST_ACCESSOR(ByteArray)
58 : CAST_ACCESSOR(FixedArray)
59 : CAST_ACCESSOR(FixedArrayBase)
60 : CAST_ACCESSOR(FixedDoubleArray)
61 : CAST_ACCESSOR(FixedTypedArrayBase)
62 : CAST_ACCESSOR(TemplateList)
63 : CAST_ACCESSOR(WeakFixedArray)
64 : CAST_ACCESSOR(WeakArrayList)
65 :
66 886096291 : SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
67 107588467 : SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
68 83115586 : SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
69 11088888 : SYNCHRONIZED_SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
70 :
71 17537886 : SMI_ACCESSORS(WeakArrayList, capacity, kCapacityOffset)
72 3780651 : SYNCHRONIZED_SMI_ACCESSORS(WeakArrayList, capacity, kCapacityOffset)
73 66125464 : SMI_ACCESSORS(WeakArrayList, length, kLengthOffset)
74 :
75 : Object FixedArrayBase::unchecked_synchronized_length() const {
76 7511438 : return ACQUIRE_READ_FIELD(*this, kLengthOffset);
77 : }
78 :
79 91891843 : ACCESSORS(FixedTypedArrayBase, base_pointer, Object, kBasePointerOffset)
80 :
81 : ObjectSlot FixedArray::GetFirstElementAddress() {
82 : return RawField(OffsetOfElementAt(0));
83 : }
84 :
85 : bool FixedArray::ContainsOnlySmisOrHoles() {
86 : Object the_hole = GetReadOnlyRoots().the_hole_value();
87 : ObjectSlot current = GetFirstElementAddress();
88 : for (int i = 0; i < length(); ++i, ++current) {
89 : Object candidate = *current;
90 : if (!candidate->IsSmi() && candidate != the_hole) return false;
91 : }
92 : return true;
93 : }
94 :
95 92784 : Object FixedArray::get(int index) const {
96 : DCHECK(index >= 0 && index < this->length());
97 6279624944 : return RELAXED_READ_FIELD(*this, kHeaderSize + index * kTaggedSize);
98 : }
99 :
100 16454864 : Handle<Object> FixedArray::get(FixedArray array, int index, Isolate* isolate) {
101 16454864 : return handle(array->get(index), isolate);
102 : }
103 :
104 : template <class T>
105 4764572 : MaybeHandle<T> FixedArray::GetValue(Isolate* isolate, int index) const {
106 : Object obj = get(index);
107 4764572 : if (obj->IsUndefined(isolate)) return MaybeHandle<T>();
108 861834 : return Handle<T>(T::cast(obj), isolate);
109 : }
110 :
111 : template <class T>
112 257540 : Handle<T> FixedArray::GetValueChecked(Isolate* isolate, int index) const {
113 : Object obj = get(index);
114 257540 : CHECK(!obj->IsUndefined(isolate));
115 257540 : return Handle<T>(T::cast(obj), isolate);
116 : }
117 :
118 : bool FixedArray::is_the_hole(Isolate* isolate, int index) {
119 : return get(index)->IsTheHole(isolate);
120 : }
121 :
122 : void FixedArray::set(int index, Smi value) {
123 : DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
124 : DCHECK_LT(index, this->length());
125 : DCHECK(Object(value).IsSmi());
126 147362175 : int offset = kHeaderSize + index * kTaggedSize;
127 253265577 : RELAXED_WRITE_FIELD(*this, offset, value);
128 : }
129 :
130 791306634 : void FixedArray::set(int index, Object value) {
131 : DCHECK_NE(GetReadOnlyRoots().fixed_cow_array_map(), map());
132 : DCHECK(IsFixedArray());
133 : DCHECK_GE(index, 0);
134 : DCHECK_LT(index, this->length());
135 791306634 : int offset = kHeaderSize + index * kTaggedSize;
136 791306634 : RELAXED_WRITE_FIELD(*this, offset, value);
137 791306634 : WRITE_BARRIER(*this, offset, value);
138 791306743 : }
139 :
140 244630423 : void FixedArray::set(int index, Object value, WriteBarrierMode mode) {
141 : DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
142 : DCHECK_GE(index, 0);
143 : DCHECK_LT(index, this->length());
144 244630423 : int offset = kHeaderSize + index * kTaggedSize;
145 244633675 : RELAXED_WRITE_FIELD(*this, offset, value);
146 405971233 : CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode);
147 244630656 : }
148 :
149 : void FixedArray::NoWriteBarrierSet(FixedArray array, int index, Object value) {
150 : DCHECK_NE(array->map(), array->GetReadOnlyRoots().fixed_cow_array_map());
151 : DCHECK_GE(index, 0);
152 : DCHECK_LT(index, array->length());
153 : DCHECK(!ObjectInYoungGeneration(value));
154 354085740 : RELAXED_WRITE_FIELD(array, kHeaderSize + index * kTaggedSize, value);
155 : }
156 :
157 332211200 : void FixedArray::set_undefined(int index) {
158 : set_undefined(GetReadOnlyRoots(), index);
159 332211200 : }
160 :
161 : void FixedArray::set_undefined(Isolate* isolate, int index) {
162 : set_undefined(ReadOnlyRoots(isolate), index);
163 : }
164 :
165 : void FixedArray::set_undefined(ReadOnlyRoots ro_roots, int index) {
166 : FixedArray::NoWriteBarrierSet(*this, index, ro_roots.undefined_value());
167 : }
168 :
169 1166 : void FixedArray::set_null(int index) { set_null(GetReadOnlyRoots(), index); }
170 :
171 : void FixedArray::set_null(Isolate* isolate, int index) {
172 : set_null(ReadOnlyRoots(isolate), index);
173 : }
174 :
175 : void FixedArray::set_null(ReadOnlyRoots ro_roots, int index) {
176 : FixedArray::NoWriteBarrierSet(*this, index, ro_roots.null_value());
177 : }
178 :
179 11811186 : void FixedArray::set_the_hole(int index) {
180 : set_the_hole(GetReadOnlyRoots(), index);
181 11811186 : }
182 :
183 1 : void FixedArray::set_the_hole(Isolate* isolate, int index) {
184 : set_the_hole(ReadOnlyRoots(isolate), index);
185 1 : }
186 :
187 : void FixedArray::set_the_hole(ReadOnlyRoots ro_roots, int index) {
188 : FixedArray::NoWriteBarrierSet(*this, index, ro_roots.the_hole_value());
189 : }
190 :
191 : void FixedArray::FillWithHoles(int from, int to) {
192 24148124 : for (int i = from; i < to; i++) {
193 11686904 : set_the_hole(i);
194 : }
195 : }
196 :
197 : ObjectSlot FixedArray::data_start() {
198 : return RawField(OffsetOfElementAt(0));
199 : }
200 :
201 : ObjectSlot FixedArray::RawFieldOfElementAt(int index) {
202 : return RawField(OffsetOfElementAt(index));
203 : }
204 :
205 : void FixedArray::MoveElements(Heap* heap, int dst_index, int src_index, int len,
206 : WriteBarrierMode mode) {
207 : DisallowHeapAllocation no_gc;
208 180504 : heap->MoveElements(*this, dst_index, src_index, len, mode);
209 : }
210 :
211 : void FixedArray::CopyElements(Heap* heap, int dst_index, FixedArray src,
212 : int src_index, int len, WriteBarrierMode mode) {
213 : DisallowHeapAllocation no_gc;
214 643743 : heap->CopyElements(*this, src, dst_index, src_index, len, mode);
215 : }
216 :
217 : // Perform a binary search in a fixed array.
218 : template <SearchMode search_mode, typename T>
219 24624041 : int BinarySearch(T* array, Name name, int valid_entries,
220 : int* out_insertion_index) {
221 : DCHECK(search_mode == ALL_ENTRIES || out_insertion_index == nullptr);
222 : int low = 0;
223 24624041 : int high = array->number_of_entries() - 1;
224 : uint32_t hash = name->hash_field();
225 : int limit = high;
226 :
227 : DCHECK(low <= high);
228 :
229 213340041 : while (low != high) {
230 107464361 : int mid = low + (high - low) / 2;
231 81251761 : Name mid_name = array->GetSortedKey(mid);
232 : uint32_t mid_hash = mid_name->hash_field();
233 :
234 107464300 : if (mid_hash >= hash) {
235 : high = mid;
236 : } else {
237 50073848 : low = mid + 1;
238 : }
239 : }
240 :
241 24623980 : for (; low <= limit; ++low) {
242 : int sort_index = array->GetSortedKeyIndex(low);
243 7184271 : Name entry = array->GetKey(sort_index);
244 : uint32_t current_hash = entry->hash_field();
245 24623965 : if (current_hash != hash) {
246 120040 : if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
247 59379 : *out_insertion_index = sort_index + (current_hash > hash ? 0 : 1);
248 : }
249 : return T::kNotFound;
250 : }
251 11591224 : if (entry == name) {
252 4526993 : if (search_mode == ALL_ENTRIES || sort_index < valid_entries) {
253 4352217 : return sort_index;
254 : }
255 : return T::kNotFound;
256 : }
257 : }
258 :
259 0 : if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
260 0 : *out_insertion_index = limit + 1;
261 : }
262 : return T::kNotFound;
263 : }
264 :
265 : // Perform a linear search in this fixed array. len is the number of entry
266 : // indices that are valid.
267 : template <SearchMode search_mode, typename T>
268 42241848 : int LinearSearch(T* array, Name name, int valid_entries,
269 : int* out_insertion_index) {
270 13055403 : if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
271 : uint32_t hash = name->hash_field();
272 : int len = array->number_of_entries();
273 630706 : for (int number = 0; number < len; number++) {
274 : int sorted_index = array->GetSortedKeyIndex(number);
275 346797 : Name entry = array->GetKey(sorted_index);
276 : uint32_t current_hash = entry->hash_field();
277 346798 : if (current_hash > hash) {
278 105770 : *out_insertion_index = sorted_index;
279 105770 : return T::kNotFound;
280 : }
281 241028 : if (entry == name) return sorted_index;
282 : }
283 50984 : *out_insertion_index = len;
284 50984 : return T::kNotFound;
285 : } else {
286 : DCHECK_LE(valid_entries, array->number_of_entries());
287 : DCHECK_NULL(out_insertion_index); // Not supported here.
288 180472154 : for (int number = 0; number < valid_entries; number++) {
289 115813012 : if (array->GetKey(number) == name) return number;
290 : }
291 : return T::kNotFound;
292 : }
293 : }
294 :
295 : template <SearchMode search_mode, typename T>
296 67191660 : int Search(T* array, Name name, int valid_entries, int* out_insertion_index) {
297 : SLOW_DCHECK(array->IsSortedNoDuplicates());
298 :
299 67191660 : if (valid_entries == 0) {
300 325936 : if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
301 224467 : *out_insertion_index = 0;
302 : }
303 : return T::kNotFound;
304 : }
305 :
306 : // Fast case: do linear search for small arrays.
307 : const int kMaxElementsForLinearSearch = 8;
308 66865816 : if (valid_entries <= kMaxElementsForLinearSearch) {
309 : return LinearSearch<search_mode>(array, name, valid_entries,
310 42241854 : out_insertion_index);
311 : }
312 :
313 : // Slow case: perform binary search.
314 : return BinarySearch<search_mode>(array, name, valid_entries,
315 24623962 : out_insertion_index);
316 : }
317 :
318 496 : double FixedDoubleArray::get_scalar(int index) {
319 : DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
320 : map() != GetReadOnlyRoots().fixed_array_map());
321 : DCHECK(index >= 0 && index < this->length());
322 : DCHECK(!is_the_hole(index));
323 8229054 : return READ_DOUBLE_FIELD(*this, kHeaderSize + index * kDoubleSize);
324 : }
325 :
326 : uint64_t FixedDoubleArray::get_representation(int index) {
327 : DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
328 : map() != GetReadOnlyRoots().fixed_array_map());
329 : DCHECK(index >= 0 && index < this->length());
330 40231277 : int offset = kHeaderSize + index * kDoubleSize;
331 40231277 : return READ_UINT64_FIELD(*this, offset);
332 : }
333 :
334 9459511 : Handle<Object> FixedDoubleArray::get(FixedDoubleArray array, int index,
335 : Isolate* isolate) {
336 9459511 : if (array->is_the_hole(index)) {
337 1354952 : return ReadOnlyRoots(isolate).the_hole_value_handle();
338 : } else {
339 8104559 : return isolate->factory()->NewNumber(array->get_scalar(index));
340 : }
341 : }
342 :
343 11627944 : void FixedDoubleArray::set(int index, double value) {
344 : DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
345 : map() != GetReadOnlyRoots().fixed_array_map());
346 11627944 : int offset = kHeaderSize + index * kDoubleSize;
347 11627944 : if (std::isnan(value)) {
348 2146 : WRITE_DOUBLE_FIELD(*this, offset, std::numeric_limits<double>::quiet_NaN());
349 : } else {
350 11625798 : WRITE_DOUBLE_FIELD(*this, offset, value);
351 : }
352 : DCHECK(!is_the_hole(index));
353 11627944 : }
354 :
355 : void FixedDoubleArray::set_the_hole(Isolate* isolate, int index) {
356 : set_the_hole(index);
357 : }
358 :
359 : void FixedDoubleArray::set_the_hole(int index) {
360 : DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
361 : map() != GetReadOnlyRoots().fixed_array_map());
362 49233701 : int offset = kHeaderSize + index * kDoubleSize;
363 49233701 : WRITE_UINT64_FIELD(*this, offset, kHoleNanInt64);
364 : }
365 :
366 : bool FixedDoubleArray::is_the_hole(Isolate* isolate, int index) {
367 : return is_the_hole(index);
368 : }
369 :
370 : bool FixedDoubleArray::is_the_hole(int index) {
371 0 : return get_representation(index) == kHoleNanInt64;
372 : }
373 :
374 : void FixedDoubleArray::MoveElements(Heap* heap, int dst_index, int src_index,
375 : int len, WriteBarrierMode mode) {
376 : DCHECK_EQ(SKIP_WRITE_BARRIER, mode);
377 : double* data_start =
378 0 : reinterpret_cast<double*>(FIELD_ADDR(*this, kHeaderSize));
379 0 : MemMove(data_start + dst_index, data_start + src_index, len * kDoubleSize);
380 : }
381 :
382 : void FixedDoubleArray::FillWithHoles(int from, int to) {
383 788942 : for (int i = from; i < to; i++) {
384 : set_the_hole(i);
385 : }
386 : }
387 :
388 : MaybeObject WeakFixedArray::Get(int index) const {
389 : DCHECK(index >= 0 && index < this->length());
390 247923451 : return RELAXED_READ_WEAK_FIELD(*this, OffsetOfElementAt(index));
391 : }
392 :
393 32238096 : void WeakFixedArray::Set(int index, MaybeObject value) {
394 : DCHECK_GE(index, 0);
395 : DCHECK_LT(index, length());
396 : int offset = OffsetOfElementAt(index);
397 32238096 : RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
398 64476195 : WEAK_WRITE_BARRIER(*this, offset, value);
399 32238107 : }
400 :
401 2393696 : void WeakFixedArray::Set(int index, MaybeObject value, WriteBarrierMode mode) {
402 : DCHECK_GE(index, 0);
403 : DCHECK_LT(index, length());
404 : int offset = OffsetOfElementAt(index);
405 2393696 : RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
406 7181088 : CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
407 2393696 : }
408 :
409 : MaybeObjectSlot WeakFixedArray::data_start() {
410 : return RawMaybeWeakField(kHeaderSize);
411 : }
412 :
413 : MaybeObjectSlot WeakFixedArray::RawFieldOfElementAt(int index) {
414 : return RawMaybeWeakField(OffsetOfElementAt(index));
415 : }
416 :
417 120 : MaybeObject WeakArrayList::Get(int index) const {
418 : DCHECK(index >= 0 && index < this->capacity());
419 31635028 : return RELAXED_READ_WEAK_FIELD(*this, OffsetOfElementAt(index));
420 : }
421 :
422 35726451 : void WeakArrayList::Set(int index, MaybeObject value, WriteBarrierMode mode) {
423 : DCHECK_GE(index, 0);
424 : DCHECK_LT(index, this->capacity());
425 : int offset = OffsetOfElementAt(index);
426 35726451 : RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
427 84244196 : CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
428 35726449 : }
429 :
430 : MaybeObjectSlot WeakArrayList::data_start() {
431 : return RawMaybeWeakField(kHeaderSize);
432 : }
433 :
434 5210744 : HeapObject WeakArrayList::Iterator::Next() {
435 5210744 : if (!array_.is_null()) {
436 10445426 : while (index_ < array_->length()) {
437 5218519 : MaybeObject item = array_->Get(index_++);
438 : DCHECK(item->IsWeakOrCleared());
439 5218519 : if (!item->IsCleared()) return item->GetHeapObjectAssumeWeak();
440 : }
441 4194 : array_ = WeakArrayList();
442 : }
443 4244 : return HeapObject();
444 : }
445 :
446 19804 : int ArrayList::Length() const {
447 19804 : if (FixedArray::cast(*this)->length() == 0) return 0;
448 : return Smi::ToInt(FixedArray::cast(*this)->get(kLengthIndex));
449 : }
450 :
451 : void ArrayList::SetLength(int length) {
452 : return FixedArray::cast(*this)->set(kLengthIndex, Smi::FromInt(length));
453 : }
454 :
455 : Object ArrayList::Get(int index) const {
456 16599 : return FixedArray::cast(*this)->get(kFirstIndex + index);
457 : }
458 :
459 : ObjectSlot ArrayList::Slot(int index) {
460 : return RawField(OffsetOfElementAt(kFirstIndex + index));
461 : }
462 :
463 : void ArrayList::Set(int index, Object obj, WriteBarrierMode mode) {
464 1949 : FixedArray::cast(*this)->set(kFirstIndex + index, obj, mode);
465 : }
466 :
467 : void ArrayList::Clear(int index, Object undefined) {
468 : DCHECK(undefined->IsUndefined());
469 10 : FixedArray::cast(*this)->set(kFirstIndex + index, undefined,
470 5 : SKIP_WRITE_BARRIER);
471 : }
472 :
473 4242374 : int ByteArray::Size() { return RoundUp(length() + kHeaderSize, kTaggedSize); }
474 :
475 : byte ByteArray::get(int index) const {
476 : DCHECK(index >= 0 && index < this->length());
477 61746647 : return READ_BYTE_FIELD(*this, kHeaderSize + index * kCharSize);
478 : }
479 :
480 : void ByteArray::set(int index, byte value) {
481 : DCHECK(index >= 0 && index < this->length());
482 11693029 : WRITE_BYTE_FIELD(*this, kHeaderSize + index * kCharSize, value);
483 : }
484 :
485 : void ByteArray::copy_in(int index, const byte* buffer, int length) {
486 : DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
487 : index + length <= this->length());
488 130782 : Address dst_addr = FIELD_ADDR(*this, kHeaderSize + index * kCharSize);
489 130782 : memcpy(reinterpret_cast<void*>(dst_addr), buffer, length);
490 : }
491 :
492 : void ByteArray::copy_out(int index, byte* buffer, int length) {
493 : DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
494 : index + length <= this->length());
495 294869640 : Address src_addr = FIELD_ADDR(*this, kHeaderSize + index * kCharSize);
496 294869640 : memcpy(buffer, reinterpret_cast<void*>(src_addr), length);
497 : }
498 :
499 : int ByteArray::get_int(int index) const {
500 : DCHECK(index >= 0 && index < this->length() / kIntSize);
501 2264 : return READ_INT_FIELD(*this, kHeaderSize + index * kIntSize);
502 : }
503 :
504 : void ByteArray::set_int(int index, int value) {
505 : DCHECK(index >= 0 && index < this->length() / kIntSize);
506 1344 : WRITE_INT_FIELD(*this, kHeaderSize + index * kIntSize, value);
507 : }
508 :
509 : uint32_t ByteArray::get_uint32(int index) const {
510 : DCHECK(index >= 0 && index < this->length() / kUInt32Size);
511 1016218 : return READ_UINT32_FIELD(*this, kHeaderSize + index * kUInt32Size);
512 : }
513 :
514 : void ByteArray::set_uint32(int index, uint32_t value) {
515 : DCHECK(index >= 0 && index < this->length() / kUInt32Size);
516 149491 : WRITE_UINT32_FIELD(*this, kHeaderSize + index * kUInt32Size, value);
517 : }
518 :
519 7195015 : void ByteArray::clear_padding() {
520 7195015 : int data_size = length() + kHeaderSize;
521 14390030 : memset(reinterpret_cast<void*>(address() + data_size), 0, Size() - data_size);
522 7195015 : }
523 :
524 : ByteArray ByteArray::FromDataStartAddress(Address address) {
525 : DCHECK_TAG_ALIGNED(address);
526 : return ByteArray::cast(Object(address - kHeaderSize + kHeapObjectTag));
527 : }
528 :
529 620 : int ByteArray::DataSize() const { return RoundUp(length(), kTaggedSize); }
530 :
531 : int ByteArray::ByteArraySize() { return SizeFor(this->length()); }
532 :
533 : byte* ByteArray::GetDataStartAddress() {
534 268102865 : return reinterpret_cast<byte*>(address() + kHeaderSize);
535 : }
536 :
537 : byte* ByteArray::GetDataEndAddress() {
538 207377503 : return GetDataStartAddress() + length();
539 : }
540 :
541 : template <class T>
542 320 : PodArray<T>::PodArray(Address ptr) : ByteArray(ptr) {}
543 :
544 : template <class T>
545 : PodArray<T> PodArray<T>::cast(Object object) {
546 160 : return PodArray<T>(object.ptr());
547 : }
548 :
549 : // static
550 : template <class T>
551 : Handle<PodArray<T>> PodArray<T>::New(Isolate* isolate, int length,
552 : AllocationType allocation) {
553 13923 : return Handle<PodArray<T>>::cast(
554 : isolate->factory()->NewByteArray(length * sizeof(T), allocation));
555 : }
556 :
557 : template <class T>
558 : int PodArray<T>::length() const {
559 0 : return ByteArray::length() / sizeof(T);
560 : }
561 :
562 : void* FixedTypedArrayBase::external_pointer() const {
563 7707577 : intptr_t ptr = READ_INTPTR_FIELD(*this, kExternalPointerOffset);
564 2158 : return reinterpret_cast<void*>(ptr);
565 : }
566 :
567 : void FixedTypedArrayBase::set_external_pointer(void* value) {
568 17891 : intptr_t ptr = reinterpret_cast<intptr_t>(value);
569 18570 : WRITE_INTPTR_FIELD(*this, kExternalPointerOffset, ptr);
570 : }
571 :
572 : void* FixedTypedArrayBase::DataPtr() {
573 : return reinterpret_cast<void*>(
574 7705319 : base_pointer()->ptr() + reinterpret_cast<intptr_t>(external_pointer()));
575 : }
576 :
577 374247 : int FixedTypedArrayBase::ElementSize(InstanceType type) {
578 : int element_size;
579 374247 : switch (type) {
580 : #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
581 : case FIXED_##TYPE##_ARRAY_TYPE: \
582 : element_size = sizeof(ctype); \
583 : break;
584 :
585 25015 : TYPED_ARRAYS(TYPED_ARRAY_CASE)
586 : #undef TYPED_ARRAY_CASE
587 : default:
588 0 : UNREACHABLE();
589 : }
590 374247 : return element_size;
591 : }
592 :
593 863590 : int FixedTypedArrayBase::DataSize(InstanceType type) const {
594 863590 : if (base_pointer() == Smi::kZero) return 0;
595 374250 : return length() * ElementSize(type);
596 : }
597 :
598 248826 : int FixedTypedArrayBase::DataSize() const {
599 248826 : return DataSize(map()->instance_type());
600 : }
601 :
602 : size_t FixedTypedArrayBase::ByteLength() const {
603 : return static_cast<size_t>(length()) *
604 : static_cast<size_t>(ElementSize(map()->instance_type()));
605 : }
606 :
607 : int FixedTypedArrayBase::size() const {
608 214011 : return OBJECT_POINTER_ALIGN(kDataOffset + DataSize());
609 : }
610 :
611 : int FixedTypedArrayBase::TypedArraySize(InstanceType type) const {
612 614714 : return OBJECT_POINTER_ALIGN(kDataOffset + DataSize(type));
613 : }
614 :
615 : // static
616 : int FixedTypedArrayBase::TypedArraySize(InstanceType type, int length) {
617 : return OBJECT_POINTER_ALIGN(kDataOffset + length * ElementSize(type));
618 : }
619 :
620 : uint8_t Uint8ArrayTraits::defaultValue() { return 0; }
621 :
622 : uint8_t Uint8ClampedArrayTraits::defaultValue() { return 0; }
623 :
624 : int8_t Int8ArrayTraits::defaultValue() { return 0; }
625 :
626 : uint16_t Uint16ArrayTraits::defaultValue() { return 0; }
627 :
628 : int16_t Int16ArrayTraits::defaultValue() { return 0; }
629 :
630 : uint32_t Uint32ArrayTraits::defaultValue() { return 0; }
631 :
632 : int32_t Int32ArrayTraits::defaultValue() { return 0; }
633 :
634 : float Float32ArrayTraits::defaultValue() {
635 : return std::numeric_limits<float>::quiet_NaN();
636 : }
637 :
638 : double Float64ArrayTraits::defaultValue() {
639 : return std::numeric_limits<double>::quiet_NaN();
640 : }
641 :
642 : template <class Traits>
643 429193 : typename Traits::ElementType FixedTypedArray<Traits>::get_scalar(int index) {
644 : // TODO(bmeurer, v8:4153): Solve this differently.
645 : // DCHECK((index < this->length()));
646 429193 : CHECK_GE(index, 0);
647 429193 : return FixedTypedArray<Traits>::get_scalar_from_data_ptr(DataPtr(), index);
648 : }
649 :
650 : // static
651 : template <class Traits>
652 : typename Traits::ElementType FixedTypedArray<Traits>::get_scalar_from_data_ptr(
653 : void* data_ptr, int index) {
654 : typename Traits::ElementType* ptr = reinterpret_cast<ElementType*>(data_ptr);
655 : // The JavaScript memory model allows for racy reads and writes to a
656 : // SharedArrayBuffer's backing store, which will always be a FixedTypedArray.
657 : // ThreadSanitizer will catch these racy accesses and warn about them, so we
658 : // disable TSAN for these reads and writes using annotations.
659 : //
660 : // We don't use relaxed atomics here, as it is not a requirement of the
661 : // JavaScript memory model to have tear-free reads of overlapping accesses,
662 : // and using relaxed atomics may introduce overhead.
663 : TSAN_ANNOTATE_IGNORE_READS_BEGIN;
664 : ElementType result;
665 : if (COMPRESS_POINTERS_BOOL && alignof(ElementType) > kTaggedSize) {
666 : // TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size
667 : // fields (external pointers, doubles and BigInt data) are only kTaggedSize
668 : // aligned so we have to use unaligned pointer friendly way of accessing
669 : // them in order to avoid undefined behavior in C++ code.
670 : result = ReadUnalignedValue<ElementType>(reinterpret_cast<Address>(ptr) +
671 : index * sizeof(ElementType));
672 : } else {
673 445042 : result = ptr[index];
674 : }
675 : TSAN_ANNOTATE_IGNORE_READS_END;
676 : return result;
677 : }
678 :
679 : template <class Traits>
680 7246554 : void FixedTypedArray<Traits>::set(int index, ElementType value) {
681 : // TODO(bmeurer, v8:4153): Solve this differently.
682 : // CHECK((index < this->length()));
683 7246554 : CHECK_GE(index, 0);
684 : // See the comment in FixedTypedArray<Traits>::get_scalar.
685 : auto* ptr = reinterpret_cast<ElementType*>(DataPtr());
686 : TSAN_ANNOTATE_IGNORE_WRITES_BEGIN;
687 : if (COMPRESS_POINTERS_BOOL && alignof(ElementType) > kTaggedSize) {
688 : // TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size
689 : // fields (external pointers, doubles and BigInt data) are only kTaggedSize
690 : // aligned so we have to use unaligned pointer friendly way of accessing
691 : // them in order to avoid undefined behavior in C++ code.
692 : WriteUnalignedValue<ElementType>(
693 : reinterpret_cast<Address>(ptr) + index * sizeof(ElementType), value);
694 : } else {
695 7246554 : ptr[index] = value;
696 : }
697 : TSAN_ANNOTATE_IGNORE_WRITES_END;
698 7246554 : }
699 :
700 : template <class Traits>
701 : typename Traits::ElementType FixedTypedArray<Traits>::from(int value) {
702 4100418 : return static_cast<ElementType>(value);
703 : }
704 :
705 : template <>
706 : inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(int value) {
707 25710 : if (value < 0) return 0;
708 25845 : if (value > 0xFF) return 0xFF;
709 25431 : return static_cast<uint8_t>(value);
710 : }
711 :
712 : template <>
713 0 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(int value) {
714 0 : UNREACHABLE();
715 : }
716 :
717 : template <>
718 0 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(int value) {
719 0 : UNREACHABLE();
720 : }
721 :
722 : template <class Traits>
723 : typename Traits::ElementType FixedTypedArray<Traits>::from(uint32_t value) {
724 918 : return static_cast<ElementType>(value);
725 : }
726 :
727 : template <>
728 : inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(uint32_t value) {
729 : // We need this special case for Uint32 -> Uint8Clamped, because the highest
730 : // Uint32 values will be negative as an int, clamping to 0, rather than 255.
731 198 : if (value > 0xFF) return 0xFF;
732 117 : return static_cast<uint8_t>(value);
733 : }
734 :
735 : template <>
736 0 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(uint32_t value) {
737 0 : UNREACHABLE();
738 : }
739 :
740 : template <>
741 0 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(uint32_t value) {
742 0 : UNREACHABLE();
743 : }
744 :
745 : template <class Traits>
746 : typename Traits::ElementType FixedTypedArray<Traits>::from(double value) {
747 355257 : return static_cast<ElementType>(DoubleToInt32(value));
748 : }
749 :
750 : template <>
751 : inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(double value) {
752 : // Handle NaNs and less than zero values which clamp to zero.
753 93853 : if (!(value > 0)) return 0;
754 92514 : if (value > 0xFF) return 0xFF;
755 91785 : return static_cast<uint8_t>(lrint(value));
756 : }
757 :
758 : template <>
759 0 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(double value) {
760 0 : UNREACHABLE();
761 : }
762 :
763 : template <>
764 0 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(double value) {
765 0 : UNREACHABLE();
766 : }
767 :
768 : template <>
769 : inline float FixedTypedArray<Float32ArrayTraits>::from(double value) {
770 : using limits = std::numeric_limits<float>;
771 134458 : if (value > limits::max()) return limits::infinity();
772 134358 : if (value < limits::lowest()) return -limits::infinity();
773 134304 : return static_cast<float>(value);
774 : }
775 :
776 : template <>
777 : inline double FixedTypedArray<Float64ArrayTraits>::from(double value) {
778 : return value;
779 : }
780 :
781 : template <class Traits>
782 0 : typename Traits::ElementType FixedTypedArray<Traits>::from(int64_t value) {
783 0 : UNREACHABLE();
784 : }
785 :
786 : template <class Traits>
787 0 : typename Traits::ElementType FixedTypedArray<Traits>::from(uint64_t value) {
788 0 : UNREACHABLE();
789 : }
790 :
791 : template <>
792 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(int64_t value) {
793 : return value;
794 : }
795 :
796 : template <>
797 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(uint64_t value) {
798 : return value;
799 : }
800 :
801 : template <>
802 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(int64_t value) {
803 0 : return static_cast<uint64_t>(value);
804 : }
805 :
806 : template <>
807 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(uint64_t value) {
808 0 : return static_cast<int64_t>(value);
809 : }
810 :
811 : template <class Traits>
812 504 : typename Traits::ElementType FixedTypedArray<Traits>::FromHandle(
813 : Handle<Object> value, bool* lossless) {
814 3878 : if (value->IsSmi()) {
815 : return from(Smi::ToInt(*value));
816 : }
817 : DCHECK(value->IsHeapNumber());
818 : return from(HeapNumber::cast(*value)->value());
819 : }
820 :
821 : template <>
822 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::FromHandle(
823 : Handle<Object> value, bool* lossless) {
824 : DCHECK(value->IsBigInt());
825 252 : return BigInt::cast(*value)->AsInt64(lossless);
826 : }
827 :
828 : template <>
829 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::FromHandle(
830 : Handle<Object> value, bool* lossless) {
831 : DCHECK(value->IsBigInt());
832 252 : return BigInt::cast(*value)->AsUint64(lossless);
833 : }
834 :
835 : template <class Traits>
836 231239 : Handle<Object> FixedTypedArray<Traits>::get(Isolate* isolate,
837 : FixedTypedArray<Traits> array,
838 : int index) {
839 637491 : return Traits::ToHandle(isolate, array->get_scalar(index));
840 : }
841 :
842 : template <class Traits>
843 3187559 : void FixedTypedArray<Traits>::SetValue(uint32_t index, Object value) {
844 : ElementType cast_value = Traits::defaultValue();
845 3187559 : if (value->IsSmi()) {
846 : int int_value = Smi::ToInt(value);
847 : cast_value = from(int_value);
848 2930159 : } else if (value->IsHeapNumber()) {
849 : double double_value = HeapNumber::cast(value)->value();
850 : cast_value = from(double_value);
851 : } else {
852 : // Clamp undefined to the default value. All other types have been
853 : // converted to a number type further up in the call chain.
854 : DCHECK(value->IsUndefined());
855 : }
856 3187559 : set(index, cast_value);
857 3187559 : }
858 :
859 : template <>
860 679 : inline void FixedTypedArray<BigInt64ArrayTraits>::SetValue(uint32_t index,
861 : Object value) {
862 : DCHECK(value->IsBigInt());
863 679 : set(index, BigInt::cast(value)->AsInt64());
864 679 : }
865 :
866 : template <>
867 450 : inline void FixedTypedArray<BigUint64ArrayTraits>::SetValue(uint32_t index,
868 : Object value) {
869 : DCHECK(value->IsBigInt());
870 450 : set(index, BigInt::cast(value)->AsUint64());
871 450 : }
872 :
873 86810 : Handle<Object> Uint8ArrayTraits::ToHandle(Isolate* isolate, uint8_t scalar) {
874 86810 : return handle(Smi::FromInt(scalar), isolate);
875 : }
876 :
877 2827 : Handle<Object> Uint8ClampedArrayTraits::ToHandle(Isolate* isolate,
878 : uint8_t scalar) {
879 2827 : return handle(Smi::FromInt(scalar), isolate);
880 : }
881 :
882 4825 : Handle<Object> Int8ArrayTraits::ToHandle(Isolate* isolate, int8_t scalar) {
883 4825 : return handle(Smi::FromInt(scalar), isolate);
884 : }
885 :
886 76252 : Handle<Object> Uint16ArrayTraits::ToHandle(Isolate* isolate, uint16_t scalar) {
887 76252 : return handle(Smi::FromInt(scalar), isolate);
888 : }
889 :
890 4299 : Handle<Object> Int16ArrayTraits::ToHandle(Isolate* isolate, int16_t scalar) {
891 4299 : return handle(Smi::FromInt(scalar), isolate);
892 : }
893 :
894 : Handle<Object> Uint32ArrayTraits::ToHandle(Isolate* isolate, uint32_t scalar) {
895 75807 : return isolate->factory()->NewNumberFromUint(scalar);
896 : }
897 :
898 : Handle<Object> Int32ArrayTraits::ToHandle(Isolate* isolate, int32_t scalar) {
899 4959 : return isolate->factory()->NewNumberFromInt(scalar);
900 : }
901 :
902 : Handle<Object> Float32ArrayTraits::ToHandle(Isolate* isolate, float scalar) {
903 75443 : return isolate->factory()->NewNumber(scalar);
904 : }
905 :
906 : Handle<Object> Float64ArrayTraits::ToHandle(Isolate* isolate, double scalar) {
907 74949 : return isolate->factory()->NewNumber(scalar);
908 : }
909 :
910 : Handle<Object> BigInt64ArrayTraits::ToHandle(Isolate* isolate, int64_t scalar) {
911 45 : return BigInt::FromInt64(isolate, scalar);
912 : }
913 :
914 : Handle<Object> BigUint64ArrayTraits::ToHandle(Isolate* isolate,
915 : uint64_t scalar) {
916 36 : return BigInt::FromUint64(isolate, scalar);
917 : }
918 :
919 : // static
920 : template <class Traits>
921 : STATIC_CONST_MEMBER_DEFINITION const InstanceType
922 : FixedTypedArray<Traits>::kInstanceType;
923 :
924 : template <class Traits>
925 809096 : FixedTypedArray<Traits>::FixedTypedArray(Address ptr)
926 : : FixedTypedArrayBase(ptr) {
927 : DCHECK(IsHeapObject() && map()->instance_type() == Traits::kInstanceType);
928 809096 : }
929 :
930 : template <class Traits>
931 : FixedTypedArray<Traits> FixedTypedArray<Traits>::cast(Object object) {
932 809094 : return FixedTypedArray<Traits>(object.ptr());
933 : }
934 :
935 : int TemplateList::length() const {
936 : return Smi::ToInt(FixedArray::cast(*this)->get(kLengthIndex));
937 : }
938 :
939 : Object TemplateList::get(int index) const {
940 61974 : return FixedArray::cast(*this)->get(kFirstElementIndex + index);
941 : }
942 :
943 : void TemplateList::set(int index, Object value) {
944 151 : FixedArray::cast(*this)->set(kFirstElementIndex + index, value);
945 : }
946 :
947 : } // namespace internal
948 : } // namespace v8
949 :
950 : #include "src/objects/object-macros-undef.h"
951 :
952 : #endif // V8_OBJECTS_FIXED_ARRAY_INL_H_
|