28#include "third_party/fp16/src/include/fp16.h"
90#define RETURN_NOTHING_IF_NOT_SUCCESSFUL(call) \
92 if (!(call)) return Nothing<bool>(); \
95#define RETURN_FAILURE_IF_NOT_SUCCESSFUL(call) \
97 ExceptionStatus status_enum_result = (call); \
98 if (!status_enum_result) return status_enum_result; \
101static const int kPackedSizeNotKnown = -1;
103enum Where { AT_START, AT_END };
110#define ELEMENTS_LIST(V) \
111 V(FastPackedSmiElementsAccessor, PACKED_SMI_ELEMENTS, FixedArray) \
112 V(FastHoleySmiElementsAccessor, HOLEY_SMI_ELEMENTS, FixedArray) \
113 V(FastPackedObjectElementsAccessor, PACKED_ELEMENTS, FixedArray) \
114 V(FastHoleyObjectElementsAccessor, HOLEY_ELEMENTS, FixedArray) \
115 V(FastPackedDoubleElementsAccessor, PACKED_DOUBLE_ELEMENTS, \
117 V(FastHoleyDoubleElementsAccessor, HOLEY_DOUBLE_ELEMENTS, FixedDoubleArray) \
118 V(FastPackedNonextensibleObjectElementsAccessor, \
119 PACKED_NONEXTENSIBLE_ELEMENTS, FixedArray) \
120 V(FastHoleyNonextensibleObjectElementsAccessor, \
121 HOLEY_NONEXTENSIBLE_ELEMENTS, FixedArray) \
122 V(FastPackedSealedObjectElementsAccessor, PACKED_SEALED_ELEMENTS, \
124 V(FastHoleySealedObjectElementsAccessor, HOLEY_SEALED_ELEMENTS, FixedArray) \
125 V(FastPackedFrozenObjectElementsAccessor, PACKED_FROZEN_ELEMENTS, \
127 V(FastHoleyFrozenObjectElementsAccessor, HOLEY_FROZEN_ELEMENTS, FixedArray) \
128 V(SharedArrayElementsAccessor, SHARED_ARRAY_ELEMENTS, FixedArray) \
129 V(DictionaryElementsAccessor, DICTIONARY_ELEMENTS, NumberDictionary) \
130 V(FastSloppyArgumentsElementsAccessor, FAST_SLOPPY_ARGUMENTS_ELEMENTS, \
132 V(SlowSloppyArgumentsElementsAccessor, SLOW_SLOPPY_ARGUMENTS_ELEMENTS, \
134 V(FastStringWrapperElementsAccessor, FAST_STRING_WRAPPER_ELEMENTS, \
136 V(SlowStringWrapperElementsAccessor, SLOW_STRING_WRAPPER_ELEMENTS, \
138 V(Uint8ElementsAccessor, UINT8_ELEMENTS, ByteArray) \
139 V(Int8ElementsAccessor, INT8_ELEMENTS, ByteArray) \
140 V(Uint16ElementsAccessor, UINT16_ELEMENTS, ByteArray) \
141 V(Int16ElementsAccessor, INT16_ELEMENTS, ByteArray) \
142 V(Uint32ElementsAccessor, UINT32_ELEMENTS, ByteArray) \
143 V(Int32ElementsAccessor, INT32_ELEMENTS, ByteArray) \
144 V(BigUint64ElementsAccessor, BIGUINT64_ELEMENTS, ByteArray) \
145 V(BigInt64ElementsAccessor, BIGINT64_ELEMENTS, ByteArray) \
146 V(Uint8ClampedElementsAccessor, UINT8_CLAMPED_ELEMENTS, ByteArray) \
147 V(Float32ElementsAccessor, FLOAT32_ELEMENTS, ByteArray) \
148 V(Float64ElementsAccessor, FLOAT64_ELEMENTS, ByteArray) \
149 V(Float16ElementsAccessor, FLOAT16_ELEMENTS, ByteArray) \
150 V(RabGsabUint8ElementsAccessor, RAB_GSAB_UINT8_ELEMENTS, ByteArray) \
151 V(RabGsabInt8ElementsAccessor, RAB_GSAB_INT8_ELEMENTS, ByteArray) \
152 V(RabGsabUint16ElementsAccessor, RAB_GSAB_UINT16_ELEMENTS, ByteArray) \
153 V(RabGsabInt16ElementsAccessor, RAB_GSAB_INT16_ELEMENTS, ByteArray) \
154 V(RabGsabUint32ElementsAccessor, RAB_GSAB_UINT32_ELEMENTS, ByteArray) \
155 V(RabGsabInt32ElementsAccessor, RAB_GSAB_INT32_ELEMENTS, ByteArray) \
156 V(RabGsabBigUint64ElementsAccessor, RAB_GSAB_BIGUINT64_ELEMENTS, ByteArray) \
157 V(RabGsabBigInt64ElementsAccessor, RAB_GSAB_BIGINT64_ELEMENTS, ByteArray) \
158 V(RabGsabUint8ClampedElementsAccessor, RAB_GSAB_UINT8_CLAMPED_ELEMENTS, \
160 V(RabGsabFloat32ElementsAccessor, RAB_GSAB_FLOAT32_ELEMENTS, ByteArray) \
161 V(RabGsabFloat64ElementsAccessor, RAB_GSAB_FLOAT64_ELEMENTS, ByteArray) \
162 V(RabGsabFloat16ElementsAccessor, RAB_GSAB_FLOAT16_ELEMENTS, ByteArray)
164template <ElementsKind Kind>
165class ElementsKindTraits {
167 using BackingStore = FixedArrayBase;
170#define ELEMENTS_TRAITS(Class, KindParam, Store) \
172 class ElementsKindTraits<KindParam> { \
174 static constexpr ElementsKind Kind = KindParam; \
175 using BackingStore = Store; \
177 constexpr ElementsKind ElementsKindTraits<KindParam>::Kind;
179#undef ELEMENTS_TRAITS
182MaybeDirectHandle<Object> ThrowArrayLengthRangeError(Isolate* isolate) {
183 THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kInvalidArrayLength));
191 return elements->GetWriteBarrierMode(promise);
198constexpr int kCopyToEndAndInitializeToHole = -1;
200void CopyObjectToObjectElements(Isolate* isolate,
206 ReadOnlyRoots roots(isolate);
207 DCHECK(to_base->map() != roots.fixed_cow_array_map());
209 int copy_size = raw_copy_size;
210 if (raw_copy_size < 0) {
211 DCHECK_EQ(kCopyToEndAndInitializeToHole, raw_copy_size);
212 copy_size = std::min(from_base->length() - from_start,
213 to_base->length() - to_start);
214 int start = to_start + copy_size;
215 int length = to_base->length() -
start;
218 roots.the_hole_value(), length);
221 DCHECK((copy_size +
static_cast<int>(to_start)) <= to_base->length() &&
222 (copy_size +
static_cast<int>(from_start)) <= from_base->length());
223 if (copy_size == 0)
return;
233 to->CopyElements(isolate, to_start, from, from_start, copy_size,
237void CopyDictionaryToObjectElements(Isolate* isolate,
245 int copy_size = raw_copy_size;
246 if (raw_copy_size < 0) {
247 DCHECK_EQ(kCopyToEndAndInitializeToHole, raw_copy_size);
248 copy_size = from->max_number_key() + 1 - from_start;
249 int start = to_start + copy_size;
250 int length = to_base->length() -
start;
253 ReadOnlyRoots(isolate).the_hole_value(), length);
256 DCHECK(to_base != from_base);
258 if (copy_size == 0)
return;
260 uint32_t to_length = to->length();
261 if (to_start + copy_size > to_length) {
262 copy_size = to_length - to_start;
264 WriteBarrierMode write_barrier_mode = GetWriteBarrierMode(to, to_kind, no_gc);
265 for (
int i = 0;
i < copy_size;
i++) {
266 InternalIndex entry = from->FindEntry(isolate,
i + from_start);
267 if (entry.is_found()) {
269 DCHECK(!IsTheHole(value, isolate));
270 to->set(
i + to_start, value, write_barrier_mode);
272 to->set_the_hole(isolate,
i + to_start);
280void CopyDoubleToObjectElements(Isolate* isolate,
284 uint32_t to_start,
int raw_copy_size) {
285 int copy_size = raw_copy_size;
286 if (raw_copy_size < 0) {
288 DCHECK_EQ(kCopyToEndAndInitializeToHole, raw_copy_size);
289 copy_size = std::min(from_base->length() - from_start,
290 to_base->length() - to_start);
294 int start = to_start;
295 int length = to_base->length() -
start;
298 ReadOnlyRoots(isolate).the_hole_value(), length);
302 DCHECK((copy_size +
static_cast<int>(to_start)) <= to_base->length() &&
303 (copy_size +
static_cast<int>(from_start)) <= from_base->length());
304 if (copy_size == 0)
return;
316 while (
offset < copy_size) {
317 HandleScope scope(isolate);
320 DirectHandle<Object> value =
330 uint32_t to_start,
int raw_copy_size) {
332 int copy_size = raw_copy_size;
333 if (raw_copy_size < 0) {
334 DCHECK_EQ(kCopyToEndAndInitializeToHole, raw_copy_size);
335 copy_size = std::min(from_base->length() - from_start,
336 to_base->length() - to_start);
337 for (
int i = to_start + copy_size;
i < to_base->
length(); ++
i) {
341 DCHECK((copy_size +
static_cast<int>(to_start)) <= to_base->length() &&
342 (copy_size +
static_cast<int>(from_start)) <= from_base->length());
343 if (copy_size == 0)
return;
350#ifdef V8_COMPRESS_POINTERS
356 static_cast<size_t>(words_per_double * copy_size));
360 static_cast<size_t>(words_per_double * copy_size));
369 int copy_size = raw_copy_size;
370 if (raw_copy_size < 0) {
371 DCHECK_EQ(kCopyToEndAndInitializeToHole, raw_copy_size);
372 copy_size = from_base->length() - from_start;
373 for (
int i = to_start + copy_size;
i < to_base->
length(); ++
i) {
377 DCHECK((copy_size +
static_cast<int>(to_start)) <= to_base->length() &&
378 (copy_size +
static_cast<int>(from_start)) <= from_base->length());
379 if (copy_size == 0)
return;
383 for (uint32_t from_end = from_start +
static_cast<uint32_t
>(copy_size);
384 from_start < from_end; from_start++, to_start++) {
386 if (hole_or_smi == the_hole) {
387 to->set_the_hole(to_start);
397 uint32_t to_start,
int packed_size,
400 int copy_size = raw_copy_size;
402 if (raw_copy_size < 0) {
403 DCHECK_EQ(kCopyToEndAndInitializeToHole, raw_copy_size);
404 copy_size = packed_size - from_start;
405 to_end = to_base->length();
406 for (uint32_t
i = to_start + copy_size;
i < to_end; ++
i) {
410 to_end = to_start +
static_cast<uint32_t
>(copy_size);
412 DCHECK(
static_cast<int>(to_end) <= to_base->length());
413 DCHECK(packed_size >= 0 && packed_size <= copy_size);
414 DCHECK((copy_size +
static_cast<int>(to_start)) <= to_base->length() &&
415 (copy_size +
static_cast<int>(from_start)) <= from_base->length());
416 if (copy_size == 0)
return;
419 for (uint32_t from_end = from_start +
static_cast<uint32_t
>(packed_size);
420 from_start < from_end; from_start++, to_start++) {
430 uint32_t to_start,
int raw_copy_size) {
432 int copy_size = raw_copy_size;
433 if (raw_copy_size < 0) {
434 DCHECK_EQ(kCopyToEndAndInitializeToHole, raw_copy_size);
435 copy_size = from_base->length() - from_start;
436 for (
int i = to_start + copy_size;
i < to_base->
length(); ++
i) {
440 DCHECK((copy_size +
static_cast<int>(to_start)) <= to_base->length() &&
441 (copy_size +
static_cast<int>(from_start)) <= from_base->length());
442 if (copy_size == 0)
return;
446 for (uint32_t from_end = from_start + copy_size; from_start < from_end;
447 from_start++, to_start++) {
449 if (hole_or_object == the_hole) {
450 to->set_the_hole(to_start);
457void CopyDictionaryToDoubleElements(Isolate* isolate,
461 uint32_t to_start,
int raw_copy_size) {
464 int copy_size = raw_copy_size;
466 DCHECK_EQ(kCopyToEndAndInitializeToHole, copy_size);
467 copy_size = from->max_number_key() + 1 - from_start;
468 for (
int i = to_start + copy_size;
i < to_base->
length(); ++
i) {
472 if (copy_size == 0)
return;
474 uint32_t to_length = to->length();
475 if (to_start + copy_size > to_length) {
476 copy_size = to_length - to_start;
478 for (
int i = 0;
i < copy_size;
i++) {
479 InternalIndex entry = from->FindEntry(isolate,
i + from_start);
480 if (entry.is_found()) {
481 to->set(
i + to_start,
484 to->set_the_hole(
i + to_start);
489void SortIndices(Isolate* isolate, DirectHandle<FixedArray> indices,
490 uint32_t sort_size) {
491 if (sort_size == 0)
return;
495 AtomicSlot
start(indices->RawFieldOfFirstElement());
498#ifdef V8_COMPRESS_POINTERS
507 if (
IsSmi(a) || !IsUndefined(a, isolate)) {
508 if (!
IsSmi(b) && IsUndefined(b, isolate)) {
514 return !
IsSmi(b) && IsUndefined(b, isolate);
520Maybe<bool> IncludesValueSlowPath(Isolate* isolate,
522 DirectHandle<Object> value,
size_t start_from,
524 bool search_for_hole = IsUndefined(*value, isolate);
525 for (
size_t k = start_from; k <
length; ++k) {
526 LookupIterator it(isolate,
receiver, k);
528 if (search_for_hole)
return Just(
true);
531 DirectHandle<Object> element_k;
541Maybe<int64_t> IndexOfValueSlowPath(Isolate* isolate,
543 DirectHandle<Object> value,
544 size_t start_from,
size_t length) {
545 for (
size_t k = start_from; k <
length; ++k) {
546 LookupIterator it(isolate,
receiver, k);
550 DirectHandle<Object> element_k;
563class InternalElementsAccessor :
public ElementsAccessor {
567 size_t index)
override = 0;
570 InternalIndex entry)
override = 0;
590template <
typename Sub
class,
typename ElementsTraitsParam>
591class ElementsAccessorBase :
public InternalElementsAccessor {
593 ElementsAccessorBase() =
default;
594 ElementsAccessorBase(
const ElementsAccessorBase&) =
delete;
595 ElementsAccessorBase& operator=(
const ElementsAccessorBase&) =
delete;
597 using ElementsTraits = ElementsTraitsParam;
598 using BackingStore =
typename ElementsTraitsParam::BackingStore;
610 if (IsJSArray(holder)) {
612 if (
IsSmi(length_obj)) {
615 }
else if (IsJSTypedArray(holder)) {
618 length = fixed_array_base->length();
620 Subclass::ValidateContents(holder, length);
625 Subclass::ValidateImpl(holder);
631 return Subclass::HasElementImpl(holder->GetIsolate(), holder, index,
632 backing_store, filter);
638 return Subclass::GetEntryForIndexImpl(isolate, holder, backing_store, index,
644 return Subclass::HasEntryImpl(holder->GetIsolate(), holder->elements(),
648 static bool HasEntryImpl(Isolate* isolate,
650 InternalIndex entry) {
655 return Subclass::HasAccessorsImpl(holder, holder->elements());
663 Handle<Object>
Get(Isolate* isolate, DirectHandle<JSObject> holder,
664 InternalIndex entry)
final {
665 return Subclass::GetInternalImpl(isolate, holder, entry);
668 static Handle<Object> GetInternalImpl(Isolate* isolate,
669 DirectHandle<JSObject> holder,
670 InternalIndex entry) {
671 return Subclass::GetImpl(isolate, holder->elements(), entry);
674 static Handle<Object> GetImpl(Isolate* isolate,
676 InternalIndex entry) {
681 Handle<Object> GetAtomic(Isolate* isolate, DirectHandle<JSObject> holder,
682 InternalIndex entry, SeqCstAccessTag tag)
final {
683 return Subclass::GetAtomicInternalImpl(isolate, holder->elements(), entry,
687 static Handle<Object> GetAtomicInternalImpl(
689 InternalIndex entry, SeqCstAccessTag tag) {
693 void SetAtomic(DirectHandle<JSObject> holder, InternalIndex entry,
695 Subclass::SetAtomicInternalImpl(holder->elements(), entry, value, tag);
700 SeqCstAccessTag tag) {
704 Handle<Object> SwapAtomic(Isolate* isolate, DirectHandle<JSObject> holder,
706 SeqCstAccessTag tag)
final {
707 return Subclass::SwapAtomicInternalImpl(isolate, holder->elements(), entry,
711 static Handle<Object> SwapAtomicInternalImpl(
717 Handle<Object> CompareAndSwapAtomic(Isolate* isolate,
718 DirectHandle<JSObject> holder,
722 SeqCstAccessTag tag)
final {
727 return Subclass::CompareAndSwapAtomicInternalImpl(
728 holder->elements(), entry, expected_value,
740 void Set(DirectHandle<JSObject> holder, InternalIndex entry,
742 Subclass::SetImpl(holder, entry, value);
745 void Reconfigure(DirectHandle<JSObject>
object,
746 DirectHandle<FixedArrayBase> store, InternalIndex entry,
747 DirectHandle<Object> value,
749 Subclass::ReconfigureImpl(
object, store, entry, value, attributes);
752 static void ReconfigureImpl(DirectHandle<JSObject>
object,
753 DirectHandle<FixedArrayBase> store,
754 InternalIndex entry, DirectHandle<Object> value,
759 Maybe<bool>
Add(DirectHandle<JSObject>
object, uint32_t index,
761 uint32_t new_capacity)
final {
762 return Subclass::AddImpl(
object, index, value, attributes, new_capacity);
765 static Maybe<bool> AddImpl(DirectHandle<JSObject>
object, uint32_t index,
766 DirectHandle<Object> value,
768 uint32_t new_capacity) {
772 Maybe<uint32_t> Push(DirectHandle<JSArray>
receiver, BuiltinArguments*
args,
773 uint32_t push_size)
final {
777 static Maybe<uint32_t> PushImpl(DirectHandle<JSArray>
receiver,
778 BuiltinArguments*
args, uint32_t push_sized) {
782 Maybe<uint32_t> Unshift(DirectHandle<JSArray>
receiver,
783 BuiltinArguments*
args, uint32_t unshift_size)
final {
784 return Subclass::UnshiftImpl(
receiver,
args, unshift_size);
787 static Maybe<uint32_t> UnshiftImpl(DirectHandle<JSArray>
receiver,
788 BuiltinArguments*
args,
789 uint32_t unshift_size) {
793 MaybeDirectHandle<Object> Pop(DirectHandle<JSArray>
receiver)
final {
797 static MaybeDirectHandle<Object> PopImpl(DirectHandle<JSArray>
receiver) {
801 MaybeDirectHandle<Object>
Shift(DirectHandle<JSArray>
receiver)
final {
802 return Subclass::ShiftImpl(
receiver);
805 static MaybeDirectHandle<Object> ShiftImpl(DirectHandle<JSArray>
receiver) {
809 Maybe<bool> SetLength(DirectHandle<JSArray> array, uint32_t length)
final {
810 return Subclass::SetLengthImpl(
811 array->GetIsolate(), array, length,
815 static Maybe<bool> SetLengthImpl(Isolate* isolate,
816 DirectHandle<JSArray> array, uint32_t length,
817 DirectHandle<FixedArrayBase> backing_store) {
818 DCHECK(!array->SetLengthWouldNormalize(length));
820 uint32_t old_length = 0;
823 if (old_length < length) {
832 uint32_t capacity = backing_store->length();
833 old_length = std::min(old_length, capacity);
835 array->initialize_elements();
836 }
else if (length <= capacity) {
839 if (array->elements() != *backing_store) {
848 uint32_t new_capacity =
849 length + 1 == old_length ? (capacity +
length) / 2 : length;
852 new_capacity, capacity);
855 ->FillWithHoles(length, std::min(old_length, new_capacity));
862 uint32_t new_capacity;
871 new_capacity = std::max(length, JSArray::NewElementsCapacity(capacity));
880 MAYBE_RETURN(Subclass::GrowCapacityAndConvertImpl(array, new_capacity),
890 return Subclass::NumberOfElementsImpl(isolate,
receiver,
894 static uint32_t NumberOfElementsImpl(Isolate* isolate,
904 return static_cast<uint32_t
>(
907 return Subclass::GetCapacityImpl(
receiver, elements);
910 static size_t GetMaxNumberOfEntries(Isolate* isolate,
913 return Subclass::GetMaxIndex(
receiver, elements);
916 static MaybeDirectHandle<FixedArrayBase> ConvertElementsWithCapacity(
917 DirectHandle<JSObject>
object, DirectHandle<FixedArrayBase> old_elements,
919 return ConvertElementsWithCapacity(
object, old_elements, from_kind,
923 static MaybeDirectHandle<FixedArrayBase> ConvertElementsWithCapacity(
924 DirectHandle<JSObject>
object, DirectHandle<FixedArrayBase> old_elements,
925 ElementsKind from_kind, uint32_t capacity, uint32_t src_index,
926 uint32_t dst_index) {
927 Isolate* isolate =
object->GetIsolate();
928 DirectHandle<FixedArrayBase> new_elements;
932 if (!isolate->context().is_null() &&
935 NewRangeError(MessageTemplate::kInvalidArrayLength));
937 new_elements = isolate->factory()->NewFixedDoubleArray(capacity);
939 if (!isolate->context().is_null() &&
942 NewRangeError(MessageTemplate::kInvalidArrayLength));
944 new_elements = isolate->factory()->NewFixedArray(capacity);
947 int packed_size = kPackedSizeNotKnown;
952 Subclass::CopyElementsImpl(isolate, *old_elements, src_index, *new_elements,
953 from_kind, dst_index, packed_size,
954 kCopyToEndAndInitializeToHole);
956 return MaybeDirectHandle<FixedArrayBase>(new_elements);
959 static void TransitionElementsKindImpl(DirectHandle<JSObject>
object,
960 DirectHandle<Map> to_map) {
961 Isolate* isolate =
object->GetIsolate();
962 DirectHandle<Map> from_map(object->map(), isolate);
968 if (from_kind != to_kind) {
974 DirectHandle<FixedArrayBase> from_elements(object->elements(), isolate);
975 if (object->elements() == ReadOnlyRoots(isolate).empty_fixed_array() ||
984 uint32_t capacity =
static_cast<uint32_t
>(
object->elements()->
length());
990 DirectHandle<FixedArrayBase> elements =
991 ConvertElementsWithCapacity(
object, from_elements, from_kind,
996 if (
v8_flags.trace_elements_transitions) {
998 stdout,
object, from_kind, from_elements, to_kind,
1004 static Maybe<bool> GrowCapacityAndConvertImpl(DirectHandle<JSObject>
object,
1005 uint32_t capacity) {
1011 object->GetIsolate()->UpdateNoElementsProtectorOnSetLength(
object);
1013 DirectHandle<FixedArrayBase> old_elements(object->elements(),
1014 object->GetIsolate());
1019 static_cast<uint32_t
>(old_elements->length()) < capacity);
1020 return Subclass::BasicGrowCapacityAndConvertImpl(
1021 object, old_elements, from_kind,
kind(), capacity);
1024 static Maybe<bool> BasicGrowCapacityAndConvertImpl(
1025 DirectHandle<JSObject>
object, DirectHandle<FixedArrayBase> old_elements,
1027 DirectHandle<FixedArrayBase> elements;
1029 object->GetIsolate(), elements,
1030 ConvertElementsWithCapacity(
object, old_elements, from_kind, capacity),
1036 DirectHandle<Map> new_map =
1043 if (
v8_flags.trace_elements_transitions) {
1050 void TransitionElementsKind(DirectHandle<JSObject>
object,
1051 DirectHandle<Map> map)
final {
1052 Subclass::TransitionElementsKindImpl(
object, map);
1055 Maybe<bool> GrowCapacityAndConvert(DirectHandle<JSObject>
object,
1056 uint32_t capacity)
final {
1057 return Subclass::GrowCapacityAndConvertImpl(
object, capacity);
1060 Maybe<bool> GrowCapacity(DirectHandle<JSObject>
object,
1061 uint32_t index)
final {
1064 if (object->map()->is_prototype_map() ||
1065 object->WouldConvertToSlowElements(index)) {
1068 DirectHandle<FixedArrayBase> old_elements(object->elements(),
1069 object->GetIsolate());
1071 DCHECK(
static_cast<uint32_t
>(old_elements->length()) < new_capacity);
1075 if (new_capacity > kMaxLength) {
1078 DirectHandle<FixedArrayBase> elements;
1080 object->GetIsolate(), elements,
1081 ConvertElementsWithCapacity(
object, old_elements,
kind(), new_capacity),
1086 if (JSObject::UpdateAllocationSite<AllocationSiteUpdateMode::kCheckOnly>(
1091 object->set_elements(*elements);
1095 void Delete(DirectHandle<JSObject> obj, InternalIndex entry)
final {
1096 Subclass::DeleteImpl(obj, entry);
1102 int packed_size,
int copy_size) {
1108 DirectHandle<FixedArrayBase> to, uint32_t to_start,
1109 int copy_size)
final {
1110 int packed_size = kPackedSizeNotKnown;
1115 if (copy_size >= 0 && packed_size > copy_size) {
1116 packed_size = copy_size;
1129 Subclass::CopyElementsImpl(isolate, from, from_start, *to, from_kind,
1130 to_start, packed_size, copy_size);
1133 void CopyElements(Isolate* isolate, DirectHandle<FixedArrayBase> source,
1136 int size)
override {
1137 Subclass::CopyElementsImpl(isolate, *source, 0, *
destination, source_kind,
1138 0, kPackedSizeNotKnown, size);
1143 size_t start,
size_t end)
override {
1154 DirectHandle<JSObject>
destination,
size_t length,
1156 return Subclass::CopyElementsHandleImpl(source,
destination, length,
1161 DirectHandle<Object> source, DirectHandle<JSObject>
destination,
1162 size_t length,
size_t offset) {
1166 DirectHandle<NumberDictionary> Normalize(
1167 DirectHandle<JSObject>
object)
final {
1168 return Subclass::NormalizeImpl(
1169 object,
direct_handle(object->elements(), object->GetIsolate()));
1172 static DirectHandle<NumberDictionary> NormalizeImpl(
1173 DirectHandle<JSObject>
object, DirectHandle<FixedArrayBase> elements) {
1177 Maybe<bool> CollectValuesOrEntries(Isolate* isolate,
1178 DirectHandle<JSObject>
object,
1179 DirectHandle<FixedArray> values_or_entries,
1180 bool get_entries,
int* nof_items,
1182 return Subclass::CollectValuesOrEntriesImpl(
1183 isolate,
object, values_or_entries, get_entries, nof_items, filter);
1186 static Maybe<bool> CollectValuesOrEntriesImpl(
1187 Isolate* isolate, DirectHandle<JSObject>
object,
1188 DirectHandle<FixedArray> values_or_entries,
bool get_entries,
1194 object,
direct_handle(object->elements(), isolate), &accumulator));
1195 DirectHandle<FixedArray> keys = accumulator.GetKeys();
1199 ElementsKind original_elements_kind =
object->GetElementsKind();
1202 DirectHandle<Object>
key(keys->get(
i), isolate);
1206 DCHECK_EQ(object->GetElementsKind(), original_elements_kind);
1207 InternalIndex entry = Subclass::GetEntryForIndexImpl(
1208 isolate, *
object, object->elements(), index, filter);
1209 if (entry.is_not_found())
continue;
1210 PropertyDetails details = Subclass::GetDetailsImpl(*
object, entry);
1212 DirectHandle<Object>
value;
1214 value = Subclass::GetInternalImpl(isolate,
object, entry);
1221 if (get_entries) value =
MakeEntryPair(isolate, index, value);
1222 values_or_entries->set(count++, *value);
1223 if (object->GetElementsKind() != original_elements_kind)
break;
1228 DirectHandle<Object>
key(keys->get(
i), isolate);
1233 InternalElementsAccessor* accessor =
1234 reinterpret_cast<InternalElementsAccessor*
>(
1235 object->GetElementsAccessor());
1236 InternalIndex entry = accessor->GetEntryForIndex(
1237 isolate, *
object, object->elements(), index);
1238 if (entry.is_not_found())
continue;
1239 PropertyDetails details = accessor->GetDetails(*
object, entry);
1240 if (!details.IsEnumerable())
continue;
1243 DirectHandle<Object>
value;
1248 if (get_entries) value =
MakeEntryPair(isolate, index, value);
1249 values_or_entries->set(count++, *value);
1257 DirectHandle<JSObject>
object, DirectHandle<FixedArrayBase> backing_store,
1258 KeyAccumulator* keys)
final {
1259 return Subclass::CollectElementIndicesImpl(
object, backing_store, keys);
1263 DirectHandle<JSObject>
object, DirectHandle<FixedArrayBase> backing_store,
1264 KeyAccumulator* keys) {
1267 size_t length = Subclass::GetMaxIndex(*
object, *backing_store);
1269 Isolate* isolate = keys->isolate();
1270 Factory* factory = isolate->factory();
1272 if (Subclass::HasElementImpl(isolate, *
object,
i, *backing_store,
1275 keys->AddKey(factory->NewNumberFromSize(
i)));
1282 Isolate* isolate, DirectHandle<JSObject>
object,
1285 uint32_t insertion_index = 0) {
1286 size_t length = Subclass::GetMaxIndex(*
object, *backing_store);
1287 uint32_t
const kMaxStringTableEntries =
1288 isolate->heap()->MaxNumberToStringCacheSize();
1290 if (Subclass::HasElementImpl(isolate, *
object,
i, *backing_store,
1293 bool use_cache =
i < kMaxStringTableEntries;
1294 DirectHandle<String> index_string =
1295 isolate->factory()->SizeToString(
i, use_cache);
1296 list->set(insertion_index, *index_string);
1298 DirectHandle<Object> number =
1299 isolate->factory()->NewNumberFromSize(
i);
1300 list->set(insertion_index, *number);
1305 *nof_indices = insertion_index;
1309 MaybeHandle<FixedArray> PrependElementIndices(
1310 Isolate* isolate, DirectHandle<JSObject>
object,
1311 DirectHandle<FixedArrayBase> backing_store, DirectHandle<FixedArray> keys,
1313 return Subclass::PrependElementIndicesImpl(isolate,
object, backing_store,
1314 keys, convert, filter);
1317 static MaybeHandle<FixedArray> PrependElementIndicesImpl(
1318 Isolate* isolate, DirectHandle<JSObject>
object,
1319 DirectHandle<FixedArrayBase> backing_store, DirectHandle<FixedArray> keys,
1321 uint32_t nof_property_keys = keys->length();
1322 size_t initial_list_length =
1323 Subclass::GetMaxNumberOfEntries(isolate, *
object, *backing_store);
1327 NewRangeError(MessageTemplate::kInvalidArrayLength));
1329 initial_list_length += nof_property_keys;
1332 DCHECK_LE(initial_list_length, std::numeric_limits<int>::max());
1333 MaybeHandle<FixedArray> raw_array = isolate->factory()->TryNewFixedArray(
1334 static_cast<int>(initial_list_length));
1340 if (!raw_array.ToHandle(&combined_keys)) {
1346 initial_list_length =
1347 Subclass::NumberOfElementsImpl(isolate, *
object, *backing_store);
1348 initial_list_length += nof_property_keys;
1350 DCHECK_LE(initial_list_length, std::numeric_limits<int>::max());
1351 combined_keys = isolate->factory()->NewFixedArray(
1352 static_cast<int>(initial_list_length));
1355 uint32_t nof_indices = 0;
1358 combined_keys = Subclass::DirectCollectElementIndicesImpl(
1359 isolate,
object, backing_store,
1361 combined_keys, &nof_indices);
1363 if (needs_sorting) {
1364 SortIndices(isolate, combined_keys, nof_indices);
1368 for (uint32_t
i = 0;
i < nof_indices;
i++) {
1369 DirectHandle<Object> index_string =
1370 isolate->factory()->Uint32ToString(
1372 combined_keys->set(
i, *index_string);
1387 int final_size = nof_indices + nof_property_keys;
1388 DCHECK_LE(final_size, combined_keys->length());
1392 return combined_keys;
1396 DirectHandle<JSObject>
receiver, KeyAccumulator* accumulator,
1398 return Subclass::AddElementsToKeyAccumulatorImpl(
receiver, accumulator,
1404 return backing_store->length();
1409 return Subclass::GetCapacityImpl(holder, backing_store);
1412 static MaybeDirectHandle<Object> FillImpl(DirectHandle<JSObject>
receiver,
1413 DirectHandle<Object> obj_value,
1418 MaybeDirectHandle<Object> Fill(DirectHandle<JSObject>
receiver,
1419 DirectHandle<Object> obj_value,
size_t start,
1420 size_t end)
override {
1424 static Maybe<bool> IncludesValueImpl(Isolate* isolate,
1426 DirectHandle<Object> value,
1427 size_t start_from,
size_t length) {
1428 return IncludesValueSlowPath(isolate,
receiver, value, start_from, length);
1431 Maybe<bool> IncludesValue(Isolate* isolate, DirectHandle<JSObject>
receiver,
1432 DirectHandle<Object> value,
size_t start_from,
1433 size_t length)
final {
1434 return Subclass::IncludesValueImpl(isolate,
receiver, value, start_from,
1438 static Maybe<int64_t> IndexOfValueImpl(Isolate* isolate,
1440 DirectHandle<Object> value,
1441 size_t start_from,
size_t length) {
1442 return IndexOfValueSlowPath(isolate,
receiver, value, start_from, length);
1445 Maybe<int64_t> IndexOfValue(Isolate* isolate, DirectHandle<JSObject>
receiver,
1446 DirectHandle<Object> value,
size_t start_from,
1447 size_t length)
final {
1448 return Subclass::IndexOfValueImpl(isolate,
receiver, value, start_from,
1452 static Maybe<int64_t> LastIndexOfValueImpl(DirectHandle<JSObject>
receiver,
1453 DirectHandle<Object> value,
1454 size_t start_from) {
1458 Maybe<int64_t> LastIndexOfValue(DirectHandle<JSObject>
receiver,
1459 DirectHandle<Object> value,
1460 size_t start_from)
final {
1461 return Subclass::LastIndexOfValueImpl(
receiver, value, start_from);
1470 static InternalIndex GetEntryForIndexImpl(
1476 size_t length = Subclass::GetMaxIndex(holder, backing_store);
1480 index <=
static_cast<size_t>(std::numeric_limits<int>::max()));
1481 return index < length &&
1483 ->is_the_hole(isolate,
static_cast<int>(index))
1484 ? InternalIndex(index)
1485 : InternalIndex::NotFound();
1487 return index < length ? InternalIndex(index) : InternalIndex::NotFound();
1493 size_t index)
final {
1494 return Subclass::GetEntryForIndexImpl(isolate, holder, backing_store, index,
1499 InternalIndex entry) {
1505 InternalIndex entry) {
1511 InternalIndex entry)
final {
1512 return Subclass::GetDetailsImpl(holder, entry);
1516 DirectHandle<JSObject>
object,
1517 uint32_t length)
final {
1518 return Subclass::CreateListFromArrayLikeImpl(isolate,
object, length);
1522 Isolate* isolate, DirectHandle<JSObject>
object, uint32_t length) {
1527class DictionaryElementsAccessor
1528 :
public ElementsAccessorBase<DictionaryElementsAccessor,
1529 ElementsKindTraits<DICTIONARY_ELEMENTS>> {
1537 static uint32_t GetMaxNumberOfEntries(Isolate* isolate,
1540 return NumberOfElementsImpl(isolate,
receiver, backing_store);
1543 static uint32_t NumberOfElementsImpl(Isolate* isolate,
1547 return dict->NumberOfElements();
1550 static Maybe<bool> SetLengthImpl(Isolate* isolate,
1551 DirectHandle<JSArray> array, uint32_t length,
1552 DirectHandle<FixedArrayBase> backing_store) {
1554 uint32_t old_length = 0;
1558 ReadOnlyRoots roots(isolate);
1559 if (length < old_length) {
1560 if (dict->requires_slow_elements()) {
1563 for (InternalIndex entry : dict->IterateEntries()) {
1565 if (dict->IsKey(roots, index)) {
1568 if (length <= number && number < old_length) {
1569 PropertyDetails details = dict->DetailsAt(entry);
1570 if (!details.IsConfigurable()) length = number + 1;
1578 array->initialize_elements();
1581 int removed_entries = 0;
1582 for (InternalIndex entry : dict->IterateEntries()) {
1584 if (dict->IsKey(roots, index)) {
1587 if (length <= number && number < old_length) {
1588 dict->ClearEntry(entry);
1594 if (removed_entries > 0) {
1596 dict->ElementsRemoved(removed_entries);
1602 DirectHandle<Number> length_obj =
1603 isolate->factory()->NewNumberFromUint(length);
1604 array->set_length(*length_obj);
1611 int packed_size,
int copy_size) {
1615 static void DeleteImpl(DirectHandle<JSObject> obj, InternalIndex entry) {
1618 dict = NumberDictionary::DeleteEntry(obj->GetIsolate(), dict, entry);
1619 obj->set_elements(*dict);
1626 if (!dict->requires_slow_elements())
return false;
1629 for (InternalIndex
i : dict->IterateEntries()) {
1631 if (!dict->IsKey(roots,
key))
continue;
1632 PropertyDetails details = dict->DetailsAt(
i);
1639 InternalIndex entry) {
1641 return backing_store->ValueAt(entry);
1644 static Handle<Object> GetImpl(Isolate* isolate,
1646 InternalIndex entry) {
1647 return handle(GetRaw(backing_store, entry), isolate);
1650 static Handle<Object> GetAtomicInternalImpl(
1652 InternalIndex entry, SeqCstAccessTag tag) {
1657 static inline void SetImpl(DirectHandle<JSObject> holder, InternalIndex entry,
1659 SetImpl(holder->elements(), entry, value);
1669 SeqCstAccessTag tag) {
1673 static Handle<Object> SwapAtomicInternalImpl(
1675 InternalIndex entry,
Tagged<Object> value, SeqCstAccessTag tag) {
1685 ->ValueAtCompareAndSwap(entry, expected, value, tag);
1688 static void ReconfigureImpl(DirectHandle<JSObject>
object,
1689 DirectHandle<FixedArrayBase> store,
1690 InternalIndex entry, DirectHandle<Object> value,
1693 if (attributes !=
NONE)
object->RequireSlowElements(dictionary);
1694 dictionary->ValueAtPut(entry, *value);
1695 PropertyDetails details = dictionary->DetailsAt(entry);
1700 dictionary->DetailsAtPut(entry, details);
1703 static Maybe<bool> AddImpl(DirectHandle<JSObject>
object, uint32_t index,
1704 DirectHandle<Object> value,
1706 uint32_t new_capacity) {
1709 DirectHandle<NumberDictionary> dictionary =
1710 object->HasFastElements() ||
object->HasFastStringWrapperElements()
1713 object->GetIsolate());
1714 DirectHandle<NumberDictionary> new_dictionary = NumberDictionary::Add(
1715 object->GetIsolate(), dictionary, index, value, details);
1716 new_dictionary->UpdateMaxNumberKey(index,
object);
1717 if (attributes !=
NONE)
object->RequireSlowElements(*new_dictionary);
1718 if (dictionary.is_identical_to(new_dictionary))
return Just(
true);
1719 object->set_elements(*new_dictionary);
1724 InternalIndex entry) {
1728 return !IsTheHole(index, isolate);
1731 static InternalIndex GetEntryForIndexImpl(Isolate* isolate,
1738 DCHECK_LE(index, std::numeric_limits<uint32_t>::max());
1739 InternalIndex entry =
1740 dictionary->FindEntry(isolate,
static_cast<uint32_t
>(index));
1741 if (entry.is_not_found())
return entry;
1744 PropertyDetails details = dictionary->DetailsAt(entry);
1752 InternalIndex entry) {
1753 return GetDetailsImpl(holder->elements(), entry);
1757 InternalIndex entry) {
1761 static uint32_t FilterKey(DirectHandle<NumberDictionary> dictionary,
1766 PropertyDetails details = dictionary->DetailsAt(entry);
1768 if ((
int{attr} & filter) != 0)
return kMaxUInt32;
1772 static uint32_t GetKeyForEntryImpl(Isolate* isolate,
1773 DirectHandle<NumberDictionary> dictionary,
1774 InternalIndex entry,
1778 if (!dictionary->IsKey(ReadOnlyRoots(isolate), raw_key))
return kMaxUInt32;
1779 return FilterKey(dictionary, entry, raw_key, filter);
1783 DirectHandle<JSObject>
object, DirectHandle<FixedArrayBase> backing_store,
1784 KeyAccumulator* keys) {
1786 Isolate* isolate = keys->isolate();
1788 DirectHandle<FixedArray> elements = isolate->factory()->NewFixedArray(
1789 GetMaxNumberOfEntries(isolate, *
object, *backing_store));
1790 int insertion_index = 0;
1792 ReadOnlyRoots roots(isolate);
1793 for (InternalIndex
i : dictionary->IterateEntries()) {
1796 if (!dictionary->IsKey(roots, raw_key))
continue;
1797 uint32_t
key = FilterKey(dictionary,
i, raw_key, filter);
1800 keys->AddShadowingKey(raw_key, &allow_gc);
1803 elements->set(insertion_index, raw_key);
1806 SortIndices(isolate, elements, insertion_index);
1807 for (
int i = 0;
i < insertion_index;
i++) {
1814 Isolate* isolate, DirectHandle<JSObject>
object,
1817 uint32_t insertion_index = 0) {
1821 for (InternalIndex
i : dictionary->IterateEntries()) {
1822 uint32_t
key = GetKeyForEntryImpl(isolate, dictionary,
i, filter);
1824 DirectHandle<Object> index = isolate->factory()->NewNumberFromUint(
key);
1825 list->set(insertion_index, *index);
1828 *nof_indices = insertion_index;
1833 DirectHandle<JSObject>
receiver, KeyAccumulator* accumulator,
1835 Isolate* isolate = accumulator->isolate();
1836 DirectHandle<NumberDictionary> dictionary(
1838 ReadOnlyRoots roots(isolate);
1839 for (InternalIndex
i : dictionary->IterateEntries()) {
1841 if (!dictionary->IsKey(roots, k))
continue;
1843 DCHECK(!IsTheHole(value, isolate));
1844 DCHECK(!IsAccessorPair(value));
1845 DCHECK(!IsAccessorInfo(value));
1851 static bool IncludesValueFastPath(Isolate* isolate,
1853 DirectHandle<Object> value,
1854 size_t start_from,
size_t length,
1859 Tagged<Object> the_hole = ReadOnlyRoots(isolate).the_hole_value();
1860 Tagged<Object> undefined = ReadOnlyRoots(isolate).undefined_value();
1865 for (InternalIndex
i : dictionary->IterateEntries()) {
1867 if (k == the_hole)
continue;
1868 if (k == undefined)
continue;
1880 }
else if (!found) {
1890 static Maybe<bool> IncludesValueImpl(Isolate* isolate,
1892 DirectHandle<Object> value,
1893 size_t start_from,
size_t length) {
1895 bool search_for_hole = IsUndefined(*value, isolate);
1897 if (!search_for_hole) {
1899 if (DictionaryElementsAccessor::IncludesValueFastPath(
1905 USE(original_elements_kind);
1906 DirectHandle<NumberDictionary> dictionary(
1910 for (
size_t k = start_from; k <
length; ++k) {
1912 InternalIndex entry =
1913 dictionary->FindEntry(isolate,
static_cast<uint32_t
>(k));
1914 if (entry.is_not_found()) {
1915 if (search_for_hole)
return Just(
true);
1919 PropertyDetails details = GetDetailsImpl(*dictionary, entry);
1920 switch (details.kind()) {
1927 LookupIterator it(isolate,
receiver, k,
1931 DirectHandle<Object> element_k;
1941 return IncludesValueSlowPath(isolate,
receiver, value, k + 1,
1946 if (*dictionary ==
receiver->elements())
continue;
1953 return Just(search_for_hole);
1958 ElementsAccessor* accessor =
receiver->GetElementsAccessor();
1959 return accessor->IncludesValue(isolate,
receiver, value, k + 1,
1971 static Maybe<int64_t> IndexOfValueImpl(Isolate* isolate,
1973 DirectHandle<Object> value,
1974 size_t start_from,
size_t length) {
1978 USE(original_elements_kind);
1979 DirectHandle<NumberDictionary> dictionary(
1983 for (
size_t k = start_from; k <
length; ++k) {
1985 DCHECK_LE(k, std::numeric_limits<uint32_t>::max());
1986 InternalIndex entry =
1987 dictionary->FindEntry(isolate,
static_cast<uint32_t
>(k));
1988 if (entry.is_not_found())
continue;
1990 PropertyDetails details =
1991 GetDetailsImpl(*dictionary, InternalIndex(entry));
1992 switch (details.kind()) {
2001 LookupIterator it(isolate,
receiver, k,
2005 DirectHandle<Object> element_k;
2015 return IndexOfValueSlowPath(isolate,
receiver, value, k + 1,
2020 if (*dictionary ==
receiver->elements())
continue;
2025 return IndexOfValueSlowPath(isolate,
receiver, value, k + 1,
2041 if (!
v8_flags.enable_slow_asserts)
return;
2046 bool requires_slow_elements =
false;
2048 for (InternalIndex
i : dictionary->IterateEntries()) {
2050 if (!dictionary->ToKey(roots,
i, &k))
continue;
2054 requires_slow_elements =
true;
2059 if (requires_slow_elements) {
2060 DCHECK(dictionary->requires_slow_elements());
2061 }
else if (!dictionary->requires_slow_elements()) {
2062 DCHECK_LE(max_key, dictionary->max_number_key());
2069template <
typename Sub
class,
typename KindTraits>
2070class FastElementsAccessor :
public ElementsAccessorBase<Subclass, KindTraits> {
2072 using BackingStore =
typename KindTraits::BackingStore;
2074 static DirectHandle<NumberDictionary> NormalizeImpl(
2075 DirectHandle<JSObject>
object, DirectHandle<FixedArrayBase> store) {
2076 Isolate* isolate =
object->GetIsolate();
2083 isolate->UpdateNoElementsProtectorOnNormalizeElements(
object);
2086 int capacity =
object->GetFastElementsUsage();
2087 DirectHandle<NumberDictionary> dictionary =
2088 NumberDictionary::New(isolate, capacity);
2092 int max_number_key = -1;
2093 for (
int i = 0; j < capacity;
i++) {
2098 DirectHandle<Object> value =
2099 Subclass::GetImpl(isolate, *store, InternalIndex(
i));
2101 NumberDictionary::Add(isolate, dictionary,
i, value, details);
2105 if (max_number_key > 0) {
2106 dictionary->UpdateMaxNumberKey(
static_cast<uint32_t
>(max_number_key),
2112 static void DeleteAtEnd(DirectHandle<JSObject> obj,
2113 DirectHandle<BackingStore> backing_store,
2115 uint32_t length =
static_cast<uint32_t
>(backing_store->length());
2117 Isolate* isolate = obj->GetIsolate();
2118 for (; entry > 0; entry--) {
2119 if (!backing_store->is_the_hole(isolate, entry - 1))
break;
2128 obj->set_elements(empty);
2133 isolate->heap()->RightTrimArray(*backing_store, entry, length);
2136 static void DeleteCommon(DirectHandle<JSObject> obj, uint32_t entry,
2137 DirectHandle<FixedArrayBase> store) {
2138 DCHECK(obj->HasSmiOrObjectElements() || obj->HasDoubleElements() ||
2139 obj->HasNonextensibleElements() || obj->HasFastArgumentsElements() ||
2140 obj->HasFastStringWrapperElements());
2142 if (!IsJSArray(*obj) &&
2143 entry ==
static_cast<uint32_t
>(store->length()) - 1) {
2144 DeleteAtEnd(obj, backing_store, entry);
2148 Isolate* isolate = obj->GetIsolate();
2149 backing_store->set_the_hole(isolate, entry);
2154 const int kMinLengthForSparsenessCheck = 64;
2155 if (backing_store->length() < kMinLengthForSparsenessCheck)
return;
2156 uint32_t length = 0;
2157 if (IsJSArray(*obj)) {
2160 length =
static_cast<uint32_t
>(store->length());
2164 const int kLengthFraction = 16;
2169 static_assert(kLengthFraction >=
2170 NumberDictionary::kEntrySize *
2172 size_t current_counter = isolate->elements_deletion_counter();
2173 if (current_counter < length / kLengthFraction) {
2174 isolate->set_elements_deletion_counter(current_counter + 1);
2178 isolate->set_elements_deletion_counter(0);
2180 if (!IsJSArray(*obj)) {
2183 if (!backing_store->is_the_hole(isolate,
i))
break;
2186 DeleteAtEnd(obj, backing_store, entry);
2191 for (
int i = 0;
i < backing_store->
length(); ++
i) {
2192 if (!backing_store->is_the_hole(isolate,
i)) {
2196 NumberDictionary::ComputeCapacity(num_used) *
2197 NumberDictionary::kEntrySize >
2198 static_cast<uint32_t
>(backing_store->length())) {
2206 static void ReconfigureImpl(DirectHandle<JSObject>
object,
2207 DirectHandle<FixedArrayBase> store,
2208 InternalIndex entry, DirectHandle<Object> value,
2210 DirectHandle<NumberDictionary> dictionary =
2212 entry = InternalIndex(
2213 dictionary->FindEntry(object->GetIsolate(), entry.as_uint32()));
2214 DictionaryElementsAccessor::ReconfigureImpl(
2218 static Maybe<bool> AddImpl(DirectHandle<JSObject>
object, uint32_t index,
2219 DirectHandle<Object> value,
2221 uint32_t new_capacity) {
2227 Subclass::GetCapacityImpl(*
object, object->elements()) !=
2229 MAYBE_RETURN(Subclass::GrowCapacityAndConvertImpl(
object, new_capacity),
2240 Subclass::SetImpl(
object, InternalIndex(index), *value);
2244 static void DeleteImpl(DirectHandle<JSObject> obj, InternalIndex entry) {
2254 DeleteCommon(obj, entry.as_uint32(),
2258 static bool HasEntryImpl(Isolate* isolate,
2260 InternalIndex entry) {
2262 ->is_the_hole(isolate, entry.as_int());
2265 static uint32_t NumberOfElementsImpl(Isolate* isolate,
2268 size_t max_index = Subclass::GetMaxIndex(
receiver, backing_store);
2269 DCHECK_LE(max_index, std::numeric_limits<uint32_t>::max());
2271 return static_cast<uint32_t
>(max_index);
2274 for (
size_t i = 0;
i < max_index;
i++) {
2275 if (Subclass::HasEntryImpl(isolate, backing_store, InternalIndex(
i))) {
2283 DirectHandle<JSObject>
receiver, KeyAccumulator* accumulator,
2285 Isolate* isolate = accumulator->isolate();
2286 DirectHandle<FixedArrayBase> elements(
receiver->elements(), isolate);
2288 Subclass::GetMaxNumberOfEntries(isolate, *
receiver, *elements);
2291 HasEntryImpl(isolate, *elements, InternalIndex(
i))) {
2293 Subclass::GetImpl(isolate, *elements, InternalIndex(
i)), convert));
2301 Isolate* isolate = holder->GetIsolate();
2302 Heap*
heap = isolate->heap();
2304 Tagged<Map> map = elements->map();
2306 DCHECK_NE(map, ReadOnlyRoots(
heap).fixed_double_array_map());
2309 if (map == ReadOnlyRoots(
heap).fixed_array_map())
DCHECK_EQ(0u, length);
2313 if (length == 0u)
return;
2314#if ENABLE_SLOW_DCHECKS
2317 DCHECK(length <= std::numeric_limits<int>::max());
2318 int length_int =
static_cast<int>(
length);
2320 HandleScope scope(isolate);
2321 for (
int i = 0;
i < length_int;
i++) {
2324 IsTheHole(element, isolate)));
2328 for (
int i = 0;
i < length_int;
i++) {
2329 DCHECK(!backing_store->is_the_hole(isolate,
i));
2338 static MaybeDirectHandle<Object> PopImpl(DirectHandle<JSArray>
receiver) {
2339 return Subclass::RemoveElement(
receiver, AT_END);
2342 static MaybeDirectHandle<Object> ShiftImpl(DirectHandle<JSArray>
receiver) {
2343 return Subclass::RemoveElement(
receiver, AT_START);
2346 static Maybe<uint32_t> PushImpl(DirectHandle<JSArray>
receiver,
2347 BuiltinArguments*
args, uint32_t push_size) {
2348 DirectHandle<FixedArrayBase> backing_store(
receiver->elements(),
2350 return Subclass::AddArguments(
receiver, backing_store,
args, push_size,
2354 static Maybe<uint32_t> UnshiftImpl(DirectHandle<JSArray>
receiver,
2355 BuiltinArguments*
args,
2356 uint32_t unshift_size) {
2357 DirectHandle<FixedArrayBase> backing_store(
receiver->elements(),
2359 return Subclass::AddArguments(
receiver, backing_store,
args, unshift_size,
2363 static DirectHandle<FixedArrayBase> MoveElements(
2364 Isolate* isolate, DirectHandle<JSArray>
receiver,
2365 DirectHandle<FixedArrayBase> backing_store,
int dst_index,
int src_index,
2366 int len,
int hole_start,
int hole_end) {
2370 isolate->heap()->CanMoveObjectStart(dst_elms)) {
2372 isolate->heap()->LeftTrimFixedArray(dst_elms, src_index));
2374 backing_store.SetValue(dst_elms);
2377 hole_end -= src_index;
2378 DCHECK_LE(hole_start, backing_store->length());
2379 DCHECK_LE(hole_end, backing_store->length());
2380 }
else if (len != 0) {
2382 GetWriteBarrierMode(dst_elms, KindTraits::Kind, no_gc);
2383 dst_elms->MoveElements(isolate, dst_index, src_index, len, mode);
2385 if (hole_start != hole_end) {
2386 dst_elms->FillWithHoles(hole_start, hole_end);
2388 return backing_store;
2391 static MaybeDirectHandle<Object> FillImpl(DirectHandle<JSObject>
receiver,
2392 DirectHandle<Object> obj_value,
2413 Subclass::SetImpl(
receiver, InternalIndex(index), *obj_value);
2415 return MaybeDirectHandle<Object>(
receiver);
2418 static Maybe<bool> IncludesValueImpl(Isolate* isolate,
2420 DirectHandle<Object> search_value,
2421 size_t start_from,
size_t length) {
2425 Tagged<Object> the_hole = ReadOnlyRoots(isolate).the_hole_value();
2426 Tagged<Object> undefined = ReadOnlyRoots(isolate).undefined_value();
2429 if (start_from >= length)
return Just(
false);
2432 size_t elements_length =
static_cast<size_t>(elements_base->length());
2433 if (value == undefined && elements_length < length)
return Just(
true);
2434 if (elements_length == 0) {
2439 length = std::min(elements_length, length);
2440 DCHECK_LE(length, std::numeric_limits<int>::max());
2443 if (value == undefined) {
2452 for (
size_t k = start_from; k <
length; ++k) {
2455 if (element_k == the_hole || element_k == undefined) {
2467 for (
size_t k = start_from; k <
length; ++k) {
2468 if (elements->is_the_hole(
static_cast<int>(k)))
return Just(
true);
2486 for (
size_t k = start_from; k <
length; ++k) {
2488 if (element_k == the_hole)
continue;
2494 if (!
IsNaN(value)) {
2503 for (
size_t k = start_from; k <
length; ++k) {
2504 if (elements->is_the_hole(
static_cast<int>(k)))
continue;
2505 if (elements->get_scalar(
static_cast<int>(k)) == search_number) {
2516 for (
size_t k = start_from; k <
length; ++k) {
2537 for (
size_t k = start_from; k <
length; ++k) {
2538 if (elements->is_the_hole(
static_cast<int>(k)))
continue;
2539 if (std::isnan(elements->get_scalar(
static_cast<int>(k)))) {
2551 for (
size_t k = start_from; k <
length; ++k) {
2552 if (
IsNaN(elements->get(
static_cast<int>(k))))
return Just(
true);
2561 Isolate* isolate, DirectHandle<JSObject>
object, uint32_t length) {
2563 DirectHandle<FixedArrayBase> elements(object->elements(), isolate);
2565 InternalIndex entry(
i);
2566 if (!Subclass::HasEntryImpl(isolate, *elements, entry))
continue;
2567 DirectHandle<Object>
value;
2568 value = Subclass::GetImpl(isolate, *elements, entry);
2569 if (IsName(*value)) {
2570 value = isolate->factory()->InternalizeName(
Cast<Name>(value));
2577 static MaybeDirectHandle<Object> RemoveElement(DirectHandle<JSArray>
receiver,
2578 Where remove_position) {
2579 Isolate* isolate =
receiver->GetIsolate();
2582 HandleScope scope(isolate);
2585 DirectHandle<FixedArrayBase> backing_store(
receiver->elements(), isolate);
2589 int remove_index = remove_position == AT_START ? 0 :
new_length;
2590 DirectHandle<Object>
result =
2591 Subclass::GetImpl(isolate, *backing_store, InternalIndex(remove_index));
2592 if (remove_position == AT_START) {
2593 backing_store = Subclass::MoveElements(isolate,
receiver, backing_store,
2600 return isolate->factory()->undefined_value();
2602 return MaybeDirectHandle<Object>(
result);
2605 static Maybe<uint32_t> AddArguments(
2607 DirectHandle<FixedArrayBase> backing_store, BuiltinArguments*
args,
2608 uint32_t add_size, Where add_position) {
2611 uint32_t elms_len = backing_store->length();
2615 Isolate* isolate =
receiver->GetIsolate();
2621 int copy_dst_index = add_position == AT_START ? add_size : 0;
2624 isolate, backing_store,
2625 Subclass::ConvertElementsWithCapacity(
receiver, backing_store,
2626 KindTraits::Kind, capacity, 0,
2629 receiver->set_elements(*backing_store);
2630 }
else if (add_position == AT_START) {
2633 backing_store = Subclass::MoveElements(isolate,
receiver, backing_store,
2634 add_size, 0, length, 0, 0);
2637 int insertion_index = add_position == AT_START ? 0 :
length;
2639 Subclass::CopyArguments(
args, backing_store, add_size, 1, insertion_index);
2645 static void CopyArguments(BuiltinArguments*
args,
2646 DirectHandle<FixedArrayBase> dst_store,
2647 uint32_t copy_size, uint32_t src_index,
2648 uint32_t dst_index) {
2653 for (uint32_t
i = 0;
i < copy_size;
i++) {
2655 DCHECK(!IsTheHole(argument));
2656 Subclass::SetImpl(raw_backing_store, InternalIndex(dst_index +
i),
2662template <
typename Sub
class,
typename KindTraits>
2663class FastSmiOrObjectElementsAccessor
2664 :
public FastElementsAccessor<Subclass, KindTraits> {
2666 static inline void SetImpl(DirectHandle<JSObject> holder, InternalIndex entry,
2668 SetImpl(holder->elements(), entry, value);
2683 InternalIndex entry) {
2684 return backing_store->get(entry.as_int());
2695 int packed_size,
int copy_size) {
2698 switch (from_kind) {
2710 CopyObjectToObjectElements(isolate, from, from_kind, from_start, to,
2711 to_kind, to_start, copy_size);
2717 CopyDoubleToObjectElements(isolate, from, from_start, to, to_start,
2722 CopyDictionaryToObjectElements(isolate, from, from_start, to, to_kind,
2723 to_start, copy_size);
2729#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS:
2732#undef TYPED_ARRAY_CASE
2742 static Maybe<bool> CollectValuesOrEntriesImpl(
2743 Isolate* isolate, DirectHandle<JSObject>
object,
2744 DirectHandle<FixedArray> values_or_entries,
bool get_entries,
2751 uint32_t length = elements->length();
2752 for (uint32_t index = 0; index <
length; ++
index) {
2753 InternalIndex entry(index);
2754 if (!Subclass::HasEntryImpl(isolate, *elements, entry))
continue;
2755 DirectHandle<Object> value =
2756 Subclass::GetImpl(isolate, *elements, entry);
2758 values_or_entries->set(count++, *value);
2764 uint32_t length = elements->length();
2765 for (uint32_t index = 0; index <
length; ++
index) {
2766 InternalIndex entry(index);
2767 if (!Subclass::HasEntryImpl(isolate, elements, entry))
continue;
2769 values_or_entries->set(count++, value);
2776 static Maybe<int64_t> IndexOfValueImpl(Isolate* isolate,
2778 DirectHandle<Object> search_value,
2779 size_t start_from,
size_t length) {
2787 length = std::min(
static_cast<size_t>(elements_base->length()), length);
2803 std::numeric_limits<uint32_t>::max());
2804 for (
size_t k = start_from; k <
length; ++k) {
2806 elements->get(
static_cast<uint32_t
>(k)))) {
2814class FastPackedSmiElementsAccessor
2815 :
public FastSmiOrObjectElementsAccessor<
2816 FastPackedSmiElementsAccessor,
2817 ElementsKindTraits<PACKED_SMI_ELEMENTS>> {};
2819class FastHoleySmiElementsAccessor
2820 :
public FastSmiOrObjectElementsAccessor<
2821 FastHoleySmiElementsAccessor,
2822 ElementsKindTraits<HOLEY_SMI_ELEMENTS>> {};
2824class FastPackedObjectElementsAccessor
2825 :
public FastSmiOrObjectElementsAccessor<
2826 FastPackedObjectElementsAccessor,
2827 ElementsKindTraits<PACKED_ELEMENTS>> {};
2829template <
typename Sub
class,
typename KindTraits>
2830class FastNonextensibleObjectElementsAccessor
2831 :
public FastSmiOrObjectElementsAccessor<Subclass, KindTraits> {
2833 using BackingStore =
typename KindTraits::BackingStore;
2835 static Maybe<uint32_t> PushImpl(DirectHandle<JSArray>
receiver,
2836 BuiltinArguments*
args, uint32_t push_size) {
2840 static Maybe<bool> AddImpl(DirectHandle<JSObject>
object, uint32_t index,
2841 DirectHandle<Object> value,
2843 uint32_t new_capacity) {
2850 static Maybe<bool> SetLengthImpl(Isolate* isolate,
2851 DirectHandle<JSArray> array, uint32_t length,
2852 DirectHandle<FixedArrayBase> backing_store) {
2853 uint32_t old_length = 0;
2855 if (length == old_length) {
2862 DirectHandle<NumberDictionary> new_element_dictionary =
2863 old_length == 0 ? isolate->factory()->empty_slow_element_dictionary()
2864 : array->GetElementsAccessor()->Normalize(array);
2867 DirectHandle<Map> new_map =
2869 "SlowCopyForSetLengthImpl");
2870 new_map->set_is_extensible(
false);
2874 if (!new_element_dictionary.is_null()) {
2875 array->set_elements(*new_element_dictionary);
2878 if (array->elements() !=
2879 ReadOnlyRoots(isolate).empty_slow_element_dictionary()) {
2880 DirectHandle<NumberDictionary> dictionary(array->element_dictionary(),
2883 array->RequireSlowElements(*dictionary);
2890 DirectHandle<FixedArrayBase> new_backing_store(array->elements(), isolate);
2891 return DictionaryElementsAccessor::SetLengthImpl(isolate, array, length,
2896class FastPackedNonextensibleObjectElementsAccessor
2897 :
public FastNonextensibleObjectElementsAccessor<
2898 FastPackedNonextensibleObjectElementsAccessor,
2899 ElementsKindTraits<PACKED_NONEXTENSIBLE_ELEMENTS>> {};
2901class FastHoleyNonextensibleObjectElementsAccessor
2902 :
public FastNonextensibleObjectElementsAccessor<
2903 FastHoleyNonextensibleObjectElementsAccessor,
2904 ElementsKindTraits<HOLEY_NONEXTENSIBLE_ELEMENTS>> {};
2906template <
typename Sub
class,
typename KindTraits>
2907class FastSealedObjectElementsAccessor
2908 :
public FastSmiOrObjectElementsAccessor<Subclass, KindTraits> {
2910 using BackingStore =
typename KindTraits::BackingStore;
2912 static DirectHandle<Object> RemoveElement(DirectHandle<JSArray>
receiver,
2913 Where remove_position) {
2917 static void DeleteImpl(DirectHandle<JSObject> obj, InternalIndex entry) {
2921 static void DeleteAtEnd(DirectHandle<JSObject> obj,
2922 DirectHandle<BackingStore> backing_store,
2927 static void DeleteCommon(DirectHandle<JSObject> obj, uint32_t entry,
2928 DirectHandle<FixedArrayBase> store) {
2932 static MaybeDirectHandle<Object> PopImpl(DirectHandle<JSArray>
receiver) {
2936 static Maybe<uint32_t> PushImpl(DirectHandle<JSArray>
receiver,
2937 BuiltinArguments*
args, uint32_t push_size) {
2941 static Maybe<bool> AddImpl(DirectHandle<JSObject>
object, uint32_t index,
2942 DirectHandle<Object> value,
2944 uint32_t new_capacity) {
2951 static Maybe<bool> SetLengthImpl(Isolate* isolate,
2952 DirectHandle<JSArray> array, uint32_t length,
2953 DirectHandle<FixedArrayBase> backing_store) {
2954 uint32_t old_length = 0;
2956 if (length == old_length) {
2963 DirectHandle<NumberDictionary> new_element_dictionary =
2964 old_length == 0 ? isolate->factory()->empty_slow_element_dictionary()
2965 : array->GetElementsAccessor()->Normalize(array);
2968 DirectHandle<Map> new_map =
2970 "SlowCopyForSetLengthImpl");
2971 new_map->set_is_extensible(
false);
2975 if (!new_element_dictionary.is_null()) {
2976 array->set_elements(*new_element_dictionary);
2979 if (array->elements() !=
2980 ReadOnlyRoots(isolate).empty_slow_element_dictionary()) {
2981 DirectHandle<NumberDictionary> dictionary(array->element_dictionary(),
2984 array->RequireSlowElements(*dictionary);
2991 DirectHandle<FixedArrayBase> new_backing_store(array->elements(), isolate);
2992 return DictionaryElementsAccessor::SetLengthImpl(isolate, array, length,
2997class FastPackedSealedObjectElementsAccessor
2998 :
public FastSealedObjectElementsAccessor<
2999 FastPackedSealedObjectElementsAccessor,
3000 ElementsKindTraits<PACKED_SEALED_ELEMENTS>> {};
3002class SharedArrayElementsAccessor
3003 :
public FastSealedObjectElementsAccessor<
3004 SharedArrayElementsAccessor,
3005 ElementsKindTraits<SHARED_ARRAY_ELEMENTS>> {
3007 static Handle<Object> GetAtomicInternalImpl(
3009 InternalIndex entry, SeqCstAccessTag tag) {
3016 SeqCstAccessTag tag) {
3020 static Handle<Object> SwapAtomicInternalImpl(
3022 InternalIndex entry,
Tagged<Object> value, SeqCstAccessTag tag) {
3032 ->compare_and_swap(entry.as_int(), expected, value, tag);
3036class FastHoleySealedObjectElementsAccessor
3037 :
public FastSealedObjectElementsAccessor<
3038 FastHoleySealedObjectElementsAccessor,
3039 ElementsKindTraits<HOLEY_SEALED_ELEMENTS>> {};
3041template <
typename Sub
class,
typename KindTraits>
3042class FastFrozenObjectElementsAccessor
3043 :
public FastSmiOrObjectElementsAccessor<Subclass, KindTraits> {
3045 using BackingStore =
typename KindTraits::BackingStore;
3047 static inline void SetImpl(DirectHandle<JSObject> holder, InternalIndex entry,
3063 static DirectHandle<Object> RemoveElement(DirectHandle<JSArray>
receiver,
3064 Where remove_position) {
3068 static void DeleteImpl(DirectHandle<JSObject> obj, InternalIndex entry) {
3072 static void DeleteAtEnd(DirectHandle<JSObject> obj,
3073 DirectHandle<BackingStore> backing_store,
3078 static void DeleteCommon(DirectHandle<JSObject> obj, uint32_t entry,
3079 DirectHandle<FixedArrayBase> store) {
3083 static MaybeDirectHandle<Object> PopImpl(DirectHandle<JSArray>
receiver) {
3087 static Maybe<uint32_t> PushImpl(DirectHandle<JSArray>
receiver,
3088 BuiltinArguments*
args, uint32_t push_size) {
3092 static Maybe<bool> AddImpl(DirectHandle<JSObject>
object, uint32_t index,
3093 DirectHandle<Object> value,
3095 uint32_t new_capacity) {
3099 static Maybe<bool> SetLengthImpl(Isolate* isolate,
3100 DirectHandle<JSArray> array, uint32_t length,
3101 DirectHandle<FixedArrayBase> backing_store) {
3105 static void ReconfigureImpl(DirectHandle<JSObject>
object,
3106 DirectHandle<FixedArrayBase> store,
3107 InternalIndex entry, DirectHandle<Object> value,
3113class FastPackedFrozenObjectElementsAccessor
3114 :
public FastFrozenObjectElementsAccessor<
3115 FastPackedFrozenObjectElementsAccessor,
3116 ElementsKindTraits<PACKED_FROZEN_ELEMENTS>> {};
3118class FastHoleyFrozenObjectElementsAccessor
3119 :
public FastFrozenObjectElementsAccessor<
3120 FastHoleyFrozenObjectElementsAccessor,
3121 ElementsKindTraits<HOLEY_FROZEN_ELEMENTS>> {};
3123class FastHoleyObjectElementsAccessor
3124 :
public FastSmiOrObjectElementsAccessor<
3125 FastHoleyObjectElementsAccessor, ElementsKindTraits<HOLEY_ELEMENTS>> {
3131 typename SourceElementType>
3132struct CopyBetweenBackingStoresImpl;
3134template <
typename Sub
class,
typename KindTraits>
3135class FastDoubleElementsAccessor
3136 :
public FastElementsAccessor<Subclass, KindTraits> {
3138 static Handle<Object> GetImpl(Isolate* isolate,
3140 InternalIndex entry) {
3142 entry.as_int(), isolate);
3145 static inline void SetImpl(DirectHandle<JSObject> holder, InternalIndex entry,
3147 SetImpl(holder->elements(), entry, value);
3152#ifdef V8_ENABLE_EXPERIMENTAL_UNDEFINED_DOUBLE
3153 if (IsUndefined(value)) {
3172 int packed_size,
int copy_size) {
3174 switch (from_kind) {
3176 CopyPackedSmiToDoubleElements(from, from_start, to, to_start,
3177 packed_size, copy_size);
3180 CopySmiToDoubleElements(from, from_start, to, to_start, copy_size);
3184 CopyDoubleToDoubleElements(from, from_start, to, to_start, copy_size);
3195 CopyObjectToDoubleElements(from, from_start, to, to_start, copy_size);
3198 CopyDictionaryToDoubleElements(isolate, from, from_start, to, to_start,
3207#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS:
3210#undef TYPED_ARRAY_CASE
3217 static Maybe<bool> CollectValuesOrEntriesImpl(
3218 Isolate* isolate, DirectHandle<JSObject>
object,
3219 DirectHandle<FixedArray> values_or_entries,
bool get_entries,
3221 DirectHandle<FixedDoubleArray> elements(
3224 uint32_t length = elements->length();
3225 for (uint32_t index = 0; index <
length; ++
index) {
3226 InternalIndex entry(index);
3227 if (!Subclass::HasEntryImpl(isolate, *elements, entry))
continue;
3228 DirectHandle<Object> value = Subclass::GetImpl(isolate, *elements, entry);
3232 values_or_entries->set(count++, *value);
3238 static Maybe<int64_t> IndexOfValueImpl(Isolate* isolate,
3240 DirectHandle<Object> search_value,
3241 size_t start_from,
size_t length) {
3247 length = std::min(
static_cast<size_t>(elements_base->length()), length);
3262 std::numeric_limits<int>::max());
3263 for (
size_t k = start_from; k <
length; ++k) {
3264 int k_int =
static_cast<int>(k);
3265 if (elements->is_the_hole(k_int)) {
3268 if (elements->get_scalar(k_int) == numeric_search_value) {
3276class FastPackedDoubleElementsAccessor
3277 :
public FastDoubleElementsAccessor<
3278 FastPackedDoubleElementsAccessor,
3279 ElementsKindTraits<PACKED_DOUBLE_ELEMENTS>> {};
3281class FastHoleyDoubleElementsAccessor
3282 :
public FastDoubleElementsAccessor<
3283 FastHoleyDoubleElementsAccessor,
3284 ElementsKindTraits<HOLEY_DOUBLE_ELEMENTS>> {};
3286enum IsSharedBuffer :
bool {
kShared =
true, kUnshared =
false };
3288constexpr bool IsFloat16RawBitsZero(uint16_t
x) {
3291 return (
x & ~0x8000) == 0;
3295template <ElementsKind Kind,
typename ElementType>
3296class TypedElementsAccessor
3297 :
public ElementsAccessorBase<TypedElementsAccessor<Kind, ElementType>,
3298 ElementsKindTraits<Kind>> {
3300 using BackingStore =
typename ElementsKindTraits<Kind>::BackingStore;
3301 using AccessorClass = TypedElementsAccessor<Kind, ElementType>;
3304 static ElementType FromScalar(
int value) {
3305 return static_cast<ElementType
>(
value);
3307 static ElementType FromScalar(uint32_t value) {
3308 return static_cast<ElementType
>(
value);
3310 static ElementType FromScalar(
double value) {
3313 static ElementType FromScalar(int64_t value) {
UNREACHABLE(); }
3314 static ElementType FromScalar(uint64_t value) {
UNREACHABLE(); }
3318 bool* lossless =
nullptr) {
3321 }
else if (IsHeapNumber(value)) {
3326 DCHECK(IsUndefined(value));
3330 static ElementType FromHandle(DirectHandle<Object> value,
3331 bool* lossless =
nullptr) {
3332 return FromObject(*value, lossless);
3336 static Handle<Object> ToHandle(Isolate* isolate, ElementType value);
3338 static void SetImpl(DirectHandle<JSObject> holder, InternalIndex entry,
3341 DCHECK_LE(entry.raw_value(), typed_array->GetLength());
3343 static_cast<ElementType*
>(typed_array->DataPtr()) + entry.raw_value();
3345 SetImpl(entry_ptr, FromObject(value),
is_shared);
3348 static void SetImpl(ElementType* data_ptr, ElementType value,
3363 if (
IsAligned(
reinterpret_cast<uintptr_t
>(data_ptr),
3364 alignof(std::atomic<ElementType>))) {
3366 static_assert(
sizeof(std::atomic<ElementType>) ==
sizeof(ElementType));
3367 reinterpret_cast<std::atomic<ElementType>*
>(data_ptr)->
store(
3368 value, std::memory_order_relaxed);
3383 constexpr size_t kNumWords =
3384 std::max(
size_t{1},
sizeof(ElementType) /
kInt32Size);
3385 uint32_t words[kNumWords];
3386 CHECK_EQ(
sizeof(words),
sizeof(value));
3387 memcpy(words, &value,
sizeof(value));
3388 for (
size_t word = 0; word < kNumWords; ++word) {
3389 static_assert(
sizeof(std::atomic<uint32_t>) ==
sizeof(uint32_t));
3390 reinterpret_cast<std::atomic<uint32_t>*
>(data_ptr)[word].
store(
3391 words[word], std::memory_order_relaxed);
3395 static Handle<Object> GetInternalImpl(Isolate* isolate,
3396 DirectHandle<JSObject> holder,
3397 InternalIndex entry) {
3399 DCHECK_LT(entry.raw_value(), typed_array->GetLength());
3400 DCHECK(!typed_array->IsDetachedOrOutOfBounds());
3402 static_cast<ElementType*
>(typed_array->DataPtr()) + entry.raw_value();
3404 ElementType elem = GetImpl(element_ptr,
is_shared);
3405 return ToHandle(isolate, elem);
3408 static DirectHandle<Object> GetImpl(Isolate* isolate,
3410 InternalIndex entry) {
3414 static ElementType GetImpl(ElementType* data_ptr, IsSharedBuffer
is_shared) {
3420 reinterpret_cast<Address>(data_ptr));
3427 if (
IsAligned(
reinterpret_cast<uintptr_t
>(data_ptr),
3428 alignof(std::atomic<ElementType>))) {
3430 static_assert(
sizeof(std::atomic<ElementType>) ==
sizeof(ElementType));
3434 return reinterpret_cast<std::atomic<ElementType>*
>(data_ptr)->load(
3435 std::memory_order_acquire);
3449 constexpr size_t kNumWords =
3450 std::max(
size_t{1},
sizeof(ElementType) /
kInt32Size);
3451 uint32_t words[kNumWords];
3452 for (
size_t word = 0; word < kNumWords; ++word) {
3453 static_assert(
sizeof(std::atomic<uint32_t>) ==
sizeof(uint32_t));
3455 reinterpret_cast<std::atomic<uint32_t>*
>(data_ptr)[word].load(
3456 std::memory_order_relaxed);
3465 InternalIndex entry) {
3471 InternalIndex entry) {
3479 return index < AccessorClass::GetCapacityImpl(holder, backing_store);
3487 static Maybe<bool> SetLengthImpl(Isolate* isolate,
3488 DirectHandle<JSArray> array, uint32_t length,
3489 DirectHandle<FixedArrayBase> backing_store) {
3494 static void DeleteImpl(DirectHandle<JSObject> obj, InternalIndex entry) {
3501 static InternalIndex GetEntryForIndexImpl(
3505 return index < AccessorClass::GetCapacityImpl(holder, backing_store)
3506 ? InternalIndex(index)
3507 : InternalIndex::NotFound();
3513 return typed_array->GetLength();
3516 static size_t NumberOfElementsImpl(Isolate* isolate,
3519 return AccessorClass::GetCapacityImpl(
receiver, backing_store);
3523 DirectHandle<JSObject>
receiver, KeyAccumulator* accumulator,
3525 Isolate* isolate =
receiver->GetIsolate();
3526 DirectHandle<FixedArrayBase> elements(
receiver->elements(), isolate);
3527 size_t length = AccessorClass::GetCapacityImpl(*
receiver, *elements);
3529 DirectHandle<Object> value =
3530 AccessorClass::GetInternalImpl(isolate,
receiver, InternalIndex(
i));
3536 static Maybe<bool> CollectValuesOrEntriesImpl(
3537 Isolate* isolate, DirectHandle<JSObject>
object,
3538 DirectHandle<FixedArray> values_or_entries,
bool get_entries,
3542 DirectHandle<FixedArrayBase> elements(object->elements(), isolate);
3543 size_t length = AccessorClass::GetCapacityImpl(*
object, *elements);
3545 DirectHandle<Object> value = AccessorClass::GetInternalImpl(
3546 isolate,
object, InternalIndex(index));
3550 values_or_entries->set(count++, *value);
3557 static bool ToTypedSearchValue(
double search_value,
3558 ElementType* typed_search_value) {
3559 if (!base::IsValueInRangeForNumericType<ElementType>(search_value) &&
3560 std::isfinite(search_value)) {
3564 ElementType typed_value;
3566 typed_value = fp16_ieee_from_fp32_value(
static_cast<float>(search_value));
3567 *typed_search_value = typed_value;
3568 return (
static_cast<double>(fp16_ieee_to_fp32_value(typed_value)) !=
3571 typed_value =
static_cast<ElementType
>(search_value);
3572 *typed_search_value = typed_value;
3573 return static_cast<double>(typed_value) !=
3577 static MaybeDirectHandle<Object> FillImpl(DirectHandle<JSObject>
receiver,
3578 DirectHandle<Object> value,
3581 DCHECK(!typed_array->IsDetachedOrOutOfBounds());
3585 ElementType scalar = FromHandle(value);
3586 ElementType* data =
static_cast<ElementType*
>(typed_array->DataPtr());
3587 ElementType* first = data +
start;
3588 ElementType* last = data +
end;
3589 if (typed_array->buffer()->is_shared()) {
3594 for (; first != last; ++first) {
3595 AccessorClass::SetImpl(first, scalar,
kShared);
3597 }
else if ((scalar == 0 && !(std::is_floating_point_v<ElementType> &&
3599 (std::is_integral_v<ElementType> &&
3600 scalar ==
static_cast<ElementType
>(-1))) {
3604 size_t num_bytes =
static_cast<size_t>(
reinterpret_cast<int8_t*
>(last) -
3605 reinterpret_cast<int8_t*
>(first));
3606 memset(first,
static_cast<int8_t
>(scalar), num_bytes);
3609 std::fill(UnalignedSlot<ElementType>(first),
3610 UnalignedSlot<ElementType>(last), scalar);
3612 std::fill(first, last, scalar);
3614 return MaybeDirectHandle<Object>(typed_array);
3617 static Maybe<bool> IncludesValueImpl(Isolate* isolate,
3619 DirectHandle<Object> value,
3620 size_t start_from,
size_t length) {
3624 bool out_of_bounds =
false;
3625 size_t new_length = typed_array->GetLengthOrOutOfBounds(out_of_bounds);
3627 return Just(IsUndefined(*value, isolate) && length > start_from);
3633 if (IsUndefined(*value, isolate) && length > start_from) {
3639 ElementType typed_search_value;
3640 ElementType* data_ptr =
3641 reinterpret_cast<ElementType*
>(typed_array->DataPtr());
3643 if (Kind == BIGINT64_ELEMENTS || Kind == BIGUINT64_ELEMENTS ||
3644 Kind == RAB_GSAB_BIGINT64_ELEMENTS ||
3645 Kind == RAB_GSAB_BIGUINT64_ELEMENTS) {
3646 if (!IsBigInt(*value))
return Just(
false);
3648 typed_search_value = FromHandle(value, &lossless);
3649 if (!lossless)
return Just(
false);
3653 if (!std::isfinite(search_value)) {
3658 if (std::isnan(search_value)) {
3659 for (
size_t k = start_from; k <
length; ++k) {
3661 float elem_k = fp16_ieee_to_fp32_value(
3662 AccessorClass::GetImpl(data_ptr + k,
is_shared));
3663 if (std::isnan(elem_k))
return Just(
true);
3665 double elem_k =
static_cast<double>(
3666 AccessorClass::GetImpl(data_ptr + k,
is_shared));
3667 if (std::isnan(elem_k))
return Just(
true);
3673 for (
size_t k = start_from; k <
length; ++k) {
3674 ElementType elem_k = AccessorClass::GetImpl(data_ptr + k,
is_shared);
3675 if (IsFloat16RawBitsZero(elem_k))
return Just(
true);
3680 if (AccessorClass::ToTypedSearchValue(search_value,
3681 &typed_search_value)) {
3686 for (
size_t k = start_from; k <
length; ++k) {
3687 ElementType elem_k = AccessorClass::GetImpl(data_ptr + k,
is_shared);
3688 if (elem_k == typed_search_value)
return Just(
true);
3693 static Maybe<int64_t> IndexOfValueImpl(Isolate* isolate,
3695 DirectHandle<Object> value,
3696 size_t start_from,
size_t length) {
3704 bool out_of_bounds =
false;
3705 size_t typed_array_length =
3706 typed_array->GetLengthOrOutOfBounds(out_of_bounds);
3713 if (typed_array_length < length) {
3714 length = typed_array_length;
3718 ElementType typed_search_value;
3720 ElementType* data_ptr =
3721 reinterpret_cast<ElementType*
>(typed_array->DataPtr());
3725 typed_search_value = FromHandle(value, &lossless);
3730 if (!std::isfinite(search_value)) {
3735 if (std::isnan(search_value)) {
3739 for (
size_t k = start_from; k <
length; ++k) {
3740 ElementType elem_k = AccessorClass::GetImpl(data_ptr + k,
is_shared);
3745 if (AccessorClass::ToTypedSearchValue(search_value,
3746 &typed_search_value)) {
3751 for (
size_t k = start_from; k <
length; ++k) {
3752 ElementType elem_k = AccessorClass::GetImpl(data_ptr + k,
is_shared);
3758 static Maybe<int64_t> LastIndexOfValueImpl(DirectHandle<JSObject>
receiver,
3759 DirectHandle<Object> value,
3760 size_t start_from) {
3765 DCHECK(!typed_array->IsDetachedOrOutOfBounds());
3767 ElementType typed_search_value;
3769 ElementType* data_ptr =
3770 reinterpret_cast<ElementType*
>(typed_array->DataPtr());
3774 typed_search_value = FromHandle(value, &lossless);
3779 if (!std::isfinite(search_value)) {
3781 std::is_integral_v<ElementType>) {
3784 }
else if (std::isnan(search_value)) {
3789 if (AccessorClass::ToTypedSearchValue(search_value,
3790 &typed_search_value)) {
3795 size_t typed_array_length = typed_array->GetLength();
3796 if (
V8_UNLIKELY(start_from >= typed_array_length)) {
3799 DCHECK(typed_array->IsVariableLength());
3800 if (typed_array_length == 0) {
3803 start_from = typed_array_length - 1;
3806 size_t k = start_from;
3808 ElementType elem_k = AccessorClass::GetImpl(data_ptr + k,
is_shared);
3810 if (IsFloat16RawBitsZero(typed_search_value) &&
3811 IsFloat16RawBitsZero(elem_k)) {
3824 DCHECK(!typed_array->IsDetachedOrOutOfBounds());
3826 size_t len = typed_array->GetLength();
3827 if (len == 0)
return;
3829 ElementType* data =
static_cast<ElementType*
>(typed_array->DataPtr());
3830 if (typed_array->buffer()->is_shared()) {
3835 for (ElementType *first = data, *last = data + len - 1; first < last;
3837 ElementType first_value = AccessorClass::GetImpl(first,
kShared);
3838 ElementType last_value = AccessorClass::GetImpl(last,
kShared);
3839 AccessorClass::SetImpl(first, last_value,
kShared);
3840 AccessorClass::SetImpl(last, first_value,
kShared);
3844 std::reverse(UnalignedSlot<ElementType>(data),
3845 UnalignedSlot<ElementType>(data + len));
3847 std::reverse(data, data + len);
3852 Isolate* isolate, DirectHandle<JSObject>
object, uint32_t length) {
3856 DirectHandle<Object> value = AccessorClass::GetInternalImpl(
3857 isolate, typed_array, InternalIndex(
i));
3868 CHECK(!source->IsDetachedOrOutOfBounds());
3874 ElementType* dest_data =
static_cast<ElementType*
>(
destination->DataPtr());
3876 source->buffer()->is_shared() ||
destination->buffer()->is_shared()
3879 switch (source->GetElementsKind()) {
3880#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
3881 case TYPE##_ELEMENTS: { \
3882 ctype* source_data = reinterpret_cast<ctype*>(source->DataPtr()) + start; \
3883 CopyBetweenBackingStores<TYPE##_ELEMENTS, ctype>(source_data, dest_data, \
3884 count, is_shared); \
3888#undef TYPED_ARRAY_CASE
3890#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, NON_RAB_GSAB_TYPE) \
3891 case TYPE##_ELEMENTS: { \
3892 ctype* source_data = reinterpret_cast<ctype*>(source->DataPtr()) + start; \
3893 CopyBetweenBackingStores<NON_RAB_GSAB_TYPE##_ELEMENTS, ctype>( \
3894 source_data, dest_data, count, is_shared); \
3898#undef TYPED_ARRAY_CASE
3912 template <ElementsKind SourceKind,
typename SourceElementType>
3913 static void CopyBetweenBackingStores(SourceElementType* source_data_ptr,
3914 ElementType* dest_data_ptr,
3917 CopyBetweenBackingStoresImpl<Kind, ElementType, SourceKind,
3918 SourceElementType>::Copy(source_data_ptr,
3919 dest_data_ptr, length,
3925 size_t length,
size_t offset) {
3930 CHECK(!source->IsDetachedOrOutOfBounds());
3940 bool same_type = source_type == destination_type;
3941 bool same_size = source->element_size() ==
destination->element_size();
3942 bool both_are_simple = HasSimpleRepresentation(source_type) &&
3943 HasSimpleRepresentation(destination_type);
3945 uint8_t* source_data =
static_cast<uint8_t*
>(source->DataPtr());
3946 uint8_t* dest_data =
static_cast<uint8_t*
>(
destination->DataPtr());
3947 size_t source_byte_length = source->GetByteLength();
3948 size_t dest_byte_length =
destination->GetByteLength();
3950 bool source_shared = source->buffer()->is_shared();
3951 bool destination_shared =
destination->buffer()->is_shared();
3957 if (same_type || (same_size && both_are_simple)) {
3958 size_t element_size = source->element_size();
3959 if (source_shared || destination_shared) {
3963 length * element_size);
3965 std::memmove(dest_data +
offset * element_size, source_data,
3966 length * element_size);
3969 std::unique_ptr<uint8_t[]> cloned_source_elements;
3972 if (dest_data + dest_byte_length > source_data &&
3973 source_data + source_byte_length > dest_data) {
3974 cloned_source_elements.reset(
new uint8_t[source_byte_length]);
3975 if (source_shared) {
3977 reinterpret_cast<base::Atomic8*
>(cloned_source_elements.get()),
3979 source_byte_length);
3981 std::memcpy(cloned_source_elements.get(), source_data,
3982 source_byte_length);
3984 source_data = cloned_source_elements.get();
3987 switch (source->GetElementsKind()) {
3988#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
3989 case TYPE##_ELEMENTS: \
3990 CopyBetweenBackingStores<TYPE##_ELEMENTS, ctype>( \
3991 reinterpret_cast<ctype*>(source_data), \
3992 reinterpret_cast<ElementType*>(dest_data) + offset, length, \
3993 source_shared || destination_shared ? kShared : kUnshared); \
4001#undef TYPED_ARRAY_CASE
4005 static bool HoleyPrototypeLookupRequired(Isolate* isolate,
4009 DisallowJavascriptExecution no_js(isolate);
4011#ifdef V8_ENABLE_FORCE_SLOW_PATH
4012 if (isolate->force_slow_path())
return true;
4019 if (
IsNull(source_proto, isolate))
return false;
4020 if (IsJSProxy(source_proto))
return true;
4021 if (IsJSObject(source_proto) &&
4022 !context->native_context()->is_initial_array_prototype(
4027 return !Protectors::IsNoElementsIntact(isolate);
4033 size_t length,
size_t offset) {
4035 Isolate* isolate = source->GetIsolate();
4037 DisallowJavascriptExecution no_js(isolate);
4040 bool out_of_bounds =
false;
4042 CHECK(!out_of_bounds);
4044 size_t current_length;
4047 length <= current_length);
4048 USE(current_length);
4056 auto destination_shared =
4064 if (HoleyPrototypeLookupRequired(isolate, context, source))
return false;
4067 ElementType* dest_data =
4078 elem_k = fp16_ieee_from_fp32_value(
Smi::ToInt(elem));
4082 SetImpl(dest_data +
i, elem_k, destination_shared);
4088 if (source_store->is_the_hole(isolate,
static_cast<int>(
i))) {
4089 SetImpl(dest_data +
i, FromObject(undefined), destination_shared);
4094 elem_k = fp16_ieee_from_fp32_value(
Smi::ToInt(elem));
4098 SetImpl(dest_data +
i, elem_k, destination_shared);
4111 double elem = source_store->get_scalar(
static_cast<int>(
i));
4112 SetImpl(dest_data +
i, FromScalar(elem), destination_shared);
4119 if (source_store->is_the_hole(
static_cast<int>(
i))) {
4120 SetImpl(dest_data +
i, FromObject(undefined), destination_shared);
4122 double elem = source_store->get_scalar(
static_cast<int>(
i));
4123 SetImpl(dest_data +
i, FromScalar(elem), destination_shared);
4133 DirectHandle<JSAny> source, DirectHandle<JSTypedArray>
destination,
4134 size_t length,
size_t offset) {
4139 DirectHandle<Object> elem;
4142 LookupIterator it(isolate, source,
i);
4152 BigInt::FromObject(isolate, elem));
4165 bool out_of_bounds =
false;
4177 return *isolate->factory()->undefined_value();
4184 DirectHandle<JSAny> source, DirectHandle<JSObject>
destination,
4185 size_t length,
size_t offset) {
4187 if (length == 0)
return *isolate->factory()->undefined_value();
4192 if (IsJSTypedArray(*source)) {
4193 CHECK(!destination_ta->WasDetached());
4194 bool out_of_bounds =
false;
4196 destination_ta->GetLengthOrOutOfBounds(out_of_bounds));
4197 CHECK(!out_of_bounds);
4199 ElementsKind source_kind = source_ta->GetElementsKind();
4204 if (source_is_bigint == target_is_bigint && !source_ta->WasDetached() &&
4206 CopyElementsFromTypedArray(*source_ta, *destination_ta, length,
offset);
4207 return *isolate->factory()->undefined_value();
4209 }
else if (IsJSArray(*source)) {
4210 CHECK(!destination_ta->WasDetached());
4211 bool out_of_bounds =
false;
4213 destination_ta->GetLengthOrOutOfBounds(out_of_bounds));
4214 CHECK(!out_of_bounds);
4217 size_t current_length;
4220 length <= current_length) {
4222 if (TryCopyElementsFastNumber(isolate->context(), *source_array,
4223 *destination_ta, length,
offset)) {
4224 return *isolate->factory()->undefined_value();
4231 return CopyElementsHandleSlow(source, destination_ta, length,
offset);
4236 typename SourceElementType>
4237struct CopyBetweenBackingStoresImpl {
4238 static void Copy(SourceElementType* source_data_ptr,
4239 ElementType* dest_data_ptr,
size_t length,
4241 for (; length > 0; --
length, ++source_data_ptr, ++dest_data_ptr) {
4244 SourceElementType source_elem =
4245 TypedElementsAccessor<SourceKind, SourceElementType>::GetImpl(
4247 ElementType dest_elem =
4248 TypedElementsAccessor<Kind, ElementType>::FromScalar(source_elem);
4250 TypedElementsAccessor<Kind, ElementType>::SetImpl(dest_data_ptr,
4256template <ElementsKind Kind,
typename ElementType>
4257struct CopyBetweenBackingStoresImpl<Kind, ElementType, FLOAT16_ELEMENTS,
4259 static void Copy(uint16_t* source_data_ptr, ElementType* dest_data_ptr,
4260 size_t length, IsSharedBuffer
is_shared) {
4261 for (; length > 0; --
length, ++source_data_ptr, ++dest_data_ptr) {
4265 TypedElementsAccessor<FLOAT16_ELEMENTS, uint16_t>::GetImpl(
4267 ElementType dest_elem =
4268 TypedElementsAccessor<Kind, ElementType>::FromScalar(
4269 fp16_ieee_to_fp32_value(source_elem));
4271 TypedElementsAccessor<Kind, ElementType>::SetImpl(dest_data_ptr,
4277template <ElementsKind Kind,
typename ElementType>
4278struct CopyBetweenBackingStoresImpl<Kind, ElementType,
4279 RAB_GSAB_FLOAT16_ELEMENTS,
uint16_t> {
4280 static void Copy(uint16_t* source_data_ptr, ElementType* dest_data_ptr,
4281 size_t length, IsSharedBuffer
is_shared) {
4282 for (; length > 0; --
length, ++source_data_ptr, ++dest_data_ptr) {
4286 TypedElementsAccessor<RAB_GSAB_FLOAT16_ELEMENTS, uint16_t>::GetImpl(
4288 ElementType dest_elem =
4289 TypedElementsAccessor<Kind, ElementType>::FromScalar(
4290 fp16_ieee_to_fp32_value(source_elem));
4292 TypedElementsAccessor<Kind, ElementType>::SetImpl(dest_data_ptr,
4300Handle<Object> TypedElementsAccessor<INT8_ELEMENTS, int8_t>::ToHandle(
4301 Isolate* isolate, int8_t value) {
4307Handle<Object> TypedElementsAccessor<UINT8_ELEMENTS, uint8_t>::ToHandle(
4308 Isolate* isolate, uint8_t value) {
4314Handle<Object> TypedElementsAccessor<INT16_ELEMENTS, int16_t>::ToHandle(
4315 Isolate* isolate, int16_t value) {
4321Handle<Object> TypedElementsAccessor<UINT16_ELEMENTS, uint16_t>::ToHandle(
4322 Isolate* isolate, uint16_t value) {
4328Handle<Object> TypedElementsAccessor<INT32_ELEMENTS, int32_t>::ToHandle(
4329 Isolate* isolate, int32_t value) {
4330 return isolate->factory()->NewNumberFromInt(value);
4335Handle<Object> TypedElementsAccessor<UINT32_ELEMENTS, uint32_t>::ToHandle(
4336 Isolate* isolate, uint32_t value) {
4337 return isolate->factory()->NewNumberFromUint(value);
4342uint16_t TypedElementsAccessor<FLOAT16_ELEMENTS, uint16_t>::FromScalar(
4349float TypedElementsAccessor<FLOAT32_ELEMENTS, float>::FromScalar(
double value) {
4355uint16_t TypedElementsAccessor<FLOAT16_ELEMENTS, uint16_t>::FromScalar(
4357 return fp16_ieee_from_fp32_value(value);
4362uint16_t TypedElementsAccessor<FLOAT16_ELEMENTS, uint16_t>::FromScalar(
4364 return fp16_ieee_from_fp32_value(value);
4369Handle<Object> TypedElementsAccessor<FLOAT16_ELEMENTS, uint16_t>::ToHandle(
4370 Isolate* isolate, uint16_t value) {
4371 return isolate->factory()->NewNumber(fp16_ieee_to_fp32_value(value));
4376Handle<Object> TypedElementsAccessor<FLOAT32_ELEMENTS, float>::ToHandle(
4377 Isolate* isolate,
float value) {
4378 return isolate->factory()->NewNumber(value);
4383double TypedElementsAccessor<FLOAT64_ELEMENTS, double>::FromScalar(
4390Handle<Object> TypedElementsAccessor<FLOAT64_ELEMENTS, double>::ToHandle(
4391 Isolate* isolate,
double value) {
4392 return isolate->factory()->NewNumber(value);
4397uint8_t TypedElementsAccessor<UINT8_CLAMPED_ELEMENTS, uint8_t>::FromScalar(
4399 if (value < 0x00)
return 0x00;
4400 if (value > 0xFF)
return 0xFF;
4401 return static_cast<uint8_t
>(
value);
4406uint8_t TypedElementsAccessor<UINT8_CLAMPED_ELEMENTS, uint8_t>::FromScalar(
4410 if (value > 0xFF)
return 0xFF;
4411 return static_cast<uint8_t
>(
value);
4416uint8_t TypedElementsAccessor<UINT8_CLAMPED_ELEMENTS, uint8_t>::FromScalar(
4419 if (!(value > 0))
return 0;
4420 if (value > 0xFF)
return 0xFF;
4421 return static_cast<uint8_t
>(lrint(value));
4426Handle<Object> TypedElementsAccessor<UINT8_CLAMPED_ELEMENTS, uint8_t>::ToHandle(
4427 Isolate* isolate, uint8_t value) {
4433int64_t TypedElementsAccessor<BIGINT64_ELEMENTS, int64_t>::FromScalar(
4440int64_t TypedElementsAccessor<BIGINT64_ELEMENTS, int64_t>::FromScalar(
4447int64_t TypedElementsAccessor<BIGINT64_ELEMENTS, int64_t>::FromScalar(
4454int64_t TypedElementsAccessor<BIGINT64_ELEMENTS, int64_t>::FromScalar(
4461int64_t TypedElementsAccessor<BIGINT64_ELEMENTS, int64_t>::FromScalar(
4463 return static_cast<int64_t
>(
value);
4468int64_t TypedElementsAccessor<BIGINT64_ELEMENTS, int64_t>::FromObject(
4475Handle<Object> TypedElementsAccessor<BIGINT64_ELEMENTS, int64_t>::ToHandle(
4476 Isolate* isolate, int64_t value) {
4482uint64_t TypedElementsAccessor<BIGUINT64_ELEMENTS, uint64_t>::FromScalar(
4489uint64_t TypedElementsAccessor<BIGUINT64_ELEMENTS, uint64_t>::FromScalar(
4496uint64_t TypedElementsAccessor<BIGUINT64_ELEMENTS, uint64_t>::FromScalar(
4503uint64_t TypedElementsAccessor<BIGUINT64_ELEMENTS, uint64_t>::FromScalar(
4505 return static_cast<uint64_t
>(
value);
4510uint64_t TypedElementsAccessor<BIGUINT64_ELEMENTS, uint64_t>::FromScalar(
4517uint64_t TypedElementsAccessor<BIGUINT64_ELEMENTS, uint64_t>::FromObject(
4524Handle<Object> TypedElementsAccessor<BIGUINT64_ELEMENTS, uint64_t>::ToHandle(
4525 Isolate* isolate, uint64_t value) {
4531Handle<Object> TypedElementsAccessor<RAB_GSAB_INT8_ELEMENTS, int8_t>::ToHandle(
4532 Isolate* isolate, int8_t value) {
4538Handle<Object> TypedElementsAccessor<RAB_GSAB_UINT8_ELEMENTS,
4539 uint8_t>::ToHandle(Isolate* isolate,
4546Handle<Object> TypedElementsAccessor<RAB_GSAB_INT16_ELEMENTS,
4547 int16_t>::ToHandle(Isolate* isolate,
4554Handle<Object> TypedElementsAccessor<RAB_GSAB_UINT16_ELEMENTS,
4555 uint16_t>::ToHandle(Isolate* isolate,
4562Handle<Object> TypedElementsAccessor<RAB_GSAB_INT32_ELEMENTS,
4563 int32_t>::ToHandle(Isolate* isolate,
4565 return isolate->factory()->NewNumberFromInt(value);
4570Handle<Object> TypedElementsAccessor<RAB_GSAB_UINT32_ELEMENTS,
4571 uint32_t>::ToHandle(Isolate* isolate,
4573 return isolate->factory()->NewNumberFromUint(value);
4578uint16_t TypedElementsAccessor<RAB_GSAB_FLOAT16_ELEMENTS, uint16_t>::FromScalar(
4585uint16_t TypedElementsAccessor<RAB_GSAB_FLOAT16_ELEMENTS, uint16_t>::FromScalar(
4587 return fp16_ieee_from_fp32_value(value);
4592uint16_t TypedElementsAccessor<RAB_GSAB_FLOAT16_ELEMENTS, uint16_t>::FromScalar(
4594 return fp16_ieee_from_fp32_value(value);
4599Handle<Object> TypedElementsAccessor<RAB_GSAB_FLOAT16_ELEMENTS,
4600 uint16_t>::ToHandle(Isolate* isolate,
4602 return isolate->factory()->NewHeapNumber(fp16_ieee_to_fp32_value(value));
4607float TypedElementsAccessor<RAB_GSAB_FLOAT32_ELEMENTS, float>::FromScalar(
4614Handle<Object> TypedElementsAccessor<RAB_GSAB_FLOAT32_ELEMENTS,
4615 float>::ToHandle(Isolate* isolate,
4617 return isolate->factory()->NewNumber(value);
4622double TypedElementsAccessor<RAB_GSAB_FLOAT64_ELEMENTS, double>::FromScalar(
4629Handle<Object> TypedElementsAccessor<RAB_GSAB_FLOAT64_ELEMENTS,
4630 double>::ToHandle(Isolate* isolate,
4632 return isolate->factory()->NewNumber(value);
4637uint8_t TypedElementsAccessor<RAB_GSAB_UINT8_CLAMPED_ELEMENTS,
4638 uint8_t>::FromScalar(
int value) {
4639 if (value < 0x00)
return 0x00;
4640 if (value > 0xFF)
return 0xFF;
4641 return static_cast<uint8_t
>(
value);
4646uint8_t TypedElementsAccessor<RAB_GSAB_UINT8_CLAMPED_ELEMENTS,
4647 uint8_t>::FromScalar(uint32_t value) {
4650 if (value > 0xFF)
return 0xFF;
4651 return static_cast<uint8_t
>(
value);
4656uint8_t TypedElementsAccessor<RAB_GSAB_UINT8_CLAMPED_ELEMENTS,
4657 uint8_t>::FromScalar(
double value) {
4659 if (!(value > 0))
return 0;
4660 if (value > 0xFF)
return 0xFF;
4661 return static_cast<uint8_t
>(lrint(value));
4666Handle<Object> TypedElementsAccessor<RAB_GSAB_UINT8_CLAMPED_ELEMENTS,
4667 uint8_t>::ToHandle(Isolate* isolate,
4674int64_t TypedElementsAccessor<RAB_GSAB_BIGINT64_ELEMENTS, int64_t>::FromScalar(
4681int64_t TypedElementsAccessor<RAB_GSAB_BIGINT64_ELEMENTS, int64_t>::FromScalar(
4688int64_t TypedElementsAccessor<RAB_GSAB_BIGINT64_ELEMENTS, int64_t>::FromScalar(
4695int64_t TypedElementsAccessor<RAB_GSAB_BIGINT64_ELEMENTS, int64_t>::FromScalar(
4702int64_t TypedElementsAccessor<RAB_GSAB_BIGINT64_ELEMENTS, int64_t>::FromScalar(
4704 return static_cast<int64_t
>(
value);
4709int64_t TypedElementsAccessor<RAB_GSAB_BIGINT64_ELEMENTS, int64_t>::FromObject(
4716Handle<Object> TypedElementsAccessor<RAB_GSAB_BIGINT64_ELEMENTS,
4717 int64_t>::ToHandle(Isolate* isolate,
4724uint64_t TypedElementsAccessor<RAB_GSAB_BIGUINT64_ELEMENTS,
4725 uint64_t>::FromScalar(
int value) {
4731uint64_t TypedElementsAccessor<RAB_GSAB_BIGUINT64_ELEMENTS,
4732 uint64_t>::FromScalar(uint32_t value) {
4738uint64_t TypedElementsAccessor<RAB_GSAB_BIGUINT64_ELEMENTS,
4739 uint64_t>::FromScalar(
double value) {
4745uint64_t TypedElementsAccessor<RAB_GSAB_BIGUINT64_ELEMENTS,
4746 uint64_t>::FromScalar(int64_t value) {
4747 return static_cast<uint64_t
>(
value);
4752uint64_t TypedElementsAccessor<RAB_GSAB_BIGUINT64_ELEMENTS,
4753 uint64_t>::FromScalar(uint64_t value) {
4759uint64_t TypedElementsAccessor<RAB_GSAB_BIGUINT64_ELEMENTS,
4767Handle<Object> TypedElementsAccessor<RAB_GSAB_BIGUINT64_ELEMENTS,
4768 uint64_t>::ToHandle(Isolate* isolate,
4773#define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype) \
4774 using Type##ElementsAccessor = TypedElementsAccessor<TYPE##_ELEMENTS, ctype>;
4777#undef FIXED_ELEMENTS_ACCESSOR
4779template <
typename Sub
class,
typename ArgumentsAccessor,
typename KindTraits>
4780class SloppyArgumentsElementsAccessor
4781 :
public ElementsAccessorBase<Subclass, KindTraits> {
4783 static void ConvertArgumentsStoreResult(
4784 DirectHandle<SloppyArgumentsElements> elements,
4785 DirectHandle<Object>
result) {
4789 static Handle<Object> GetImpl(Isolate* isolate,
4791 InternalIndex entry) {
4792 DirectHandle<SloppyArgumentsElements> elements(
4794 uint32_t length = elements->length();
4795 if (entry.as_uint32() < length) {
4799 elements->mapped_entries(entry.as_uint32(),
kRelaxedLoad);
4800 DCHECK(!IsTheHole(probe, isolate));
4803 DCHECK(!IsTheHole(context->get(context_entry), isolate));
4804 return handle(context->get(context_entry), isolate);
4807 Handle<Object>
result = ArgumentsAccessor::GetImpl(
4808 isolate, elements->arguments(), entry.adjust_down(length));
4809 return Subclass::ConvertArgumentsStoreResult(isolate, elements,
result);
4813 static void TransitionElementsKindImpl(DirectHandle<JSObject>
object,
4814 DirectHandle<Map> map) {
4818 static Maybe<bool> GrowCapacityAndConvertImpl(DirectHandle<JSObject>
object,
4819 uint32_t capacity) {
4823 static inline void SetImpl(DirectHandle<JSObject> holder, InternalIndex entry,
4825 SetImpl(holder->elements(), entry, value);
4832 uint32_t length = elements->length();
4833 if (entry.as_uint32() < length) {
4837 elements->mapped_entries(entry.as_uint32(),
kRelaxedLoad);
4838 DCHECK(!IsTheHole(probe));
4841 DCHECK(!IsTheHole(context->get(context_entry)));
4842 context->set(context_entry, value);
4847 ArgumentsAccessor::GetRaw(arguments, entry.adjust_down(length));
4848 if (IsAliasedArgumentsEntry(current)) {
4852 int context_entry = alias->aliased_context_slot();
4853 DCHECK(!IsTheHole(context->get(context_entry)));
4854 context->set(context_entry, value);
4856 ArgumentsAccessor::SetImpl(arguments, entry.adjust_down(length), value);
4861 static Maybe<bool> SetLengthImpl(Isolate* isolate,
4862 DirectHandle<JSArray> array, uint32_t length,
4863 DirectHandle<FixedArrayBase> parameter_map) {
4873 return elements->length() +
4874 ArgumentsAccessor::GetCapacityImpl(holder, arguments);
4877 static uint32_t GetMaxNumberOfEntries(Isolate* isolate,
4883 size_t max_entries =
4884 ArgumentsAccessor::GetMaxNumberOfEntries(isolate, holder, arguments);
4885 DCHECK_LE(max_entries, std::numeric_limits<uint32_t>::max());
4886 return elements->length() +
static_cast<uint32_t
>(max_entries);
4889 static uint32_t NumberOfElementsImpl(Isolate* isolate,
4895 uint32_t nof_elements = 0;
4896 uint32_t length = elements->length();
4897 for (uint32_t index = 0; index <
length; index++) {
4898 if (HasParameterMapArg(isolate, elements, index)) nof_elements++;
4900 return nof_elements + ArgumentsAccessor::NumberOfElementsImpl(
4905 DirectHandle<JSObject>
receiver, KeyAccumulator* accumulator,
4907 Isolate* isolate = accumulator->isolate();
4908 DirectHandle<FixedArrayBase> elements(
receiver->elements(), isolate);
4909 uint32_t length = GetCapacityImpl(*
receiver, *elements);
4910 for (uint32_t index = 0; index <
length; index++) {
4911 InternalIndex entry(index);
4912 if (!HasEntryImpl(isolate, *elements, entry))
continue;
4913 DirectHandle<Object> value = GetImpl(isolate, *elements, entry);
4920 InternalIndex entry) {
4923 uint32_t length = elements->length();
4924 if (entry.raw_value() < length) {
4925 return HasParameterMapArg(isolate, elements, entry.raw_value());
4928 return ArgumentsAccessor::HasEntryImpl(isolate, arguments,
4929 entry.adjust_down(length));
4937 return ArgumentsAccessor::HasAccessorsImpl(holder, arguments);
4940 static InternalIndex GetEntryForIndexImpl(Isolate* isolate,
4947 if (HasParameterMapArg(isolate, elements, index)) {
4948 return InternalIndex(index);
4951 InternalIndex entry = ArgumentsAccessor::GetEntryForIndexImpl(
4952 isolate, holder, arguments, index, filter);
4953 if (entry.is_not_found())
return entry;
4956 return entry.adjust_up(elements->length());
4960 InternalIndex entry) {
4963 uint32_t length = elements->length();
4964 if (entry.as_uint32() < length) {
4969 return ArgumentsAccessor::GetDetailsImpl(arguments,
4970 entry.adjust_down(length));
4973 static bool HasParameterMapArg(Isolate* isolate,
4976 uint32_t length = elements->length();
4977 if (index >= length)
return false;
4979 elements->mapped_entries(
static_cast<uint32_t
>(index),
kRelaxedLoad),
4983 static void DeleteImpl(DirectHandle<JSObject> obj, InternalIndex entry) {
4984 DirectHandle<SloppyArgumentsElements> elements(
4986 uint32_t length = elements->length();
4987 InternalIndex delete_or_entry = entry;
4988 if (entry.as_uint32() < length) {
4991 Subclass::SloppyDeleteImpl(obj, elements, delete_or_entry);
4994 if (entry.as_uint32() < length) {
4995 elements->set_mapped_entries(entry.as_uint32(),
5000 static void SloppyDeleteImpl(DirectHandle<JSObject> obj,
5001 DirectHandle<SloppyArgumentsElements> elements,
5002 InternalIndex entry) {
5008 DirectHandle<JSObject>
object, DirectHandle<FixedArrayBase> backing_store,
5009 KeyAccumulator* keys) {
5010 Isolate* isolate = keys->isolate();
5011 uint32_t nof_indices = 0;
5013 GetCapacityImpl(*
object, *backing_store));
5014 DirectCollectElementIndicesImpl(isolate,
object, backing_store,
5017 SortIndices(isolate, indices, nof_indices);
5018 for (uint32_t
i = 0;
i < nof_indices;
i++) {
5025 Isolate* isolate, DirectHandle<JSObject>
object,
5028 uint32_t insertion_index = 0) {
5030 uint32_t length = elements->length();
5033 if (IsTheHole(elements->mapped_entries(
i,
kRelaxedLoad), isolate))
5036 DirectHandle<String> index_string =
5037 isolate->factory()->Uint32ToString(
i);
5038 list->set(insertion_index, *index_string);
5045 DirectHandle<FixedArray>
store(elements->arguments(), isolate);
5046 return ArgumentsAccessor::DirectCollectElementIndicesImpl(
5047 isolate,
object, store, convert, filter, list, nof_indices,
5051 static Maybe<bool> IncludesValueImpl(Isolate* isolate,
5052 DirectHandle<JSObject>
object,
5053 DirectHandle<Object> value,
5054 size_t start_from,
size_t length) {
5056 DirectHandle<Map> original_map(object->map(), isolate);
5057 DirectHandle<SloppyArgumentsElements> elements(
5059 bool search_for_hole = IsUndefined(*value, isolate);
5061 for (
size_t k = start_from; k <
length; ++k) {
5062 DCHECK_EQ(object->map(), *original_map);
5063 InternalIndex entry =
5064 GetEntryForIndexImpl(isolate, *
object, *elements, k,
ALL_PROPERTIES);
5065 if (entry.is_not_found()) {
5066 if (search_for_hole)
return Just(
true);
5070 DirectHandle<Object> element_k =
5071 Subclass::GetImpl(isolate, *elements, entry);
5073 if (IsAccessorPair(*element_k)) {
5083 if (object->map() != *original_map) {
5085 return IncludesValueSlowPath(isolate,
object, value, k + 1, length);
5094 static Maybe<int64_t> IndexOfValueImpl(Isolate* isolate,
5095 DirectHandle<JSObject>
object,
5096 DirectHandle<Object> value,
5097 size_t start_from,
size_t length) {
5099 DirectHandle<Map> original_map(object->map(), isolate);
5100 DirectHandle<SloppyArgumentsElements> elements(
5103 for (
size_t k = start_from; k <
length; ++k) {
5104 DCHECK_EQ(object->map(), *original_map);
5105 InternalIndex entry =
5106 GetEntryForIndexImpl(isolate, *
object, *elements, k,
ALL_PROPERTIES);
5107 if (entry.is_not_found()) {
5111 DirectHandle<Object> element_k =
5112 Subclass::GetImpl(isolate, *elements, entry);
5114 if (IsAccessorPair(*element_k)) {
5126 if (object->map() != *original_map) {
5128 return IndexOfValueSlowPath(isolate,
object, value, k + 1, length);
5138class SlowSloppyArgumentsElementsAccessor
5139 :
public SloppyArgumentsElementsAccessor<
5140 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor,
5141 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS>> {
5143 static Handle<Object> ConvertArgumentsStoreResult(
5144 Isolate* isolate, DirectHandle<SloppyArgumentsElements> elements,
5147 if (IsAliasedArgumentsEntry(*
result)) {
5152 int context_entry = alias->aliased_context_slot();
5153 DCHECK(!IsTheHole(context->get(context_entry), isolate));
5154 return handle(context->get(context_entry), isolate);
5158 static void SloppyDeleteImpl(DirectHandle<JSObject> obj,
5159 DirectHandle<SloppyArgumentsElements> elements,
5160 InternalIndex entry) {
5162 if (entry.is_not_found())
return;
5163 Isolate* isolate = obj->GetIsolate();
5164 DirectHandle<NumberDictionary> dict(
5166 uint32_t length = elements->length();
5168 NumberDictionary::DeleteEntry(isolate, dict, entry.adjust_down(length));
5169 elements->set_arguments(*dict);
5171 static Maybe<bool> AddImpl(DirectHandle<JSObject>
object, uint32_t index,
5172 DirectHandle<Object> value,
5174 uint32_t new_capacity) {
5175 Isolate* isolate =
object->GetIsolate();
5176 DirectHandle<SloppyArgumentsElements> elements(
5178 DirectHandle<FixedArrayBase> old_arguments(elements->arguments(), isolate);
5179 DirectHandle<NumberDictionary> dictionary =
5180 IsNumberDictionary(*old_arguments)
5182 : JSObject::NormalizeElements(object);
5185 DirectHandle<NumberDictionary> new_dictionary =
5186 NumberDictionary::Add(isolate, dictionary, index, value, details);
5187 if (attributes !=
NONE)
object->RequireSlowElements(*new_dictionary);
5188 if (*dictionary != *new_dictionary) {
5189 elements->set_arguments(*new_dictionary);
5194 static void ReconfigureImpl(DirectHandle<JSObject>
object,
5195 DirectHandle<FixedArrayBase> store,
5196 InternalIndex entry, DirectHandle<Object> value,
5198 Isolate* isolate =
object->GetIsolate();
5200 uint32_t length = elements->length();
5201 if (entry.as_uint32() < length) {
5203 elements->mapped_entries(entry.as_uint32(),
kRelaxedLoad);
5204 DCHECK(!IsTheHole(probe, isolate));
5207 DCHECK(!IsTheHole(context->get(context_entry), isolate));
5208 context->set(context_entry, *value);
5211 elements->set_mapped_entries(entry.as_uint32(),
5212 ReadOnlyRoots(isolate).the_hole_value());
5215 value = isolate->factory()->NewAliasedArgumentsEntry(context_entry);
5220 DirectHandle<NumberDictionary> arguments(
5222 arguments = NumberDictionary::Add(isolate, arguments, entry.as_uint32(),
5227 object->RequireSlowElements(*arguments);
5228 elements->set_arguments(*arguments);
5230 DirectHandle<FixedArrayBase> arguments(elements->arguments(), isolate);
5231 DictionaryElementsAccessor::ReconfigureImpl(
5232 object, arguments, entry.adjust_down(length), value, attributes);
5237class FastSloppyArgumentsElementsAccessor
5238 :
public SloppyArgumentsElementsAccessor<
5239 FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor,
5240 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS>> {
5242 static Handle<Object> ConvertArgumentsStoreResult(
5243 Isolate* isolate, DirectHandle<SloppyArgumentsElements> parameter_map,
5249 static DirectHandle<FixedArray> GetArguments(Isolate* isolate,
5253 return DirectHandle<FixedArray>(elements->arguments(), isolate);
5256 static DirectHandle<NumberDictionary> NormalizeImpl(
5257 DirectHandle<JSObject>
object, DirectHandle<FixedArrayBase> elements) {
5258 DirectHandle<FixedArray> arguments =
5259 GetArguments(object->GetIsolate(), *elements);
5260 return FastHoleyObjectElementsAccessor::NormalizeImpl(
object, arguments);
5263 static DirectHandle<NumberDictionary> NormalizeArgumentsElements(
5264 DirectHandle<JSObject>
object,
5265 DirectHandle<SloppyArgumentsElements> elements, InternalIndex* entry) {
5266 DirectHandle<NumberDictionary> dictionary =
5268 elements->set_arguments(*dictionary);
5271 if (entry->is_not_found())
return dictionary;
5272 uint32_t length = elements->length();
5273 if (entry->as_uint32() >= length) {
5276 ->FindEntry(object->GetIsolate(), entry->as_uint32() - length)
5282 static void SloppyDeleteImpl(DirectHandle<JSObject> obj,
5283 DirectHandle<SloppyArgumentsElements> elements,
5284 InternalIndex entry) {
5286 NormalizeArgumentsElements(obj, elements, &entry);
5287 SlowSloppyArgumentsElementsAccessor::SloppyDeleteImpl(obj, elements, entry);
5290 static Maybe<bool> AddImpl(DirectHandle<JSObject>
object, uint32_t index,
5291 DirectHandle<Object> value,
5293 uint32_t new_capacity) {
5295 Isolate* isolate =
object->GetIsolate();
5296 DirectHandle<SloppyArgumentsElements> elements(
5298 DirectHandle<FixedArray> old_arguments(elements->arguments(), isolate);
5299 if (IsNumberDictionary(*old_arguments) ||
5300 static_cast<uint32_t
>(old_arguments->length()) < new_capacity) {
5301 MAYBE_RETURN(GrowCapacityAndConvertImpl(
object, new_capacity),
5310 FastHoleyObjectElementsAccessor::SetImpl(arguments, InternalIndex(index),
5315 static void ReconfigureImpl(DirectHandle<JSObject>
object,
5316 DirectHandle<FixedArrayBase> store,
5317 InternalIndex entry, DirectHandle<Object> value,
5320 DirectHandle<SloppyArgumentsElements> elements(
5322 NormalizeArgumentsElements(
object, elements, &entry);
5323 SlowSloppyArgumentsElementsAccessor::ReconfigureImpl(
object, store, entry,
5330 int packed_size,
int copy_size) {
5331 DCHECK(!IsNumberDictionary(to));
5333 CopyDictionaryToObjectElements(isolate, from, from_start, to,
5337 CopyObjectToObjectElements(isolate, from,
HOLEY_ELEMENTS, from_start, to,
5342 static Maybe<bool> GrowCapacityAndConvertImpl(DirectHandle<JSObject>
object,
5343 uint32_t capacity) {
5344 Isolate* isolate =
object->GetIsolate();
5345 DirectHandle<SloppyArgumentsElements> elements(
5347 DirectHandle<FixedArray> old_arguments(
5353 static_cast<uint32_t
>(old_arguments->length()) < capacity);
5354 DirectHandle<FixedArrayBase> arguments;
5357 ConvertElementsWithCapacity(
object, old_arguments, from_kind, capacity),
5368template <
typename Sub
class,
typename BackingStoreAccessor,
typename KindTraits>
5369class StringWrapperElementsAccessor
5370 :
public ElementsAccessorBase<Subclass, KindTraits> {
5372 static Handle<Object> GetInternalImpl(Isolate* isolate,
5373 DirectHandle<JSObject> holder,
5374 InternalIndex entry) {
5375 return GetImpl(holder, entry);
5378 static Handle<Object> GetImpl(DirectHandle<JSObject> holder,
5379 InternalIndex entry) {
5380 Isolate* isolate = holder->GetIsolate();
5381 DirectHandle<String>
string(GetString(*holder), isolate);
5382 uint32_t length =
static_cast<uint32_t
>(
string->length());
5383 if (entry.as_uint32() < length) {
5384 return isolate->factory()->LookupSingleCharacterStringFromCode(
5387 return BackingStoreAccessor::GetImpl(isolate, holder->elements(),
5388 entry.adjust_down(length));
5391 static DirectHandle<Object> GetImpl(Isolate* isolate,
5393 InternalIndex entry) {
5398 InternalIndex entry) {
5399 uint32_t length =
static_cast<uint32_t
>(GetString(holder)->length());
5400 if (entry.as_uint32() < length) {
5406 return BackingStoreAccessor::GetDetailsImpl(holder,
5407 entry.adjust_down(length));
5410 static InternalIndex GetEntryForIndexImpl(
5414 uint32_t length =
static_cast<uint32_t
>(GetString(holder)->length());
5415 if (index < length)
return InternalIndex(index);
5416 InternalIndex backing_store_entry =
5417 BackingStoreAccessor::GetEntryForIndexImpl(
5418 isolate, holder, backing_store, index, filter);
5419 if (backing_store_entry.is_not_found())
return backing_store_entry;
5420 return backing_store_entry.adjust_up(length);
5423 static void DeleteImpl(DirectHandle<JSObject> holder, InternalIndex entry) {
5424 uint32_t length =
static_cast<uint32_t
>(GetString(*holder)->length());
5425 if (entry.as_uint32() < length) {
5428 BackingStoreAccessor::DeleteImpl(holder, entry.adjust_down(length));
5431 static void SetImpl(DirectHandle<JSObject> holder, InternalIndex entry,
5433 uint32_t length =
static_cast<uint32_t
>(GetString(*holder)->length());
5434 if (entry.as_uint32() < length) {
5437 BackingStoreAccessor::SetImpl(holder->elements(), entry.adjust_down(length),
5441 static Maybe<bool> AddImpl(DirectHandle<JSObject>
object, uint32_t index,
5442 DirectHandle<Object> value,
5444 uint32_t new_capacity) {
5445 DCHECK(index >=
static_cast<uint32_t
>(GetString(*object)->length()));
5450 BackingStoreAccessor::GetCapacityImpl(*
object, object->elements()) !=
5452 MAYBE_RETURN(GrowCapacityAndConvertImpl(
object, new_capacity),
5455 BackingStoreAccessor::AddImpl(
object, index, value, attributes,
5460 static void ReconfigureImpl(DirectHandle<JSObject>
object,
5461 DirectHandle<FixedArrayBase> store,
5462 InternalIndex entry, DirectHandle<Object> value,
5464 uint32_t length =
static_cast<uint32_t
>(GetString(*object)->length());
5465 if (entry.as_uint32() < length) {
5468 BackingStoreAccessor::ReconfigureImpl(
5469 object, store, entry.adjust_down(length), value, attributes);
5473 DirectHandle<JSObject>
receiver, KeyAccumulator* accumulator,
5475 Isolate* isolate =
receiver->GetIsolate();
5478 uint32_t length =
static_cast<uint32_t
>(
string->length());
5480 DirectHandle<String>
key =
5481 isolate->factory()->LookupSingleCharacterStringFromCode(
5485 return BackingStoreAccessor::AddElementsToKeyAccumulatorImpl(
5490 DirectHandle<JSObject>
object, DirectHandle<FixedArrayBase> backing_store,
5491 KeyAccumulator* keys) {
5492 uint32_t length = GetString(*object)->length();
5493 Factory* factory = keys->isolate()->factory();
5496 keys->AddKey(factory->NewNumberFromUint(
i)));
5498 return BackingStoreAccessor::CollectElementIndicesImpl(
object,
5499 backing_store, keys);
5502 static Maybe<bool> GrowCapacityAndConvertImpl(DirectHandle<JSObject>
object,
5503 uint32_t capacity) {
5504 DirectHandle<FixedArrayBase> old_elements(object->elements(),
5505 object->GetIsolate());
5512 object->GetIsolate()->UpdateNoElementsProtectorOnSetLength(
object);
5517 static_cast<uint32_t
>(old_elements->length()) < capacity);
5518 return Subclass::BasicGrowCapacityAndConvertImpl(
5526 int packed_size,
int copy_size) {
5527 DCHECK(!IsNumberDictionary(to));
5529 CopyDictionaryToObjectElements(isolate, from, from_start, to,
5533 CopyObjectToObjectElements(isolate, from,
HOLEY_ELEMENTS, from_start, to,
5538 static uint32_t NumberOfElementsImpl(Isolate* isolate,
5541 uint32_t length = GetString(
object)->length();
5542 return length + BackingStoreAccessor::NumberOfElementsImpl(isolate,
object,
5548 DCHECK(IsJSPrimitiveWrapper(holder));
5550 DCHECK(IsString(js_value->value()));
5555class FastStringWrapperElementsAccessor
5556 :
public StringWrapperElementsAccessor<
5557 FastStringWrapperElementsAccessor, FastHoleyObjectElementsAccessor,
5558 ElementsKindTraits<FAST_STRING_WRAPPER_ELEMENTS>> {
5560 static DirectHandle<NumberDictionary> NormalizeImpl(
5561 DirectHandle<JSObject>
object, DirectHandle<FixedArrayBase> elements) {
5562 return FastHoleyObjectElementsAccessor::NormalizeImpl(
object, elements);
5566class SlowStringWrapperElementsAccessor
5567 :
public StringWrapperElementsAccessor<
5568 SlowStringWrapperElementsAccessor, DictionaryElementsAccessor,
5569 ElementsKindTraits<SLOW_STRING_WRAPPER_ELEMENTS>> {
5573 return DictionaryElementsAccessor::HasAccessorsImpl(holder, backing_store);
5581 if (
args->length() == 0) {
5589 return ThrowArrayLengthRangeError(array->GetIsolate());
5602 }
else if (length == 0) {
5612 Factory* factory = array->GetIsolate()->factory();
5615 int number_of_elements =
args->length();
5631 switch (elements_kind) {
5635 for (
int entry = 0; entry < number_of_elements; entry++) {
5645 for (
int entry = 0; entry < number_of_elements; entry++) {
5646 object_elms->set(entry, (*
args)[entry], mode);
5653 for (
int entry = 0; entry < number_of_elements; entry++) {
5662 array->set_elements(*elms);
5678#define TYPED_ARRAYS_CASE(Type, type, TYPE, ctype) \
5679 case TYPE##_ELEMENTS: \
5680 CHECK(Type##ElementsAccessor::TryCopyElementsFastNumber( \
5681 context, source, destination, length, offset)); \
5685#undef TYPED_ARRAYS_CASE
5693 uintptr_t length, uintptr_t
offset) {
5699#define TYPED_ARRAYS_CASE(Type, type, TYPE, ctype) \
5700 case TYPE##_ELEMENTS: \
5701 Type##ElementsAccessor::CopyElementsFromTypedArray(source, destination, \
5706#undef TYPED_ARRAYS_CASE
5718 destination->GetElementsAccessor()->CopyTypedArrayElementsSlice(
5722template <
typename Mapping>
5724 return (index >= std::size(mapping)) ||
5735 static_assert(std::is_same_v<std::underlying_type_t<ElementsKind>, uint8_t>);
5737#define ACCESSOR_ARRAY(Class, Kind, Store) new Class(),
5739#undef ACCESSOR_ARRAY
5742 static_assert((
sizeof(accessor_array) /
sizeof(*accessor_array)) >=
5748#define ACCESSOR_KIND(Class, Kind, Store) Kind,
5759#define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind];
5761#undef ACCESSOR_DELETE
5767 uint32_t concat_size,
5768 uint32_t result_len) {
5770 bool has_raw_doubles =
false;
5773 bool is_holey =
false;
5774 for (uint32_t
i = 0;
i < concat_size;
i++) {
5779 result_elements_kind =
5790 bool requires_double_boxing =
5793 requires_double_boxing
5797 result_elements_kind, result_len, result_len, mode);
5798 if (result_len == 0)
return result_array;
5800 uint32_t insertion_index = 0;
5803 for (uint32_t
i = 0;
i < concat_size;
i++) {
5809 if (len == 0)
continue;
5811 accessor->
CopyElements(isolate, array, 0, from_kind, storage,
5812 insertion_index, len);
5813 insertion_index += len;
5817 return result_array;
5823#undef RETURN_NOTHING_IF_NOT_SUCCESSFUL
5824#undef RETURN_FAILURE_IF_NOT_SUCCESSFUL
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype)
static V8_EXPORT_PRIVATE Handle< BigInt > FromUint64(Isolate *isolate, uint64_t n)
static V8_EXPORT_PRIVATE Handle< BigInt > FromInt64(Isolate *isolate, int64_t n)
static ElementsAccessor * ForKind(ElementsKind elements_kind)
virtual void CopyElements(Isolate *isolate, DirectHandle< FixedArrayBase > source, ElementsKind source_kind, DirectHandle< FixedArrayBase > destination, int size)=0
static V8_EXPORT_PRIVATE ElementsAccessor ** elements_accessors_
static void InitializeOncePerProcess()
static DirectHandle< JSArray > Concat(Isolate *isolate, BuiltinArguments *args, uint32_t concat_size, uint32_t result_length)
Handle< FixedArray > NewFixedArrayWithHoles(int length, AllocationType allocation=AllocationType::kYoung)
Handle< FixedArrayBase > NewFixedDoubleArray(int length, AllocationType allocation=AllocationType::kYoung)
static constexpr int kMaxLength
static HandleType< FixedArray > RightTrimOrEmpty(Isolate *isolate, HandleType< FixedArray > array, int new_length)
static Handle< Object > get(Tagged< FixedDoubleArray > array, int index, Isolate *isolate)
static Tagged< Object > SeqCst_CompareAndSwapField(Tagged< Object > expected_value, Tagged< Object > new_value, CompareAndSwapImpl compare_and_swap_impl)
static InternalIndex NotFound()
static V8_EXPORT_PRIVATE Maybe< bool > SetLength(DirectHandle< JSArray > array, uint32_t length)
static const int kInitialMaxFastElementArray
static V8_EXPORT_PRIVATE void Initialize(DirectHandle< JSArray > array, int capacity, int length=0)
static const int kPreallocatedArrayElements
static const int kMaxCopyElements
static V8_EXPORT_PRIVATE DirectHandle< NumberDictionary > NormalizeElements(DirectHandle< JSObject > object)
static bool PrototypeHasNoElements(Isolate *isolate, Tagged< JSObject > object)
static void ApplyAttributesToDictionary(Isolate *isolate, ReadOnlyRoots roots, DirectHandle< Dictionary > dictionary, const PropertyAttributes attributes)
static void ValidateElements(Tagged< JSObject > object)
static constexpr uint32_t NewElementsCapacity(uint32_t old_capacity)
static void EnsureCanContainElements(DirectHandle< JSObject > object, TSlot elements, uint32_t count, EnsureElementsMode mode)
static void SetMapAndElements(DirectHandle< JSObject > object, DirectHandle< Map > map, DirectHandle< FixedArrayBase > elements)
static V8_EXPORT_PRIVATE void TransitionElementsKind(DirectHandle< JSObject > object, ElementsKind to_kind)
static void PrintElementsTransition(FILE *file, DirectHandle< JSObject > object, ElementsKind from_kind, DirectHandle< FixedArrayBase > from_elements, ElementsKind to_kind, DirectHandle< FixedArrayBase > to_elements)
static V8_EXPORT_PRIVATE void MigrateToMap(Isolate *isolate, DirectHandle< JSObject > object, DirectHandle< Map > new_map, int expected_additional_properties=0)
static DirectHandle< Map > GetElementsTransitionMap(DirectHandle< JSObject > object, ElementsKind to_kind)
static bool UpdateAllocationSite(DirectHandle< JSObject > object, ElementsKind to_kind)
static void EnsureWritableFastElements(DirectHandle< JSObject > object)
static const uint32_t kMinAddedElementsCapacity
static Handle< Map > Copy(Isolate *isolate, DirectHandle< Map > map, const char *reason, TransitionKindFlag kind=SPECIAL_TRANSITION)
static const uint32_t kPreferFastElementsSizeFactor
static const uint32_t kRequiresSlowElementsLimit
static V8_WARN_UNUSED_RESULT MaybeHandle< JSAny > GetPropertyWithAccessor(LookupIterator *it)
static V8_WARN_UNUSED_RESULT bool ToArrayIndex(Tagged< Object > obj, uint32_t *index)
static bool ToArrayLength(Tagged< Object > obj, uint32_t *index)
static V8_WARN_UNUSED_RESULT HandleType< Number >::MaybeType ToNumber(Isolate *isolate, HandleType< T > input)
static bool SameValueZero(Tagged< Object > obj, Tagged< Object > other)
static double NumberValue(Tagged< Number > obj)
static V8_EXPORT_PRIVATE bool StrictEquals(Tagged< Object > obj, Tagged< Object > that)
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT MaybeHandle< Object > GetProperty(LookupIterator *it, bool is_global_reference=false)
static bool ToUint32(Tagged< Object > obj, uint32_t *value)
static constexpr int kMaxLength
static constexpr PropertyDetails Empty(PropertyCellType cell_type=PropertyCellType::kNoCell)
static constexpr int ToInt(const Tagged< Object > object)
static constexpr Tagged< Smi > FromInt(int value)
static constexpr int kMaxValue
static V8_INLINE HandleType< String > Flatten(Isolate *isolate, HandleType< T > string, AllocationType allocation=AllocationType::kYoung)
static V8_INLINE Address DecompressTagged(TOnHeapAddress on_heap_addr, Tagged_t raw_value)
static void ForRange(Heap *heap, Tagged< HeapObject > object, TSlot start, TSlot end)
#define COMPRESS_POINTERS_BOOL
#define RAB_GSAB_TYPED_ARRAYS_WITH_NON_RAB_GSAB_ELEMENTS_KIND(V)
#define RAB_GSAB_TYPED_ARRAYS(V)
#define RETURN_FAILURE_IF_NOT_SUCCESSFUL(call)
#define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype)
#define ACCESSOR_ARRAY(Class, Kind, Store)
#define RETURN_NOTHING_IF_NOT_SUCCESSFUL(call)
#define ACCESSOR_DELETE(Class, Kind, Store)
#define ELEMENTS_TRAITS(Class, KindParam, Store)
#define ACCESSOR_KIND(Class, Kind, Store)
#define TYPED_ARRAYS_CASE(Type, type, TYPE, ctype)
#define ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call)
#define THROW_NEW_ERROR(isolate, call)
#define ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, value)
#define MAYBE_RETURN_NULL(call)
#define MAYBE_RETURN(call, value)
base::Vector< const DirectHandle< Object > > args
std::optional< TNode< JSArray > > a
ZoneVector< RpoNumber > & result
InstructionOperand destination
static V ReadUnalignedValue(Address p)
void Relaxed_Memcpy(volatile Atomic8 *dst, volatile const Atomic8 *src, size_t bytes)
constexpr bool IsInRange(T value, U lower_limit, U higher_limit)
static void WriteUnalignedValue(Address p, V value)
void Add(RWDigits Z, Digits X, Digits Y)
V8_INLINE constexpr bool IsFreeSpaceOrFiller(InstanceType instance_type)
V8_INLINE const Operation & Get(const Graph &graph, OpIndex index)
constexpr bool is_packed(ValueKind kind)
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
@ ALLOW_CONVERTED_DOUBLE_ELEMENTS
constexpr int kTaggedSize
bool IsNaN(Tagged< Object > obj)
PerThreadAssertScopeDebugOnly< false, SAFEPOINTS_ASSERT, HEAP_ALLOCATION_ASSERT > DisallowGarbageCollection
constexpr bool IsHoleyElementsKind(ElementsKind kind)
static DirectHandle< Object > MakeEntryPair(Isolate *isolate, size_t index, DirectHandle< Object > value)
SlotTraits::TObjectSlot ObjectSlot
void CopyTagged(Address dst, const Address src, size_t num_tagged)
bool IsNumber(Tagged< Object > obj)
ReadOnlyRoots GetReadOnlyRoots()
MaybeDirectHandle< Object > ArrayConstructInitializeElements(DirectHandle< JSArray > array, JavaScriptArguments *args)
Tagged(T object) -> Tagged< T >
constexpr bool IsSmiElementsKind(ElementsKind kind)
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in allocation gc speed threshold for starting incremental marking via a task in percent of available threshold for starting incremental marking immediately in percent of available Use a single schedule for determining a marking schedule between JS and C objects schedules the minor GC task with kUserVisible priority max worker number of concurrent for NumberOfWorkerThreads start background threads that allocate memory concurrent_array_buffer_sweeping use parallel threads to clear weak refs in the atomic pause trace progress of the incremental marking trace object counts and memory usage report a tick only when allocated zone memory changes by this amount TracingFlags::gc_stats store(v8::tracing::TracingCategoryObserver::ENABLED_BY_NATIVE)) DEFINE_GENERIC_IMPLICATION(trace_gc_object_stats
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
bool IsAnyNonextensibleElementsKind(ElementsKind kind)
constexpr bool IsObjectElementsKind(ElementsKind kind)
kStaticElementsTemplateOffset kInstancePropertiesTemplateOffset Tagged< FixedArray >
void MemsetTagged(Tagged_t *start, Tagged< MaybeObject > value, size_t counter)
constexpr bool IsFloat16TypedArrayElementsKind(ElementsKind kind)
bool IsNonextensibleElementsKind(ElementsKind kind)
@ HOLEY_NONEXTENSIBLE_ELEMENTS
@ SLOW_STRING_WRAPPER_ELEMENTS
@ PACKED_NONEXTENSIBLE_ELEMENTS
@ TERMINAL_FAST_ELEMENTS_KIND
@ SLOW_SLOPPY_ARGUMENTS_ELEMENTS
@ FAST_SLOPPY_ARGUMENTS_ELEMENTS
@ FAST_STRING_WRAPPER_ELEMENTS
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
return Cast< NumberDictionary >(elements(cage_base))
bool IsHoleyElementsKindForRead(ElementsKind kind)
PerThreadAssertScopeDebugOnly< true, SAFEPOINTS_ASSERT, HEAP_ALLOCATION_ASSERT > AllowGarbageCollection
bool IsSmiOrObjectElementsKind(ElementsKind kind)
constexpr int kSystemPointerSize
bool IsFastPackedElementsKind(ElementsKind kind)
V8_INLINE PtrComprCageBase GetPtrComprCageBase()
void CopyTypedArrayElementsToTypedArray(Address raw_source, Address raw_destination, uintptr_t length, uintptr_t offset)
ElementsKind GetHoleyElementsKind(ElementsKind packed_kind)
bool IsSloppyArgumentsElementsKind(ElementsKind kind)
DONT_OVERRIDE DISABLE_ALLOCATION_SITES HOLEY_ELEMENTS
bool IsBigIntTypedArrayElementsKind(ElementsKind kind)
bool IsFastElementsKind(ElementsKind kind)
void CopyWords(Address dst, const Address src, size_t num_words)
DONT_OVERRIDE DISABLE_ALLOCATION_SITES DISABLE_ALLOCATION_SITES HOLEY_DOUBLE_ELEMENTS
int32_t DoubleToInt32(double x)
bool IsHoleyOrDictionaryElementsKind(ElementsKind kind)
bool IsDictionaryElementsKind(ElementsKind kind)
V8_INLINE constexpr bool IsHeapObject(TaggedImpl< kRefType, StorageType > obj)
bool IsFloatTypedArrayElementsKind(ElementsKind kind)
V8_EXPORT_PRIVATE FlagValues v8_flags
void CopyTypedArrayElementsSlice(Address raw_source, Address raw_destination, uintptr_t start, uintptr_t end)
float DoubleToFloat32(double x)
@ kExternalUint8ClampedArray
uint16_t DoubleToFloat16(double value)
static bool IsMinusZero(double value)
Tagged< NumberDictionary >
tsan_relaxed_store_8_bits tsan_relaxed_store_32_bits tsan_seq_cst_store_8_bits tsan_seq_cst_store_32_bits tsan_relaxed_load_32_bits Address raw_context
constexpr bool IsDoubleElementsKind(ElementsKind kind)
constexpr int kElementsKindCount
constexpr int kDoubleSize
ElementsKind GetMoreGeneralElementsKind(ElementsKind from_kind, ElementsKind to_kind)
JSArrayBuffer::IsDetachableBit is_shared
constexpr bool IsIdentityMapping(const Mapping &mapping, size_t index)
ElementsKind GetInitialFastElementsKind()
void CopyFastNumberJSArrayElementsToTypedArray(Address raw_context, Address raw_source, Address raw_destination, uintptr_t length, uintptr_t offset)
bool TryNumberToSize(Tagged< Object > number, size_t *result)
constexpr uint32_t kMaxUInt32
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset IsNull(value)||IsJSProxy(value)||IsWasmObject(value)||(IsJSObject(value) &&(HeapLayout
uint32_t GetLength(Tagged< JSArray > array)
@ DONT_INITIALIZE_ARRAY_ELEMENTS
@ INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE
template const char * string
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
static constexpr RelaxedLoadTag kRelaxedLoad
Maybe< T > Just(const T &t)
#define DCHECK_LE(v1, v2)
#define CHECK_GE(lhs, rhs)
#define CHECK_LE(lhs, rhs)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK_NE(v1, v2)
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
#define DCHECK_GT(v1, v2)
constexpr bool IsAligned(T value, U alignment)
#define V8_WARN_UNUSED_RESULT
#define V8_UNLIKELY(condition)