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/heap-number-inl.h"
17 : #include "src/objects/map.h"
18 : #include "src/objects/maybe-object-inl.h"
19 : #include "src/objects/oddball.h"
20 : #include "src/objects/slots.h"
21 : #include "src/roots-inl.h"
22 :
23 : // Has to be the last include (doesn't have include guards):
24 : #include "src/objects/object-macros.h"
25 :
26 : namespace v8 {
27 : namespace internal {
28 :
29 777468541 : OBJECT_CONSTRUCTORS_IMPL(FixedArrayBase, HeapObject)
30 1096788346 : OBJECT_CONSTRUCTORS_IMPL(FixedArray, FixedArrayBase)
31 54855648 : OBJECT_CONSTRUCTORS_IMPL(FixedDoubleArray, FixedArrayBase)
32 82800095 : OBJECT_CONSTRUCTORS_IMPL(FixedTypedArrayBase, FixedArrayBase)
33 9376 : OBJECT_CONSTRUCTORS_IMPL(ArrayList, FixedArray)
34 137913192 : OBJECT_CONSTRUCTORS_IMPL(ByteArray, FixedArrayBase)
35 17152032 : OBJECT_CONSTRUCTORS_IMPL(TemplateList, FixedArray)
36 45025677 : OBJECT_CONSTRUCTORS_IMPL(WeakFixedArray, HeapObject)
37 19371956 : OBJECT_CONSTRUCTORS_IMPL(WeakArrayList, HeapObject)
38 :
39 5824 : FixedArrayBase::FixedArrayBase(Address ptr, AllowInlineSmiStorage allow_smi)
40 5824 : : HeapObject(ptr, allow_smi) {
41 : SLOW_DCHECK(
42 : (allow_smi == AllowInlineSmiStorage::kAllowBeingASmi && IsSmi()) ||
43 : IsFixedArrayBase());
44 5824 : }
45 :
46 5824 : ByteArray::ByteArray(Address ptr, AllowInlineSmiStorage allow_smi)
47 5824 : : FixedArrayBase(ptr, allow_smi) {
48 : SLOW_DCHECK(
49 : (allow_smi == AllowInlineSmiStorage::kAllowBeingASmi && IsSmi()) ||
50 : IsByteArray());
51 5824 : }
52 :
53 : NEVER_READ_ONLY_SPACE_IMPL(WeakArrayList)
54 :
55 4688 : CAST_ACCESSOR(ArrayList)
56 68982303 : CAST_ACCESSOR(ByteArray)
57 548164683 : CAST_ACCESSOR(FixedArray)
58 388162586 : CAST_ACCESSOR(FixedArrayBase)
59 27426981 : CAST_ACCESSOR(FixedDoubleArray)
60 41404044 : CAST_ACCESSOR(FixedTypedArrayBase)
61 8576016 : CAST_ACCESSOR(TemplateList)
62 22514050 : CAST_ACCESSOR(WeakFixedArray)
63 9686780 : CAST_ACCESSOR(WeakArrayList)
64 :
65 1833344595 : SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
66 323865369 : SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
67 159427952 : SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
68 34569358 : SYNCHRONIZED_SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
69 :
70 30371918 : SMI_ACCESSORS(WeakArrayList, capacity, kCapacityOffset)
71 11698551 : SYNCHRONIZED_SMI_ACCESSORS(WeakArrayList, capacity, kCapacityOffset)
72 112623239 : SMI_ACCESSORS(WeakArrayList, length, kLengthOffset)
73 :
74 : Object FixedArrayBase::unchecked_synchronized_length() const {
75 9055746 : return ACQUIRE_READ_FIELD(*this, kLengthOffset);
76 : }
77 :
78 47417632 : ACCESSORS(FixedTypedArrayBase, base_pointer, Object, kBasePointerOffset)
79 :
80 : ObjectSlot FixedArray::GetFirstElementAddress() {
81 : return RawField(OffsetOfElementAt(0));
82 : }
83 :
84 : bool FixedArray::ContainsOnlySmisOrHoles() {
85 : Object the_hole = GetReadOnlyRoots().the_hole_value();
86 : ObjectSlot current = GetFirstElementAddress();
87 : for (int i = 0; i < length(); ++i, ++current) {
88 : Object candidate = *current;
89 : if (!candidate->IsSmi() && candidate != the_hole) return false;
90 : }
91 : return true;
92 : }
93 :
94 465570 : Object FixedArray::get(int index) const {
95 : DCHECK(index >= 0 && index < this->length());
96 6726582493 : return RELAXED_READ_FIELD(*this, kHeaderSize + index * kTaggedSize);
97 : }
98 :
99 16447426 : Handle<Object> FixedArray::get(FixedArray array, int index, Isolate* isolate) {
100 16447426 : return handle(array->get(index), isolate);
101 : }
102 :
103 : template <class T>
104 4560062 : MaybeHandle<T> FixedArray::GetValue(Isolate* isolate, int index) const {
105 4560062 : Object obj = get(index);
106 4560062 : if (obj->IsUndefined(isolate)) return MaybeHandle<T>();
107 845141 : return Handle<T>(T::cast(obj), isolate);
108 : }
109 :
110 : template <class T>
111 261319 : Handle<T> FixedArray::GetValueChecked(Isolate* isolate, int index) const {
112 261319 : Object obj = get(index);
113 261320 : CHECK(!obj->IsUndefined(isolate));
114 261320 : return Handle<T>(T::cast(obj), isolate);
115 : }
116 :
117 309015670 : bool FixedArray::is_the_hole(Isolate* isolate, int index) {
118 618031340 : return get(index)->IsTheHole(isolate);
119 : }
120 :
121 664 : void FixedArray::set(int index, Smi value) {
122 : DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
123 : DCHECK_LT(index, this->length());
124 : DCHECK(Object(value).IsSmi());
125 145494988 : int offset = kHeaderSize + index * kTaggedSize;
126 248642951 : RELAXED_WRITE_FIELD(*this, offset, value);
127 664 : }
128 :
129 468959918 : void FixedArray::set(int index, Object value) {
130 : DCHECK_NE(GetReadOnlyRoots().fixed_cow_array_map(), map());
131 : DCHECK(IsFixedArray());
132 : DCHECK_GE(index, 0);
133 : DCHECK_LT(index, this->length());
134 468959918 : int offset = kHeaderSize + index * kTaggedSize;
135 468959918 : RELAXED_WRITE_FIELD(*this, offset, value);
136 937919869 : WRITE_BARRIER(*this, offset, value);
137 468959934 : }
138 :
139 1268032792 : void FixedArray::set(int index, Object value, WriteBarrierMode mode) {
140 : DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
141 : DCHECK_GE(index, 0);
142 : DCHECK_LT(index, this->length());
143 1268032792 : int offset = kHeaderSize + index * kTaggedSize;
144 1268032792 : RELAXED_WRITE_FIELD(*this, offset, value);
145 2766081673 : CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode);
146 1268032859 : }
147 :
148 : void FixedArray::NoWriteBarrierSet(FixedArray array, int index, Object value) {
149 : DCHECK_NE(array->map(), array->GetReadOnlyRoots().fixed_cow_array_map());
150 : DCHECK_GE(index, 0);
151 : DCHECK_LT(index, array->length());
152 : DCHECK(!ObjectInYoungGeneration(value));
153 353800193 : RELAXED_WRITE_FIELD(array, kHeaderSize + index * kTaggedSize, value);
154 : }
155 :
156 332976128 : void FixedArray::set_undefined(int index) {
157 332976128 : set_undefined(GetReadOnlyRoots(), index);
158 332976128 : }
159 :
160 1476 : void FixedArray::set_undefined(Isolate* isolate, int index) {
161 1476 : set_undefined(ReadOnlyRoots(isolate), index);
162 1476 : }
163 :
164 332977604 : void FixedArray::set_undefined(ReadOnlyRoots ro_roots, int index) {
165 : FixedArray::NoWriteBarrierSet(*this, index, ro_roots.undefined_value());
166 332977604 : }
167 :
168 529 : void FixedArray::set_null(int index) { set_null(GetReadOnlyRoots(), index); }
169 :
170 : void FixedArray::set_null(Isolate* isolate, int index) {
171 : set_null(ReadOnlyRoots(isolate), index);
172 : }
173 :
174 529 : void FixedArray::set_null(ReadOnlyRoots ro_roots, int index) {
175 : FixedArray::NoWriteBarrierSet(*this, index, ro_roots.null_value());
176 529 : }
177 :
178 11509017 : void FixedArray::set_the_hole(int index) {
179 11509017 : set_the_hole(GetReadOnlyRoots(), index);
180 11509017 : }
181 :
182 8121392 : void FixedArray::set_the_hole(Isolate* isolate, int index) {
183 8121392 : set_the_hole(ReadOnlyRoots(isolate), index);
184 8121392 : }
185 :
186 19630409 : void FixedArray::set_the_hole(ReadOnlyRoots ro_roots, int index) {
187 : FixedArray::NoWriteBarrierSet(*this, index, ro_roots.the_hole_value());
188 19630409 : }
189 :
190 : void FixedArray::FillWithHoles(int from, int to) {
191 11459309 : for (int i = from; i < to; i++) {
192 11459309 : set_the_hole(i);
193 : }
194 : }
195 :
196 0 : ObjectSlot FixedArray::data_start() {
197 0 : return RawField(OffsetOfElementAt(0));
198 : }
199 :
200 147320 : ObjectSlot FixedArray::RawFieldOfElementAt(int index) {
201 147320 : return RawField(OffsetOfElementAt(index));
202 : }
203 :
204 : void FixedArray::MoveElements(Heap* heap, int dst_index, int src_index, int len,
205 : WriteBarrierMode mode) {
206 : DisallowHeapAllocation no_gc;
207 1426 : heap->MoveElements(*this, dst_index, src_index, len, mode);
208 : }
209 :
210 : // Perform a binary search in a fixed array.
211 : template <SearchMode search_mode, typename T>
212 22271166 : int BinarySearch(T* array, Name name, int valid_entries,
213 : int* out_insertion_index) {
214 : DCHECK(search_mode == ALL_ENTRIES || out_insertion_index == nullptr);
215 : int low = 0;
216 22271166 : int high = array->number_of_entries() - 1;
217 : uint32_t hash = name->hash_field();
218 : int limit = high;
219 :
220 : DCHECK(low <= high);
221 :
222 141357880 : while (low != high) {
223 96815594 : int mid = low + (high - low) / 2;
224 69626947 : Name mid_name = array->GetSortedKey(mid);
225 : uint32_t mid_hash = mid_name->hash_field();
226 :
227 96815548 : if (mid_hash >= hash) {
228 : high = mid;
229 : } else {
230 41716538 : low = mid + 1;
231 : }
232 : }
233 :
234 0 : for (; low <= limit; ++low) {
235 : int sort_index = array->GetSortedKeyIndex(low);
236 22271109 : Name entry = array->GetKey(sort_index);
237 : uint32_t current_hash = entry->hash_field();
238 22271106 : if (current_hash != hash) {
239 120843 : if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
240 60589 : *out_insertion_index = sort_index + (current_hash > hash ? 0 : 1);
241 : }
242 : return T::kNotFound;
243 : }
244 10956073 : if (entry == name) {
245 3880668 : if (search_mode == ALL_ENTRIES || sort_index < valid_entries) {
246 3709673 : return sort_index;
247 : }
248 : return T::kNotFound;
249 : }
250 : }
251 :
252 0 : if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
253 0 : *out_insertion_index = limit + 1;
254 : }
255 : return T::kNotFound;
256 : }
257 :
258 : // Perform a linear search in this fixed array. len is the number of entry
259 : // indices that are valid.
260 : template <SearchMode search_mode, typename T>
261 12937772 : int LinearSearch(T* array, Name name, int valid_entries,
262 : int* out_insertion_index) {
263 12937772 : if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
264 : uint32_t hash = name->hash_field();
265 : int len = array->number_of_entries();
266 338265 : for (int number = 0; number < len; number++) {
267 : int sorted_index = array->GetSortedKeyIndex(number);
268 289453 : Name entry = array->GetKey(sorted_index);
269 : uint32_t current_hash = entry->hash_field();
270 289461 : if (current_hash > hash) {
271 105403 : *out_insertion_index = sorted_index;
272 105403 : return T::kNotFound;
273 : }
274 184058 : if (entry == name) return sorted_index;
275 : }
276 48812 : *out_insertion_index = len;
277 48812 : return T::kNotFound;
278 : } else {
279 : DCHECK_LE(valid_entries, array->number_of_entries());
280 : DCHECK_NULL(out_insertion_index); // Not supported here.
281 61543274 : for (int number = 0; number < valid_entries; number++) {
282 172713913 : if (array->GetKey(number) == name) return number;
283 : }
284 : return T::kNotFound;
285 : }
286 : }
287 :
288 : template <SearchMode search_mode, typename T>
289 60830078 : int Search(T* array, Name name, int valid_entries, int* out_insertion_index) {
290 : SLOW_DCHECK(array->IsSortedNoDuplicates());
291 :
292 60830078 : if (valid_entries == 0) {
293 236632 : if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
294 226349 : *out_insertion_index = 0;
295 : }
296 : return T::kNotFound;
297 : }
298 :
299 : // Fast case: do linear search for small arrays.
300 : const int kMaxElementsForLinearSearch = 8;
301 60593474 : if (valid_entries <= kMaxElementsForLinearSearch) {
302 : return LinearSearch<search_mode>(array, name, valid_entries,
303 38322357 : out_insertion_index);
304 : }
305 :
306 : // Slow case: perform binary search.
307 : return BinarySearch<search_mode>(array, name, valid_entries,
308 22271117 : out_insertion_index);
309 : }
310 :
311 532 : double FixedDoubleArray::get_scalar(int index) {
312 : DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
313 : map() != GetReadOnlyRoots().fixed_array_map());
314 : DCHECK(index >= 0 && index < this->length());
315 : DCHECK(!is_the_hole(index));
316 7491475 : return READ_DOUBLE_FIELD(*this, kHeaderSize + index * kDoubleSize);
317 : }
318 :
319 : uint64_t FixedDoubleArray::get_representation(int index) {
320 : DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
321 : map() != GetReadOnlyRoots().fixed_array_map());
322 : DCHECK(index >= 0 && index < this->length());
323 37317906 : int offset = kHeaderSize + index * kDoubleSize;
324 37317906 : return READ_UINT64_FIELD(*this, offset);
325 : }
326 :
327 8471553 : Handle<Object> FixedDoubleArray::get(FixedDoubleArray array, int index,
328 : Isolate* isolate) {
329 8471553 : if (array->is_the_hole(index)) {
330 1097502 : return ReadOnlyRoots(isolate).the_hole_value_handle();
331 : } else {
332 7374051 : return isolate->factory()->NewNumber(array->get_scalar(index));
333 : }
334 : }
335 :
336 11985711 : void FixedDoubleArray::set(int index, double value) {
337 : DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
338 : map() != GetReadOnlyRoots().fixed_array_map());
339 11985711 : int offset = kHeaderSize + index * kDoubleSize;
340 11985711 : if (std::isnan(value)) {
341 2146 : WRITE_DOUBLE_FIELD(*this, offset, std::numeric_limits<double>::quiet_NaN());
342 : } else {
343 11983565 : WRITE_DOUBLE_FIELD(*this, offset, value);
344 : }
345 : DCHECK(!is_the_hole(index));
346 11985711 : }
347 :
348 : void FixedDoubleArray::set_the_hole(Isolate* isolate, int index) {
349 : set_the_hole(index);
350 : }
351 :
352 : void FixedDoubleArray::set_the_hole(int index) {
353 : DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
354 : map() != GetReadOnlyRoots().fixed_array_map());
355 45683927 : int offset = kHeaderSize + index * kDoubleSize;
356 45683927 : WRITE_UINT64_FIELD(*this, offset, kHoleNanInt64);
357 : }
358 :
359 : bool FixedDoubleArray::is_the_hole(Isolate* isolate, int index) {
360 : return is_the_hole(index);
361 : }
362 :
363 : bool FixedDoubleArray::is_the_hole(int index) {
364 0 : return get_representation(index) == kHoleNanInt64;
365 : }
366 :
367 16 : void FixedDoubleArray::MoveElements(Heap* heap, int dst_index, int src_index,
368 : int len, WriteBarrierMode mode) {
369 : DCHECK_EQ(SKIP_WRITE_BARRIER, mode);
370 : double* data_start =
371 16 : reinterpret_cast<double*>(FIELD_ADDR(*this, kHeaderSize));
372 16 : MemMove(data_start + dst_index, data_start + src_index, len * kDoubleSize);
373 16 : }
374 :
375 : void FixedDoubleArray::FillWithHoles(int from, int to) {
376 381510 : for (int i = from; i < to; i++) {
377 : set_the_hole(i);
378 : }
379 : }
380 :
381 237454152 : MaybeObject WeakFixedArray::Get(int index) const {
382 : DCHECK(index >= 0 && index < this->length());
383 474908304 : return RELAXED_READ_WEAK_FIELD(*this, OffsetOfElementAt(index));
384 : }
385 :
386 33355549 : void WeakFixedArray::Set(int index, MaybeObject value) {
387 : DCHECK_GE(index, 0);
388 : DCHECK_LT(index, length());
389 : int offset = OffsetOfElementAt(index);
390 33355549 : RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
391 66711105 : WEAK_WRITE_BARRIER(*this, offset, value);
392 33355560 : }
393 :
394 2332684 : void WeakFixedArray::Set(int index, MaybeObject value, WriteBarrierMode mode) {
395 : DCHECK_GE(index, 0);
396 : DCHECK_LT(index, length());
397 : int offset = OffsetOfElementAt(index);
398 2332684 : RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
399 6998052 : CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
400 2332684 : }
401 :
402 : MaybeObjectSlot WeakFixedArray::data_start() {
403 : return RawMaybeWeakField(kHeaderSize);
404 : }
405 :
406 : MaybeObjectSlot WeakFixedArray::RawFieldOfElementAt(int index) {
407 : return RawMaybeWeakField(OffsetOfElementAt(index));
408 : }
409 :
410 30654688 : MaybeObject WeakArrayList::Get(int index) const {
411 : DCHECK(index >= 0 && index < this->capacity());
412 61309376 : return RELAXED_READ_WEAK_FIELD(*this, OffsetOfElementAt(index));
413 : }
414 :
415 33188587 : void WeakArrayList::Set(int index, MaybeObject value, WriteBarrierMode mode) {
416 : DCHECK_GE(index, 0);
417 : DCHECK_LT(index, this->capacity());
418 : int offset = OffsetOfElementAt(index);
419 33188587 : RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
420 77988898 : CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
421 33188590 : }
422 :
423 : MaybeObjectSlot WeakArrayList::data_start() {
424 : return RawMaybeWeakField(kHeaderSize);
425 : }
426 :
427 5200804 : HeapObject WeakArrayList::Iterator::Next() {
428 5200804 : if (!array_.is_null()) {
429 10425546 : while (index_ < array_->length()) {
430 5208616 : MaybeObject item = array_->Get(index_++);
431 : DCHECK(item->IsWeakOrCleared());
432 10405213 : if (!item->IsCleared()) return item->GetHeapObjectAssumeWeak();
433 : }
434 4157 : array_ = WeakArrayList();
435 : }
436 4207 : return HeapObject();
437 : }
438 :
439 19355 : int ArrayList::Length() const {
440 19355 : if (FixedArray::cast(*this)->length() == 0) return 0;
441 18923 : return Smi::ToInt(FixedArray::cast(*this)->get(kLengthIndex));
442 : }
443 :
444 2318 : void ArrayList::SetLength(int length) {
445 2318 : return FixedArray::cast(*this)->set(kLengthIndex, Smi::FromInt(length));
446 : }
447 :
448 16204 : Object ArrayList::Get(int index) const {
449 32408 : return FixedArray::cast(*this)->get(kFirstIndex + index);
450 : }
451 :
452 : ObjectSlot ArrayList::Slot(int index) {
453 : return RawField(OffsetOfElementAt(kFirstIndex + index));
454 : }
455 :
456 1944 : void ArrayList::Set(int index, Object obj, WriteBarrierMode mode) {
457 3888 : FixedArray::cast(*this)->set(kFirstIndex + index, obj, mode);
458 1944 : }
459 :
460 5 : void ArrayList::Clear(int index, Object undefined) {
461 : DCHECK(undefined->IsUndefined());
462 : FixedArray::cast(*this)->set(kFirstIndex + index, undefined,
463 10 : SKIP_WRITE_BARRIER);
464 5 : }
465 :
466 34076900 : int ByteArray::Size() { return RoundUp(length() + kHeaderSize, kTaggedSize); }
467 :
468 : byte ByteArray::get(int index) const {
469 : DCHECK(index >= 0 && index < this->length());
470 60974188 : return READ_BYTE_FIELD(*this, kHeaderSize + index * kCharSize);
471 : }
472 :
473 : void ByteArray::set(int index, byte value) {
474 : DCHECK(index >= 0 && index < this->length());
475 11529471 : WRITE_BYTE_FIELD(*this, kHeaderSize + index * kCharSize, value);
476 : }
477 :
478 : void ByteArray::copy_in(int index, const byte* buffer, int length) {
479 : DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
480 : index + length <= this->length());
481 129761 : Address dst_addr = FIELD_ADDR(*this, kHeaderSize + index * kCharSize);
482 192934 : memcpy(reinterpret_cast<void*>(dst_addr), buffer, length);
483 : }
484 :
485 : void ByteArray::copy_out(int index, byte* buffer, int length) {
486 : DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
487 : index + length <= this->length());
488 261747581 : Address src_addr = FIELD_ADDR(*this, kHeaderSize + index * kCharSize);
489 261747581 : memcpy(buffer, reinterpret_cast<void*>(src_addr), length);
490 : }
491 :
492 : int ByteArray::get_int(int index) const {
493 : DCHECK(index >= 0 && index < this->length() / kIntSize);
494 2264 : return READ_INT_FIELD(*this, kHeaderSize + index * kIntSize);
495 : }
496 :
497 : void ByteArray::set_int(int index, int value) {
498 : DCHECK(index >= 0 && index < this->length() / kIntSize);
499 1344 : WRITE_INT_FIELD(*this, kHeaderSize + index * kIntSize, value);
500 : }
501 :
502 1016188 : uint32_t ByteArray::get_uint32(int index) const {
503 : DCHECK(index >= 0 && index < this->length() / kUInt32Size);
504 1016188 : return READ_UINT32_FIELD(*this, kHeaderSize + index * kUInt32Size);
505 : }
506 :
507 149482 : void ByteArray::set_uint32(int index, uint32_t value) {
508 : DCHECK(index >= 0 && index < this->length() / kUInt32Size);
509 149482 : WRITE_UINT32_FIELD(*this, kHeaderSize + index * kUInt32Size, value);
510 149482 : }
511 :
512 7124513 : void ByteArray::clear_padding() {
513 7124516 : int data_size = length() + kHeaderSize;
514 14249035 : memset(reinterpret_cast<void*>(address() + data_size), 0, Size() - data_size);
515 7124519 : }
516 :
517 : ByteArray ByteArray::FromDataStartAddress(Address address) {
518 : DCHECK_TAG_ALIGNED(address);
519 : return ByteArray::cast(Object(address - kHeaderSize + kHeapObjectTag));
520 : }
521 :
522 862 : int ByteArray::DataSize() const { return RoundUp(length(), kTaggedSize); }
523 :
524 : int ByteArray::ByteArraySize() { return SizeFor(this->length()); }
525 :
526 388 : byte* ByteArray::GetDataStartAddress() {
527 488014412 : return reinterpret_cast<byte*>(address() + kHeaderSize);
528 : }
529 :
530 213750612 : byte* ByteArray::GetDataEndAddress() {
531 213523948 : return GetDataStartAddress() + length();
532 : }
533 :
534 : template <class T>
535 1040884 : PodArray<T>::PodArray(Address ptr) : ByteArray(ptr) {}
536 :
537 : template <class T>
538 : PodArray<T> PodArray<T>::cast(Object object) {
539 520442 : return PodArray<T>(object.ptr());
540 : }
541 :
542 : // static
543 : template <class T>
544 13374 : Handle<PodArray<T>> PodArray<T>::New(Isolate* isolate, int length,
545 : PretenureFlag pretenure) {
546 : return Handle<PodArray<T>>::cast(
547 13470 : isolate->factory()->NewByteArray(length * sizeof(T), pretenure));
548 : }
549 :
550 : template <class T>
551 : int PodArray<T>::length() const {
552 0 : return ByteArray::length() / sizeof(T);
553 : }
554 :
555 : void* FixedTypedArrayBase::external_pointer() const {
556 5532968 : intptr_t ptr = READ_INTPTR_FIELD(*this, kExternalPointerOffset);
557 2384 : return reinterpret_cast<void*>(ptr);
558 : }
559 :
560 616 : void FixedTypedArrayBase::set_external_pointer(void* value,
561 : WriteBarrierMode mode) {
562 11973 : intptr_t ptr = reinterpret_cast<intptr_t>(value);
563 11978 : WRITE_INTPTR_FIELD(*this, kExternalPointerOffset, ptr);
564 616 : }
565 :
566 342 : void* FixedTypedArrayBase::DataPtr() {
567 : return reinterpret_cast<void*>(
568 5530826 : base_pointer()->ptr() + reinterpret_cast<intptr_t>(external_pointer()));
569 : }
570 :
571 335602 : int FixedTypedArrayBase::ElementSize(InstanceType type) {
572 : int element_size;
573 335602 : switch (type) {
574 : #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
575 : case FIXED_##TYPE##_ARRAY_TYPE: \
576 : element_size = sizeof(ctype); \
577 : break;
578 :
579 24845 : TYPED_ARRAYS(TYPED_ARRAY_CASE)
580 : #undef TYPED_ARRAY_CASE
581 : default:
582 0 : UNREACHABLE();
583 : }
584 335602 : return element_size;
585 : }
586 :
587 774343 : int FixedTypedArrayBase::DataSize(InstanceType type) const {
588 774343 : if (base_pointer() == Smi::kZero) return 0;
589 335623 : return length() * ElementSize(type);
590 : }
591 :
592 223953 : int FixedTypedArrayBase::DataSize() const {
593 223953 : return DataSize(map()->instance_type());
594 : }
595 :
596 : size_t FixedTypedArrayBase::ByteLength() const {
597 : return static_cast<size_t>(length()) *
598 : static_cast<size_t>(ElementSize(map()->instance_type()));
599 : }
600 :
601 : int FixedTypedArrayBase::size() const {
602 202166 : return OBJECT_POINTER_ALIGN(kDataOffset + DataSize());
603 : }
604 :
605 : int FixedTypedArrayBase::TypedArraySize(InstanceType type) const {
606 550433 : return OBJECT_POINTER_ALIGN(kDataOffset + DataSize(type));
607 : }
608 :
609 : // static
610 : int FixedTypedArrayBase::TypedArraySize(InstanceType type, int length) {
611 : return OBJECT_POINTER_ALIGN(kDataOffset + length * ElementSize(type));
612 : }
613 :
614 : uint8_t Uint8ArrayTraits::defaultValue() { return 0; }
615 :
616 : uint8_t Uint8ClampedArrayTraits::defaultValue() { return 0; }
617 :
618 : int8_t Int8ArrayTraits::defaultValue() { return 0; }
619 :
620 : uint16_t Uint16ArrayTraits::defaultValue() { return 0; }
621 :
622 : int16_t Int16ArrayTraits::defaultValue() { return 0; }
623 :
624 : uint32_t Uint32ArrayTraits::defaultValue() { return 0; }
625 :
626 : int32_t Int32ArrayTraits::defaultValue() { return 0; }
627 :
628 : float Float32ArrayTraits::defaultValue() {
629 : return std::numeric_limits<float>::quiet_NaN();
630 : }
631 :
632 : double Float64ArrayTraits::defaultValue() {
633 : return std::numeric_limits<double>::quiet_NaN();
634 : }
635 :
636 : template <class Traits>
637 : typename Traits::ElementType FixedTypedArray<Traits>::get_scalar(int index) {
638 : DCHECK((index >= 0) && (index < this->length()));
639 : return FixedTypedArray<Traits>::get_scalar_from_data_ptr(DataPtr(), index);
640 : }
641 :
642 : // static
643 : template <class Traits>
644 : typename Traits::ElementType FixedTypedArray<Traits>::get_scalar_from_data_ptr(
645 : void* data_ptr, int index) {
646 : typename Traits::ElementType* ptr = reinterpret_cast<ElementType*>(data_ptr);
647 : // The JavaScript memory model allows for racy reads and writes to a
648 : // SharedArrayBuffer's backing store, which will always be a FixedTypedArray.
649 : // ThreadSanitizer will catch these racy accesses and warn about them, so we
650 : // disable TSAN for these reads and writes using annotations.
651 : //
652 : // We don't use relaxed atomics here, as it is not a requirement of the
653 : // JavaScript memory model to have tear-free reads of overlapping accesses,
654 : // and using relaxed atomics may introduce overhead.
655 : TSAN_ANNOTATE_IGNORE_READS_BEGIN;
656 440131 : auto result = ptr[index];
657 : TSAN_ANNOTATE_IGNORE_READS_END;
658 : return result;
659 : }
660 :
661 : template <class Traits>
662 5083905 : void FixedTypedArray<Traits>::set(int index, ElementType value) {
663 10167810 : CHECK((index >= 0) && (index < this->length()));
664 : // See the comment in FixedTypedArray<Traits>::get_scalar.
665 : auto* ptr = reinterpret_cast<ElementType*>(DataPtr());
666 : TSAN_ANNOTATE_IGNORE_WRITES_BEGIN;
667 5083905 : ptr[index] = value;
668 : TSAN_ANNOTATE_IGNORE_WRITES_END;
669 5083905 : }
670 :
671 : template <class Traits>
672 : typename Traits::ElementType FixedTypedArray<Traits>::from(int value) {
673 2469376 : return static_cast<ElementType>(value);
674 : }
675 :
676 : template <>
677 : inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(int value) {
678 25692 : if (value < 0) return 0;
679 25827 : if (value > 0xFF) return 0xFF;
680 25413 : return static_cast<uint8_t>(value);
681 : }
682 :
683 : template <>
684 0 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(int value) {
685 0 : UNREACHABLE();
686 : }
687 :
688 : template <>
689 0 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(int value) {
690 0 : UNREACHABLE();
691 : }
692 :
693 : template <class Traits>
694 : typename Traits::ElementType FixedTypedArray<Traits>::from(uint32_t value) {
695 1314 : return static_cast<ElementType>(value);
696 : }
697 :
698 : template <>
699 : inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(uint32_t value) {
700 : // We need this special case for Uint32 -> Uint8Clamped, because the highest
701 : // Uint32 values will be negative as an int, clamping to 0, rather than 255.
702 198 : if (value > 0xFF) return 0xFF;
703 117 : return static_cast<uint8_t>(value);
704 : }
705 :
706 : template <>
707 0 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(uint32_t value) {
708 0 : UNREACHABLE();
709 : }
710 :
711 : template <>
712 0 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(uint32_t value) {
713 0 : UNREACHABLE();
714 : }
715 :
716 : template <class Traits>
717 : typename Traits::ElementType FixedTypedArray<Traits>::from(double value) {
718 348222 : return static_cast<ElementType>(DoubleToInt32(value));
719 : }
720 :
721 : template <>
722 : inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(double value) {
723 : // Handle NaNs and less than zero values which clamp to zero.
724 93853 : if (!(value > 0)) return 0;
725 92514 : if (value > 0xFF) return 0xFF;
726 91785 : return static_cast<uint8_t>(lrint(value));
727 : }
728 :
729 : template <>
730 0 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(double value) {
731 0 : UNREACHABLE();
732 : }
733 :
734 : template <>
735 0 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(double value) {
736 0 : UNREACHABLE();
737 : }
738 :
739 : template <>
740 : inline float FixedTypedArray<Float32ArrayTraits>::from(double value) {
741 134449 : return static_cast<float>(value);
742 : }
743 :
744 : template <>
745 : inline double FixedTypedArray<Float64ArrayTraits>::from(double value) {
746 : return value;
747 : }
748 :
749 : template <class Traits>
750 0 : typename Traits::ElementType FixedTypedArray<Traits>::from(int64_t value) {
751 0 : UNREACHABLE();
752 : }
753 :
754 : template <class Traits>
755 0 : typename Traits::ElementType FixedTypedArray<Traits>::from(uint64_t value) {
756 0 : UNREACHABLE();
757 : }
758 :
759 : template <>
760 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(int64_t value) {
761 : return value;
762 : }
763 :
764 : template <>
765 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(uint64_t value) {
766 : return value;
767 : }
768 :
769 : template <>
770 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(int64_t value) {
771 0 : return static_cast<uint64_t>(value);
772 : }
773 :
774 : template <>
775 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(uint64_t value) {
776 0 : return static_cast<int64_t>(value);
777 : }
778 :
779 : template <class Traits>
780 3707 : typename Traits::ElementType FixedTypedArray<Traits>::FromHandle(
781 : Handle<Object> value, bool* lossless) {
782 7414 : if (value->IsSmi()) {
783 6262 : return from(Smi::ToInt(*value));
784 : }
785 : DCHECK(value->IsHeapNumber());
786 : return from(HeapNumber::cast(*value)->value());
787 : }
788 :
789 : template <>
790 252 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::FromHandle(
791 : Handle<Object> value, bool* lossless) {
792 : DCHECK(value->IsBigInt());
793 252 : return BigInt::cast(*value)->AsInt64(lossless);
794 : }
795 :
796 : template <>
797 252 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::FromHandle(
798 : Handle<Object> value, bool* lossless) {
799 : DCHECK(value->IsBigInt());
800 252 : return BigInt::cast(*value)->AsUint64(lossless);
801 : }
802 :
803 : template <class Traits>
804 401341 : Handle<Object> FixedTypedArray<Traits>::get(Isolate* isolate,
805 : FixedTypedArray<Traits> array,
806 : int index) {
807 401341 : return Traits::ToHandle(isolate, array->get_scalar(index));
808 : }
809 :
810 : template <class Traits>
811 2660537 : void FixedTypedArray<Traits>::SetValue(uint32_t index, Object value) {
812 : ElementType cast_value = Traits::defaultValue();
813 2660537 : if (value->IsSmi()) {
814 254675 : int int_value = Smi::ToInt(value);
815 : cast_value = from(int_value);
816 2405862 : } else if (value->IsHeapNumber()) {
817 : double double_value = HeapNumber::cast(value)->value();
818 : cast_value = from(double_value);
819 : } else {
820 : // Clamp undefined to the default value. All other types have been
821 : // converted to a number type further up in the call chain.
822 : DCHECK(value->IsUndefined());
823 : }
824 2660537 : set(index, cast_value);
825 2660537 : }
826 :
827 : template <>
828 675 : inline void FixedTypedArray<BigInt64ArrayTraits>::SetValue(uint32_t index,
829 : Object value) {
830 : DCHECK(value->IsBigInt());
831 675 : set(index, BigInt::cast(value)->AsInt64());
832 675 : }
833 :
834 : template <>
835 450 : inline void FixedTypedArray<BigUint64ArrayTraits>::SetValue(uint32_t index,
836 : Object value) {
837 : DCHECK(value->IsBigInt());
838 450 : set(index, BigInt::cast(value)->AsUint64());
839 450 : }
840 :
841 86576 : Handle<Object> Uint8ArrayTraits::ToHandle(Isolate* isolate, uint8_t scalar) {
842 86576 : return handle(Smi::FromInt(scalar), isolate);
843 : }
844 :
845 2233 : Handle<Object> Uint8ClampedArrayTraits::ToHandle(Isolate* isolate,
846 : uint8_t scalar) {
847 2233 : return handle(Smi::FromInt(scalar), isolate);
848 : }
849 :
850 4338 : Handle<Object> Int8ArrayTraits::ToHandle(Isolate* isolate, int8_t scalar) {
851 4338 : return handle(Smi::FromInt(scalar), isolate);
852 : }
853 :
854 75658 : Handle<Object> Uint16ArrayTraits::ToHandle(Isolate* isolate, uint16_t scalar) {
855 75658 : return handle(Smi::FromInt(scalar), isolate);
856 : }
857 :
858 3685 : Handle<Object> Int16ArrayTraits::ToHandle(Isolate* isolate, int16_t scalar) {
859 3685 : return handle(Smi::FromInt(scalar), isolate);
860 : }
861 :
862 : Handle<Object> Uint32ArrayTraits::ToHandle(Isolate* isolate, uint32_t scalar) {
863 75213 : return isolate->factory()->NewNumberFromUint(scalar);
864 : }
865 :
866 : Handle<Object> Int32ArrayTraits::ToHandle(Isolate* isolate, int32_t scalar) {
867 4353 : return isolate->factory()->NewNumberFromInt(scalar);
868 : }
869 :
870 : Handle<Object> Float32ArrayTraits::ToHandle(Isolate* isolate, float scalar) {
871 74849 : return isolate->factory()->NewNumber(scalar);
872 : }
873 :
874 : Handle<Object> Float64ArrayTraits::ToHandle(Isolate* isolate, double scalar) {
875 74355 : return isolate->factory()->NewNumber(scalar);
876 : }
877 :
878 : Handle<Object> BigInt64ArrayTraits::ToHandle(Isolate* isolate, int64_t scalar) {
879 45 : return BigInt::FromInt64(isolate, scalar);
880 : }
881 :
882 : Handle<Object> BigUint64ArrayTraits::ToHandle(Isolate* isolate,
883 : uint64_t scalar) {
884 36 : return BigInt::FromUint64(isolate, scalar);
885 : }
886 :
887 : // static
888 : template <class Traits>
889 : STATIC_CONST_MEMBER_DEFINITION const InstanceType
890 : FixedTypedArray<Traits>::kInstanceType;
891 :
892 : template <class Traits>
893 1263934 : FixedTypedArray<Traits>::FixedTypedArray(Address ptr)
894 : : FixedTypedArrayBase(ptr) {
895 : DCHECK(IsHeapObject() && map()->instance_type() == Traits::kInstanceType);
896 1263934 : }
897 :
898 : template <class Traits>
899 : FixedTypedArray<Traits> FixedTypedArray<Traits>::cast(Object object) {
900 1263939 : return FixedTypedArray<Traits>(object.ptr());
901 : }
902 :
903 6541875 : int TemplateList::length() const {
904 6541875 : return Smi::ToInt(FixedArray::cast(*this)->get(kLengthIndex));
905 : }
906 :
907 8557661 : Object TemplateList::get(int index) const {
908 17115322 : return FixedArray::cast(*this)->get(kFirstElementIndex + index);
909 : }
910 :
911 151 : void TemplateList::set(int index, Object value) {
912 302 : FixedArray::cast(*this)->set(kFirstElementIndex + index, value);
913 151 : }
914 :
915 : } // namespace internal
916 : } // namespace v8
917 :
918 : #include "src/objects/object-macros-undef.h"
919 :
920 : #endif // V8_OBJECTS_FIXED_ARRAY_INL_H_
|