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/conversions.h"
11 : #include "src/handles-inl.h"
12 : #include "src/heap/heap-write-barrier-inl.h"
13 : #include "src/objects/bigint.h"
14 : #include "src/objects/heap-number-inl.h"
15 : #include "src/objects/map.h"
16 : #include "src/objects/maybe-object-inl.h"
17 : #include "src/objects/oddball.h"
18 : #include "src/objects/slots.h"
19 :
20 : // Has to be the last include (doesn't have include guards):
21 : #include "src/objects/object-macros.h"
22 :
23 : namespace v8 {
24 : namespace internal {
25 :
26 790349948 : OBJECT_CONSTRUCTORS_IMPL(FixedArrayBase, HeapObject)
27 1451789908 : OBJECT_CONSTRUCTORS_IMPL(FixedArray, FixedArrayBase)
28 51532906 : OBJECT_CONSTRUCTORS_IMPL(FixedDoubleArray, FixedArrayBase)
29 76167526 : OBJECT_CONSTRUCTORS_IMPL(FixedTypedArrayBase, FixedArrayBase)
30 11072 : OBJECT_CONSTRUCTORS_IMPL(ArrayList, FixedArray)
31 795739842 : OBJECT_CONSTRUCTORS_IMPL(ByteArray, FixedArrayBase)
32 16866860 : OBJECT_CONSTRUCTORS_IMPL(TemplateList, FixedArray)
33 70058256 : OBJECT_CONSTRUCTORS_IMPL(WeakFixedArray, HeapObject)
34 23982328 : OBJECT_CONSTRUCTORS_IMPL(WeakArrayList, HeapObject)
35 :
36 : FixedArrayBase::FixedArrayBase(Address ptr, AllowInlineSmiStorage allow_smi)
37 : : HeapObject(ptr, allow_smi) {
38 : SLOW_DCHECK(
39 : (allow_smi == AllowInlineSmiStorage::kAllowBeingASmi && IsSmi()) ||
40 : IsFixedArrayBase());
41 : }
42 :
43 : ByteArray::ByteArray(Address ptr, AllowInlineSmiStorage allow_smi)
44 : : FixedArrayBase(ptr, allow_smi) {
45 : SLOW_DCHECK(
46 : (allow_smi == AllowInlineSmiStorage::kAllowBeingASmi && IsSmi()) ||
47 : IsByteArray());
48 : }
49 :
50 : NEVER_READ_ONLY_SPACE_IMPL(WeakArrayList)
51 :
52 5536 : CAST_ACCESSOR(ArrayList)
53 397921062 : CAST_ACCESSOR(ByteArray)
54 725094482 : CAST_ACCESSOR(FixedArray)
55 395174829 : CAST_ACCESSOR(FixedArrayBase)
56 25765545 : CAST_ACCESSOR(FixedDoubleArray)
57 38083876 : CAST_ACCESSOR(FixedTypedArrayBase)
58 8433430 : CAST_ACCESSOR(TemplateList)
59 35029136 : CAST_ACCESSOR(WeakFixedArray)
60 11991162 : CAST_ACCESSOR(WeakArrayList)
61 :
62 1894920937 : SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
63 483567284 : SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
64 163519893 : SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
65 36079330 : SYNCHRONIZED_SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
66 :
67 35346725 : SMI_ACCESSORS(WeakArrayList, capacity, kCapacityOffset)
68 13151643 : SYNCHRONIZED_SMI_ACCESSORS(WeakArrayList, capacity, kCapacityOffset)
69 123664900 : SMI_ACCESSORS(WeakArrayList, length, kLengthOffset)
70 :
71 : Object FixedArrayBase::unchecked_synchronized_length() const {
72 11629081 : return ACQUIRE_READ_FIELD(this, kLengthOffset);
73 : }
74 :
75 132368500 : ACCESSORS(FixedTypedArrayBase, base_pointer, Object, kBasePointerOffset)
76 :
77 : ObjectSlot FixedArray::GetFirstElementAddress() {
78 : return RawField(OffsetOfElementAt(0));
79 : }
80 :
81 : bool FixedArray::ContainsOnlySmisOrHoles() {
82 : Object the_hole = GetReadOnlyRoots().the_hole_value();
83 : ObjectSlot current = GetFirstElementAddress();
84 : for (int i = 0; i < length(); ++i, ++current) {
85 : Object candidate = *current;
86 : if (!candidate->IsSmi() && candidate != the_hole) return false;
87 : }
88 : return true;
89 : }
90 :
91 467580 : Object FixedArray::get(int index) const {
92 : DCHECK(index >= 0 && index < this->length());
93 6235337460 : return RELAXED_READ_FIELD(this, kHeaderSize + index * kTaggedSize);
94 : }
95 :
96 31129485 : Handle<Object> FixedArray::get(FixedArray array, int index, Isolate* isolate) {
97 31129487 : return handle(array->get(index), isolate);
98 : }
99 :
100 : template <class T>
101 4744851 : MaybeHandle<T> FixedArray::GetValue(Isolate* isolate, int index) const {
102 4744851 : Object obj = get(index);
103 4744851 : if (obj->IsUndefined(isolate)) return MaybeHandle<T>();
104 830457 : return Handle<T>(T::cast(obj), isolate);
105 : }
106 :
107 : template <class T>
108 297313 : Handle<T> FixedArray::GetValueChecked(Isolate* isolate, int index) const {
109 297313 : Object obj = get(index);
110 297318 : CHECK(!obj->IsUndefined(isolate));
111 297320 : return Handle<T>(T::cast(obj), isolate);
112 : }
113 :
114 310985008 : bool FixedArray::is_the_hole(Isolate* isolate, int index) {
115 621970016 : return get(index)->IsTheHole(isolate);
116 : }
117 :
118 608 : void FixedArray::set(int index, Smi value) {
119 : DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
120 : DCHECK_LT(index, this->length());
121 : DCHECK(Object(value).IsSmi());
122 134410104 : int offset = kHeaderSize + index * kTaggedSize;
123 236924763 : RELAXED_WRITE_FIELD(this, offset, value);
124 608 : }
125 :
126 470483318 : void FixedArray::set(int index, Object value) {
127 : DCHECK_NE(GetReadOnlyRoots().fixed_cow_array_map(), map());
128 : DCHECK(IsFixedArray());
129 : DCHECK_GE(index, 0);
130 : DCHECK_LT(index, this->length());
131 470483318 : int offset = kHeaderSize + index * kTaggedSize;
132 470483318 : RELAXED_WRITE_FIELD(*this, offset, value);
133 940966688 : WRITE_BARRIER(*this, offset, value);
134 470483384 : }
135 :
136 1278726184 : void FixedArray::set(int index, Object value, WriteBarrierMode mode) {
137 : DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
138 : DCHECK_GE(index, 0);
139 : DCHECK_LT(index, this->length());
140 1278726184 : int offset = kHeaderSize + index * kTaggedSize;
141 1278726184 : RELAXED_WRITE_FIELD(*this, offset, value);
142 2780563281 : CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode);
143 1278726110 : }
144 :
145 : void FixedArray::NoWriteBarrierSet(FixedArray array, int index, Object value) {
146 : DCHECK_NE(array->map(), array->GetReadOnlyRoots().fixed_cow_array_map());
147 : DCHECK_GE(index, 0);
148 : DCHECK_LT(index, array->length());
149 : DCHECK(!Heap::InNewSpace(value));
150 378057698 : RELAXED_WRITE_FIELD(array, kHeaderSize + index * kTaggedSize, value);
151 : }
152 :
153 357484032 : void FixedArray::set_undefined(int index) {
154 357484032 : set_undefined(GetReadOnlyRoots(), index);
155 357484032 : }
156 :
157 1476 : void FixedArray::set_undefined(Isolate* isolate, int index) {
158 1476 : set_undefined(ReadOnlyRoots(isolate), index);
159 1476 : }
160 :
161 357485508 : void FixedArray::set_undefined(ReadOnlyRoots ro_roots, int index) {
162 : FixedArray::NoWriteBarrierSet(*this, index, ro_roots.undefined_value());
163 357485508 : }
164 :
165 529 : void FixedArray::set_null(int index) { set_null(GetReadOnlyRoots(), index); }
166 :
167 : void FixedArray::set_null(Isolate* isolate, int index) {
168 : set_null(ReadOnlyRoots(isolate), index);
169 : }
170 :
171 529 : void FixedArray::set_null(ReadOnlyRoots ro_roots, int index) {
172 : FixedArray::NoWriteBarrierSet(*this, index, ro_roots.null_value());
173 529 : }
174 :
175 11329514 : void FixedArray::set_the_hole(int index) {
176 11329514 : set_the_hole(GetReadOnlyRoots(), index);
177 11329515 : }
178 :
179 8121485 : void FixedArray::set_the_hole(Isolate* isolate, int index) {
180 8121485 : set_the_hole(ReadOnlyRoots(isolate), index);
181 8121485 : }
182 :
183 19451000 : void FixedArray::set_the_hole(ReadOnlyRoots ro_roots, int index) {
184 : FixedArray::NoWriteBarrierSet(*this, index, ro_roots.the_hole_value());
185 19451000 : }
186 :
187 : void FixedArray::FillWithHoles(int from, int to) {
188 11280093 : for (int i = from; i < to; i++) {
189 11280092 : set_the_hole(i);
190 : }
191 : }
192 :
193 0 : ObjectSlot FixedArray::data_start() {
194 0 : return RawField(OffsetOfElementAt(0));
195 : }
196 :
197 140344 : ObjectSlot FixedArray::RawFieldOfElementAt(int index) {
198 140344 : return RawField(OffsetOfElementAt(index));
199 : }
200 :
201 : void FixedArray::MoveElements(Heap* heap, int dst_index, int src_index, int len,
202 : WriteBarrierMode mode) {
203 : DisallowHeapAllocation no_gc;
204 1345 : heap->MoveElements(*this, dst_index, src_index, len, mode);
205 : }
206 :
207 : // Perform a binary search in a fixed array.
208 : template <SearchMode search_mode, typename T>
209 20537070 : int BinarySearch(T* array, Name name, int valid_entries,
210 : int* out_insertion_index) {
211 : DCHECK(search_mode == ALL_ENTRIES || out_insertion_index == nullptr);
212 : int low = 0;
213 20537070 : int high = array->number_of_entries() - 1;
214 : uint32_t hash = name->hash_field();
215 : int limit = high;
216 :
217 : DCHECK(low <= high);
218 :
219 127196623 : while (low != high) {
220 86122558 : int mid = low + (high - low) / 2;
221 59371450 : Name mid_name = array->GetSortedKey(mid);
222 : uint32_t mid_hash = mid_name->hash_field();
223 :
224 86122483 : if (mid_hash >= hash) {
225 : high = mid;
226 : } else {
227 48574672 : low = mid + 1;
228 : }
229 : }
230 :
231 0 : for (; low <= limit; ++low) {
232 : int sort_index = array->GetSortedKeyIndex(low);
233 20536968 : Name entry = array->GetKey(sort_index);
234 : uint32_t current_hash = entry->hash_field();
235 20536958 : if (current_hash != hash) {
236 120985 : if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
237 60734 : *out_insertion_index = sort_index + (current_hash > hash ? 0 : 1);
238 : }
239 : return T::kNotFound;
240 : }
241 11190475 : if (entry == name) {
242 4118730 : if (search_mode == ALL_ENTRIES || sort_index < valid_entries) {
243 3954622 : return sort_index;
244 : }
245 : return T::kNotFound;
246 : }
247 : }
248 :
249 0 : if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
250 0 : *out_insertion_index = limit + 1;
251 : }
252 : return T::kNotFound;
253 : }
254 :
255 : // Perform a linear search in this fixed array. len is the number of entry
256 : // indices that are valid.
257 : template <SearchMode search_mode, typename T>
258 13038776 : int LinearSearch(T* array, Name name, int valid_entries,
259 : int* out_insertion_index) {
260 13038776 : if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
261 : uint32_t hash = name->hash_field();
262 : int len = array->number_of_entries();
263 394398 : for (int number = 0; number < len; number++) {
264 : int sorted_index = array->GetSortedKeyIndex(number);
265 344816 : Name entry = array->GetKey(sorted_index);
266 : uint32_t current_hash = entry->hash_field();
267 344819 : if (current_hash > hash) {
268 105450 : *out_insertion_index = sorted_index;
269 105450 : return T::kNotFound;
270 : }
271 239369 : if (entry == name) return sorted_index;
272 : }
273 49582 : *out_insertion_index = len;
274 49582 : return T::kNotFound;
275 : } else {
276 : DCHECK_LE(valid_entries, array->number_of_entries());
277 : DCHECK_NULL(out_insertion_index); // Not supported here.
278 65318046 : for (int number = 0; number < valid_entries; number++) {
279 183936745 : if (array->GetKey(number) == name) return number;
280 : }
281 : return T::kNotFound;
282 : }
283 : }
284 :
285 : template <SearchMode search_mode, typename T>
286 61543621 : int Search(T* array, Name name, int valid_entries, int* out_insertion_index) {
287 : SLOW_DCHECK(array->IsSortedNoDuplicates());
288 :
289 61543621 : if (valid_entries == 0) {
290 434674 : if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
291 241147 : *out_insertion_index = 0;
292 : }
293 : return T::kNotFound;
294 : }
295 :
296 : // Fast case: do linear search for small arrays.
297 : const int kMaxElementsForLinearSearch = 8;
298 61108976 : if (valid_entries <= kMaxElementsForLinearSearch) {
299 : return LinearSearch<search_mode>(array, name, valid_entries,
300 40572012 : out_insertion_index);
301 : }
302 :
303 : // Slow case: perform binary search.
304 : return BinarySearch<search_mode>(array, name, valid_entries,
305 20536977 : out_insertion_index);
306 : }
307 :
308 656 : double FixedDoubleArray::get_scalar(int index) {
309 : DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
310 : map() != GetReadOnlyRoots().fixed_array_map());
311 : DCHECK(index >= 0 && index < this->length());
312 : DCHECK(!is_the_hole(index));
313 7493425 : return READ_DOUBLE_FIELD(this, kHeaderSize + index * kDoubleSize);
314 : }
315 :
316 : uint64_t FixedDoubleArray::get_representation(int index) {
317 : DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
318 : map() != GetReadOnlyRoots().fixed_array_map());
319 : DCHECK(index >= 0 && index < this->length());
320 27571346 : int offset = kHeaderSize + index * kDoubleSize;
321 27571346 : return READ_UINT64_FIELD(this, offset);
322 : }
323 :
324 8673395 : Handle<Object> FixedDoubleArray::get(FixedDoubleArray array, int index,
325 : Isolate* isolate) {
326 8673395 : if (array->is_the_hole(index)) {
327 1297705 : return isolate->factory()->the_hole_value();
328 : } else {
329 7375690 : return isolate->factory()->NewNumber(array->get_scalar(index));
330 : }
331 : }
332 :
333 : void FixedDoubleArray::set(int index, double value) {
334 : DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
335 : map() != GetReadOnlyRoots().fixed_array_map());
336 12129488 : int offset = kHeaderSize + index * kDoubleSize;
337 12122402 : if (std::isnan(value)) {
338 2157 : WRITE_DOUBLE_FIELD(this, offset, std::numeric_limits<double>::quiet_NaN());
339 : } else {
340 12127356 : WRITE_DOUBLE_FIELD(this, offset, value);
341 : }
342 : DCHECK(!is_the_hole(index));
343 : }
344 :
345 : void FixedDoubleArray::set_the_hole(Isolate* isolate, int index) {
346 : set_the_hole(index);
347 : }
348 :
349 : void FixedDoubleArray::set_the_hole(int index) {
350 : DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
351 : map() != GetReadOnlyRoots().fixed_array_map());
352 44358680 : int offset = kHeaderSize + index * kDoubleSize;
353 44358680 : WRITE_UINT64_FIELD(this, offset, kHoleNanInt64);
354 : }
355 :
356 : bool FixedDoubleArray::is_the_hole(Isolate* isolate, int index) {
357 : return is_the_hole(index);
358 : }
359 :
360 : bool FixedDoubleArray::is_the_hole(int index) {
361 0 : return get_representation(index) == kHoleNanInt64;
362 : }
363 :
364 16 : void FixedDoubleArray::MoveElements(Heap* heap, int dst_index, int src_index,
365 : int len, WriteBarrierMode mode) {
366 : DCHECK_EQ(SKIP_WRITE_BARRIER, mode);
367 : double* data_start =
368 16 : reinterpret_cast<double*>(FIELD_ADDR(*this, kHeaderSize));
369 16 : MemMove(data_start + dst_index, data_start + src_index, len * kDoubleSize);
370 16 : }
371 :
372 : void FixedDoubleArray::FillWithHoles(int from, int to) {
373 381916 : for (int i = from; i < to; i++) {
374 : set_the_hole(i);
375 : }
376 : }
377 :
378 272920612 : MaybeObject WeakFixedArray::Get(int index) const {
379 : DCHECK(index >= 0 && index < this->length());
380 545841224 : return RELAXED_READ_WEAK_FIELD(*this, OffsetOfElementAt(index));
381 : }
382 :
383 34885267 : void WeakFixedArray::Set(int index, MaybeObject value) {
384 : DCHECK_GE(index, 0);
385 : DCHECK_LT(index, length());
386 : int offset = OffsetOfElementAt(index);
387 34885267 : RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
388 69770568 : WEAK_WRITE_BARRIER(*this, offset, value);
389 34885309 : }
390 :
391 2621842 : void WeakFixedArray::Set(int index, MaybeObject value, WriteBarrierMode mode) {
392 : DCHECK_GE(index, 0);
393 : DCHECK_LT(index, length());
394 : int offset = OffsetOfElementAt(index);
395 2621842 : RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
396 7865526 : CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
397 2621842 : }
398 :
399 : MaybeObjectSlot WeakFixedArray::data_start() {
400 : return RawMaybeWeakField(kHeaderSize);
401 : }
402 :
403 : MaybeObjectSlot WeakFixedArray::RawFieldOfElementAt(int index) {
404 : return RawMaybeWeakField(OffsetOfElementAt(index));
405 : }
406 :
407 31861926 : MaybeObject WeakArrayList::Get(int index) const {
408 : DCHECK(index >= 0 && index < this->capacity());
409 63723852 : return RELAXED_READ_WEAK_FIELD(*this, OffsetOfElementAt(index));
410 : }
411 :
412 36417787 : void WeakArrayList::Set(int index, MaybeObject value, WriteBarrierMode mode) {
413 : DCHECK_GE(index, 0);
414 : DCHECK_LT(index, this->capacity());
415 : int offset = OffsetOfElementAt(index);
416 36417787 : RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
417 85529532 : CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
418 36417813 : }
419 :
420 : MaybeObjectSlot WeakArrayList::data_start() {
421 : return RawMaybeWeakField(kHeaderSize);
422 : }
423 :
424 5200954 : HeapObject WeakArrayList::Iterator::Next() {
425 5200954 : if (!array_.is_null()) {
426 10427072 : while (index_ < array_->length()) {
427 5209278 : MaybeObject item = array_->Get(index_++);
428 : DCHECK(item->IsWeakOrCleared());
429 10405924 : if (!item->IsCleared()) return item->GetHeapObjectAssumeWeak();
430 : }
431 4258 : array_ = WeakArrayList();
432 : }
433 4308 : return HeapObject();
434 : }
435 :
436 22838 : int ArrayList::Length() const {
437 22838 : if (FixedArray::cast(*this)->length() == 0) return 0;
438 22416 : return Smi::ToInt(FixedArray::cast(*this)->get(kLengthIndex));
439 : }
440 :
441 2780 : void ArrayList::SetLength(int length) {
442 2780 : return FixedArray::cast(*this)->set(kLengthIndex, Smi::FromInt(length));
443 : }
444 :
445 19146 : Object ArrayList::Get(int index) const {
446 38292 : return FixedArray::cast(*this)->get(kFirstIndex + index);
447 : }
448 :
449 : ObjectSlot ArrayList::Slot(int index) {
450 : return RawField(OffsetOfElementAt(kFirstIndex + index));
451 : }
452 :
453 2325 : void ArrayList::Set(int index, Object obj, WriteBarrierMode mode) {
454 4650 : FixedArray::cast(*this)->set(kFirstIndex + index, obj, mode);
455 2325 : }
456 :
457 5 : void ArrayList::Clear(int index, Object undefined) {
458 : DCHECK(undefined->IsUndefined());
459 : FixedArray::cast(*this)->set(kFirstIndex + index, undefined,
460 10 : SKIP_WRITE_BARRIER);
461 5 : }
462 :
463 35213215 : int ByteArray::Size() { return RoundUp(length() + kHeaderSize, kTaggedSize); }
464 :
465 : byte ByteArray::get(int index) const {
466 : DCHECK(index >= 0 && index < this->length());
467 61152898 : return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
468 : }
469 :
470 : void ByteArray::set(int index, byte value) {
471 : DCHECK(index >= 0 && index < this->length());
472 11486770 : WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
473 : }
474 :
475 : void ByteArray::copy_in(int index, const byte* buffer, int length) {
476 : DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
477 : index + length <= this->length());
478 133013 : Address dst_addr = FIELD_ADDR(this, kHeaderSize + index * kCharSize);
479 195916 : memcpy(reinterpret_cast<void*>(dst_addr), buffer, length);
480 : }
481 :
482 : void ByteArray::copy_out(int index, byte* buffer, int length) {
483 : DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
484 : index + length <= this->length());
485 304044371 : Address src_addr = FIELD_ADDR(this, kHeaderSize + index * kCharSize);
486 304044371 : memcpy(buffer, reinterpret_cast<void*>(src_addr), length);
487 : }
488 :
489 : int ByteArray::get_int(int index) const {
490 : DCHECK(index >= 0 && index < this->length() / kIntSize);
491 2568 : return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
492 : }
493 :
494 : void ByteArray::set_int(int index, int value) {
495 : DCHECK(index >= 0 && index < this->length() / kIntSize);
496 1530 : WRITE_INT_FIELD(this, kHeaderSize + index * kIntSize, value);
497 : }
498 :
499 1016815 : uint32_t ByteArray::get_uint32(int index) const {
500 : DCHECK(index >= 0 && index < this->length() / kUInt32Size);
501 1016815 : return READ_UINT32_FIELD(this, kHeaderSize + index * kUInt32Size);
502 : }
503 :
504 149491 : void ByteArray::set_uint32(int index, uint32_t value) {
505 : DCHECK(index >= 0 && index < this->length() / kUInt32Size);
506 149491 : WRITE_UINT32_FIELD(this, kHeaderSize + index * kUInt32Size, value);
507 149491 : }
508 :
509 7457593 : void ByteArray::clear_padding() {
510 7457599 : int data_size = length() + kHeaderSize;
511 14915209 : memset(reinterpret_cast<void*>(address() + data_size), 0, Size() - data_size);
512 7457610 : }
513 :
514 : ByteArray ByteArray::FromDataStartAddress(Address address) {
515 : DCHECK_TAG_ALIGNED(address);
516 : return ByteArray::cast(Object(address - kHeaderSize + kHeapObjectTag));
517 : }
518 :
519 874 : int ByteArray::DataSize() const { return RoundUp(length(), kTaggedSize); }
520 :
521 : int ByteArray::ByteArraySize() { return SizeFor(this->length()); }
522 :
523 394 : byte* ByteArray::GetDataStartAddress() {
524 432599116 : return reinterpret_cast<byte*>(address() + kHeaderSize);
525 : }
526 :
527 169578651 : byte* ByteArray::GetDataEndAddress() {
528 169154875 : return GetDataStartAddress() + length();
529 : }
530 :
531 : template <class T>
532 1039200 : PodArray<T>::PodArray(Address ptr) : ByteArray(ptr) {}
533 :
534 : template <class T>
535 : PodArray<T> PodArray<T>::cast(Object object) {
536 519598 : return PodArray<T>(object.ptr());
537 : }
538 :
539 : // static
540 : template <class T>
541 13568 : Handle<PodArray<T>> PodArray<T>::New(Isolate* isolate, int length,
542 : PretenureFlag pretenure) {
543 : return Handle<PodArray<T>>::cast(
544 13676 : isolate->factory()->NewByteArray(length * sizeof(T), pretenure));
545 : }
546 :
547 : template <class T>
548 : int PodArray<T>::length() const {
549 0 : return ByteArray::length() / sizeof(T);
550 : }
551 :
552 : void* FixedTypedArrayBase::external_pointer() const {
553 5570899 : intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
554 3334 : return reinterpret_cast<void*>(ptr);
555 : }
556 :
557 : void FixedTypedArrayBase::set_external_pointer(void* value,
558 : WriteBarrierMode mode) {
559 13977 : intptr_t ptr = reinterpret_cast<intptr_t>(value);
560 13982 : WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
561 : }
562 :
563 342 : void* FixedTypedArrayBase::DataPtr() {
564 : return reinterpret_cast<void*>(
565 11134010 : base_pointer()->ptr() + reinterpret_cast<intptr_t>(external_pointer()));
566 : }
567 :
568 327769 : int FixedTypedArrayBase::ElementSize(InstanceType type) {
569 : int element_size;
570 327769 : switch (type) {
571 : #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
572 : case FIXED_##TYPE##_ARRAY_TYPE: \
573 : element_size = sizeof(ctype); \
574 : break;
575 :
576 24899 : TYPED_ARRAYS(TYPED_ARRAY_CASE)
577 : #undef TYPED_ARRAY_CASE
578 : default:
579 0 : UNREACHABLE();
580 : }
581 327769 : return element_size;
582 : }
583 :
584 780398 : int FixedTypedArrayBase::DataSize(InstanceType type) const {
585 1560788 : if (base_pointer() == Smi::kZero) return 0;
586 327766 : return length() * ElementSize(type);
587 : }
588 :
589 219707 : int FixedTypedArrayBase::DataSize() const {
590 219707 : return DataSize(map()->instance_type());
591 : }
592 :
593 : size_t FixedTypedArrayBase::ByteLength() const {
594 : return static_cast<size_t>(length()) *
595 : static_cast<size_t>(ElementSize(map()->instance_type()));
596 : }
597 :
598 : int FixedTypedArrayBase::size() const {
599 193909 : return OBJECT_POINTER_ALIGN(kDataOffset + DataSize());
600 : }
601 :
602 : int FixedTypedArrayBase::TypedArraySize(InstanceType type) const {
603 560667 : return OBJECT_POINTER_ALIGN(kDataOffset + DataSize(type));
604 : }
605 :
606 : // static
607 : int FixedTypedArrayBase::TypedArraySize(InstanceType type, int length) {
608 : return OBJECT_POINTER_ALIGN(kDataOffset + length * ElementSize(type));
609 : }
610 :
611 : uint8_t Uint8ArrayTraits::defaultValue() { return 0; }
612 :
613 : uint8_t Uint8ClampedArrayTraits::defaultValue() { return 0; }
614 :
615 : int8_t Int8ArrayTraits::defaultValue() { return 0; }
616 :
617 : uint16_t Uint16ArrayTraits::defaultValue() { return 0; }
618 :
619 : int16_t Int16ArrayTraits::defaultValue() { return 0; }
620 :
621 : uint32_t Uint32ArrayTraits::defaultValue() { return 0; }
622 :
623 : int32_t Int32ArrayTraits::defaultValue() { return 0; }
624 :
625 : float Float32ArrayTraits::defaultValue() {
626 : return std::numeric_limits<float>::quiet_NaN();
627 : }
628 :
629 : double Float64ArrayTraits::defaultValue() {
630 : return std::numeric_limits<double>::quiet_NaN();
631 : }
632 :
633 : template <class Traits>
634 426554 : typename Traits::ElementType FixedTypedArray<Traits>::get_scalar(int index) {
635 : DCHECK((index >= 0) && (index < this->length()));
636 853108 : return FixedTypedArray<Traits>::get_scalar_from_data_ptr(DataPtr(), index);
637 : }
638 :
639 : // static
640 : template <class Traits>
641 : typename Traits::ElementType FixedTypedArray<Traits>::get_scalar_from_data_ptr(
642 : void* data_ptr, int index) {
643 : typename Traits::ElementType* ptr = reinterpret_cast<ElementType*>(data_ptr);
644 : // The JavaScript memory model allows for racy reads and writes to a
645 : // SharedArrayBuffer's backing store, which will always be a FixedTypedArray.
646 : // ThreadSanitizer will catch these racy accesses and warn about them, so we
647 : // disable TSAN for these reads and writes using annotations.
648 : //
649 : // We don't use relaxed atomics here, as it is not a requirement of the
650 : // JavaScript memory model to have tear-free reads of overlapping accesses,
651 : // and using relaxed atomics may introduce overhead.
652 : TSAN_ANNOTATE_IGNORE_READS_BEGIN;
653 442403 : auto result = ptr[index];
654 : TSAN_ANNOTATE_IGNORE_READS_END;
655 : return result;
656 : }
657 :
658 : template <class Traits>
659 5116609 : void FixedTypedArray<Traits>::set(int index, ElementType value) {
660 10233218 : CHECK((index >= 0) && (index < this->length()));
661 : // See the comment in FixedTypedArray<Traits>::get_scalar.
662 5116609 : auto* ptr = reinterpret_cast<ElementType*>(DataPtr());
663 : TSAN_ANNOTATE_IGNORE_WRITES_BEGIN;
664 5116609 : ptr[index] = value;
665 : TSAN_ANNOTATE_IGNORE_WRITES_END;
666 5116609 : }
667 :
668 : template <class Traits>
669 : typename Traits::ElementType FixedTypedArray<Traits>::from(int value) {
670 2504250 : return static_cast<ElementType>(value);
671 : }
672 :
673 : template <>
674 : inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(int value) {
675 24553 : if (value < 0) return 0;
676 24688 : if (value > 0xFF) return 0xFF;
677 24274 : return static_cast<uint8_t>(value);
678 : }
679 :
680 : template <>
681 0 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(int value) {
682 0 : UNREACHABLE();
683 : }
684 :
685 : template <>
686 0 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(int value) {
687 0 : UNREACHABLE();
688 : }
689 :
690 : template <class Traits>
691 : typename Traits::ElementType FixedTypedArray<Traits>::from(uint32_t value) {
692 1314 : return static_cast<ElementType>(value);
693 : }
694 :
695 : template <>
696 : inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(uint32_t value) {
697 : // We need this special case for Uint32 -> Uint8Clamped, because the highest
698 : // Uint32 values will be negative as an int, clamping to 0, rather than 255.
699 198 : if (value > 0xFF) return 0xFF;
700 117 : return static_cast<uint8_t>(value);
701 : }
702 :
703 : template <>
704 0 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(uint32_t value) {
705 0 : UNREACHABLE();
706 : }
707 :
708 : template <>
709 0 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(uint32_t value) {
710 0 : UNREACHABLE();
711 : }
712 :
713 : template <class Traits>
714 : typename Traits::ElementType FixedTypedArray<Traits>::from(double value) {
715 348208 : return static_cast<ElementType>(DoubleToInt32(value));
716 : }
717 :
718 : template <>
719 : inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(double value) {
720 : // Handle NaNs and less than zero values which clamp to zero.
721 93857 : if (!(value > 0)) return 0;
722 92521 : if (value > 0xFF) return 0xFF;
723 91792 : return static_cast<uint8_t>(lrint(value));
724 : }
725 :
726 : template <>
727 0 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(double value) {
728 0 : UNREACHABLE();
729 : }
730 :
731 : template <>
732 0 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(double value) {
733 0 : UNREACHABLE();
734 : }
735 :
736 : template <>
737 : inline float FixedTypedArray<Float32ArrayTraits>::from(double value) {
738 134455 : return static_cast<float>(value);
739 : }
740 :
741 : template <>
742 : inline double FixedTypedArray<Float64ArrayTraits>::from(double value) {
743 : return value;
744 : }
745 :
746 : template <class Traits>
747 0 : typename Traits::ElementType FixedTypedArray<Traits>::from(int64_t value) {
748 0 : UNREACHABLE();
749 : }
750 :
751 : template <class Traits>
752 0 : typename Traits::ElementType FixedTypedArray<Traits>::from(uint64_t value) {
753 0 : UNREACHABLE();
754 : }
755 :
756 : template <>
757 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(int64_t value) {
758 : return value;
759 : }
760 :
761 : template <>
762 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(uint64_t value) {
763 : return value;
764 : }
765 :
766 : template <>
767 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(int64_t value) {
768 0 : return static_cast<uint64_t>(value);
769 : }
770 :
771 : template <>
772 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(uint64_t value) {
773 0 : return static_cast<int64_t>(value);
774 : }
775 :
776 : template <class Traits>
777 3708 : typename Traits::ElementType FixedTypedArray<Traits>::FromHandle(
778 : Handle<Object> value, bool* lossless) {
779 7416 : if (value->IsSmi()) {
780 6264 : return from(Smi::ToInt(*value));
781 : }
782 : DCHECK(value->IsHeapNumber());
783 : return from(HeapNumber::cast(*value)->value());
784 : }
785 :
786 : template <>
787 252 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::FromHandle(
788 : Handle<Object> value, bool* lossless) {
789 : DCHECK(value->IsBigInt());
790 252 : return BigInt::cast(*value)->AsInt64(lossless);
791 : }
792 :
793 : template <>
794 252 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::FromHandle(
795 : Handle<Object> value, bool* lossless) {
796 : DCHECK(value->IsBigInt());
797 252 : return BigInt::cast(*value)->AsUint64(lossless);
798 : }
799 :
800 : template <class Traits>
801 228883 : Handle<Object> FixedTypedArray<Traits>::get(Isolate* isolate,
802 : FixedTypedArray<Traits> array,
803 : int index) {
804 632496 : return Traits::ToHandle(isolate, array->get_scalar(index));
805 : }
806 :
807 : template <class Traits>
808 2661233 : void FixedTypedArray<Traits>::SetValue(uint32_t index, Object value) {
809 : ElementType cast_value = Traits::defaultValue();
810 2661233 : if (value->IsSmi()) {
811 255417 : int int_value = Smi::ToInt(value);
812 : cast_value = from(int_value);
813 2405816 : } else if (value->IsHeapNumber()) {
814 : double double_value = HeapNumber::cast(value)->value();
815 : cast_value = from(double_value);
816 : } else {
817 : // Clamp undefined to the default value. All other types have been
818 : // converted to a number type further up in the call chain.
819 : DCHECK(value->IsUndefined());
820 : }
821 2661233 : set(index, cast_value);
822 2661233 : }
823 :
824 : template <>
825 675 : inline void FixedTypedArray<BigInt64ArrayTraits>::SetValue(uint32_t index,
826 : Object value) {
827 : DCHECK(value->IsBigInt());
828 675 : set(index, BigInt::cast(value)->AsInt64());
829 675 : }
830 :
831 : template <>
832 450 : inline void FixedTypedArray<BigUint64ArrayTraits>::SetValue(uint32_t index,
833 : Object value) {
834 : DCHECK(value->IsBigInt());
835 450 : set(index, BigInt::cast(value)->AsUint64());
836 450 : }
837 :
838 86924 : Handle<Object> Uint8ArrayTraits::ToHandle(Isolate* isolate, uint8_t scalar) {
839 86924 : return handle(Smi::FromInt(scalar), isolate);
840 : }
841 :
842 2241 : Handle<Object> Uint8ClampedArrayTraits::ToHandle(Isolate* isolate,
843 : uint8_t scalar) {
844 2241 : return handle(Smi::FromInt(scalar), isolate);
845 : }
846 :
847 5522 : Handle<Object> Int8ArrayTraits::ToHandle(Isolate* isolate, int8_t scalar) {
848 5522 : return handle(Smi::FromInt(scalar), isolate);
849 : }
850 :
851 75627 : Handle<Object> Uint16ArrayTraits::ToHandle(Isolate* isolate, uint16_t scalar) {
852 75627 : return handle(Smi::FromInt(scalar), isolate);
853 : }
854 :
855 4416 : Handle<Object> Int16ArrayTraits::ToHandle(Isolate* isolate, int16_t scalar) {
856 4416 : return handle(Smi::FromInt(scalar), isolate);
857 : }
858 :
859 : Handle<Object> Uint32ArrayTraits::ToHandle(Isolate* isolate, uint32_t scalar) {
860 75180 : return isolate->factory()->NewNumberFromUint(scalar);
861 : }
862 :
863 : Handle<Object> Int32ArrayTraits::ToHandle(Isolate* isolate, int32_t scalar) {
864 4414 : return isolate->factory()->NewNumberFromInt(scalar);
865 : }
866 :
867 : Handle<Object> Float32ArrayTraits::ToHandle(Isolate* isolate, float scalar) {
868 74849 : return isolate->factory()->NewNumber(scalar);
869 : }
870 :
871 : Handle<Object> Float64ArrayTraits::ToHandle(Isolate* isolate, double scalar) {
872 74359 : return isolate->factory()->NewNumber(scalar);
873 : }
874 :
875 : Handle<Object> BigInt64ArrayTraits::ToHandle(Isolate* isolate, int64_t scalar) {
876 45 : return BigInt::FromInt64(isolate, scalar);
877 : }
878 :
879 : Handle<Object> BigUint64ArrayTraits::ToHandle(Isolate* isolate,
880 : uint64_t scalar) {
881 36 : return BigInt::FromUint64(isolate, scalar);
882 : }
883 :
884 : // static
885 : template <class Traits>
886 : STATIC_CONST_MEMBER_DEFINITION const InstanceType
887 : FixedTypedArray<Traits>::kInstanceType;
888 :
889 : template <class Traits>
890 1264910 : FixedTypedArray<Traits>::FixedTypedArray(Address ptr)
891 : : FixedTypedArrayBase(ptr) {
892 : DCHECK(IsHeapObject() && map()->instance_type() == Traits::kInstanceType);
893 1264910 : }
894 :
895 : template <class Traits>
896 : FixedTypedArray<Traits> FixedTypedArray<Traits>::cast(Object object) {
897 1264910 : return FixedTypedArray<Traits>(object.ptr());
898 : }
899 :
900 6432534 : int TemplateList::length() const {
901 6432534 : return Smi::ToInt(FixedArray::cast(*this)->get(kLengthIndex));
902 : }
903 :
904 8412485 : Object TemplateList::get(int index) const {
905 16824970 : return FixedArray::cast(*this)->get(kFirstElementIndex + index);
906 : }
907 :
908 151 : void TemplateList::set(int index, Object value) {
909 302 : FixedArray::cast(*this)->set(kFirstElementIndex + index, value);
910 151 : }
911 :
912 : } // namespace internal
913 : } // namespace v8
914 :
915 : #include "src/objects/object-macros-undef.h"
916 :
917 : #endif // V8_OBJECTS_FIXED_ARRAY_INL_H_
|