5#ifndef V8_OBJECTS_JS_OBJECTS_INL_H_
6#define V8_OBJECTS_JS_OBJECTS_INL_H_
43#include "torque-generated/src/objects/js-objects-tq-inl.inc"
55JSIteratorResult::JSIteratorResult(
Address ptr) : JSObject(ptr) {}
69 return elements(cage_base, tag);
89 if (!it.IsFound())
return it.factory()->undefined_value();
90 return Object::GetProperty(&it);
97 if (!it.IsFound())
return it.factory()->undefined_value();
98 return Object::GetProperty(&it);
105 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
106 if (!it.IsFound())
return it.factory()->undefined_value();
107 return GetDataProperty(&it);
116 PrototypeIterator::END_AT_NON_HIDDEN);
120 return PrototypeIterator::GetCurrent(iter);
127 return GetProperty(isolate,
receiver, str);
133 return KeyAccumulator::GetKeys(isolate,
object, KeyCollectionMode::kOwnOnly,
135 GetKeysConversion::kConvertToString);
138bool JSObject::PrototypeHasNoElements(
Isolate* isolate,
146 roots.empty_slow_element_dictionary();
147 while (prototype !=
null) {
151 if (elements != empty_fixed_array &&
152 elements != empty_slow_element_dictionary) {
155 prototype = Cast<HeapObject>(map->prototype());
161 kPropertiesOrHashOffset)
163 kPropertiesOrHashOffset)
167 JSObject::ValidateElements(*
object);
168 ElementsKind elements_kind =
object->map()->elements_kind();
178template <
typename TSlot>
180 TSlot objects, uint32_t
count,
182 static_assert(std::is_same<TSlot, FullObjectSlot>::value ||
183 std::is_same<TSlot, ObjectSlot>::value,
184 "Only ObjectSlot and FullObjectSlot are expected here");
193#ifdef V8_ENABLE_EXPERIMENTAL_UNDEFINED_DOUBLE
196 for (uint32_t
i = 0;
i <
count; ++
i, ++objects) {
198 if (current == the_hole
199#ifdef V8_ENABLE_EXPERIMENTAL_UNDEFINED_DOUBLE
200 || current == undefined
205 }
else if (!
IsSmi(current)) {
214 }
else if (is_holey) {
223 if (target_kind != current_kind) {
224 TransitionElementsKind(
object, target_kind);
233 if (elements->map() != roots.fixed_double_array_map()) {
234 DCHECK(elements->map() == roots.fixed_array_map() ||
235 elements->map() == roots.fixed_cow_array_map());
239 ObjectSlot objects = Cast<FixedArray>(elements)->RawFieldOfFirstElement();
240 EnsureCanContainElements(
object, objects, length, mode);
248 auto double_array = Cast<FixedDoubleArray>(elements);
250 if (double_array->is_the_hole(
i)) {
262 Isolate* isolate =
object->GetIsolate();
263 JSObject::MigrateToMap(isolate,
object, new_map);
264 DCHECK((object->map()->has_fast_smi_or_object_elements() ||
266 object->map()->has_fast_string_wrapper_elements()) ==
268 value->map() ==
ReadOnlyRoots(isolate).fixed_cow_array_map()));
270 (object->map()->has_fast_double_elements() ==
271 IsFixedDoubleArray(*value)));
272 object->set_elements(*value);
275void JSObject::initialize_elements() {
281 return map(cage_base)->GetIndexedInterceptor(cage_base);
285 return map(cage_base)->GetNamedInterceptor(cage_base);
294 return instance_type == JS_OBJECT_TYPE
295 ? JSObject::kHeaderSize
296 : GetHeaderSize(instance_type, map->has_prototype_slot());
302 return GetHeaderSize(map);
305int JSObject::GetEmbedderFieldsStartOffset() {
306 return GetEmbedderFieldsStartOffset(
map());
315 return InstanceTypeChecker::IsJSObjectWithEmbedderSlots(instance_type) ||
316 InstanceTypeChecker::IsJSAPIObjectWithEmbedderSlots(instance_type) ||
317 InstanceTypeChecker::IsJSSpecialObject(instance_type);
320bool JSObject::MayHaveEmbedderFields()
const {
321 return MayHaveEmbedderFields(
map());
326 int instance_size = map->instance_size();
333 return (((instance_size - GetEmbedderFieldsStartOffset(map)) >>
335 map->GetInObjectProperties()) /
339int JSObject::GetEmbedderFieldCount()
const {
340 return GetEmbedderFieldCount(
map());
343int JSObject::GetEmbedderFieldOffset(
int index) {
345 static_cast<unsigned>(GetEmbedderFieldCount()));
354 EmbedderDataSlot::store_tagged(
Tagged(*
this), index, value);
363 auto instance_type = map->instance_type();
364 return InstanceTypeChecker::IsJSApiObject(instance_type) ||
365 instance_type == JS_SPECIAL_API_OBJECT_TYPE;
368bool JSObject::IsDroppableApiObject()
const {
369 return IsDroppableApiObject(
map());
377 return RawFastPropertyAt(cage_base, index);
382 if (index.is_inobject()) {
385 return property_array(cage_base)->get(cage_base,
386 index.outobject_array_index());
395 return RawFastPropertyAt(cage_base, index, tag);
401 if (index.is_inobject()) {
404 return property_array(cage_base)->get(cage_base,
405 index.outobject_array_index(), tag);
409std::optional<Tagged<Object>> JSObject::RawInobjectPropertyAt(
412 CHECK(index.is_inobject());
441 if (original_map !=
map(cage_base, kAcquireLoad))
return {};
442 return maybe_tagged_object;
448 DCHECK(index.is_inobject());
449 int offset = index.offset();
457 DCHECK(index.is_inobject());
465 if (index.is_inobject()) {
466 RawFastInobjectPropertyAtPut(index, value, mode);
469 property_array()->set(index.outobject_array_index(), value);
475 if (index.is_inobject()) {
476 RawFastInobjectPropertyAtPut(index, value, tag);
478 property_array()->set(index.outobject_array_index(), value, tag);
496 bits = base::bit_cast<uint64_t>(
static_cast<double>(Smi::ToInt(value)));
497 }
else if (IsUninitialized(value)) {
500 DCHECK(IsHeapNumber(value));
501 bits = Cast<HeapNumber>(value)->value_as_bits();
503 auto box = Cast<HeapNumber>(RawFastPropertyAt(index));
504 box->set_value_as_bits(bits);
506 FastPropertyAtPut(index, value);
513 DCHECK(index.is_inobject());
515 int offset = index.offset();
524 if (index.is_inobject()) {
525 return RawFastInobjectPropertyAtSwap(index, value, tag);
527 return property_array()->Swap(index.outobject_array_index(), value, tag);
533 DCHECK(index.is_inobject());
537 if (previous_value == expected) {
541 return previous_value;
547 if (index.is_inobject()) {
548 return RawFastInobjectPropertyAtCompareAndSwap(index, expected, value, tag);
550 return property_array()->CompareAndSwap(index.outobject_array_index(),
551 expected, value, tag);
554int JSObject::GetInObjectPropertyOffset(
int index) {
555 return map()->GetInObjectPropertyOffset(index);
559 int offset = GetInObjectPropertyOffset(index);
566 int offset = GetInObjectPropertyOffset(index);
573 bool is_slack_tracking_in_progress,
576 int size = map->instance_size();
577 int offset = start_offset;
580 if (MayHaveEmbedderFields(map)) {
581 int embedder_field_start = GetEmbedderFieldsStartOffset(map);
582 int embedder_field_count = GetEmbedderFieldCount(map);
586 while (
offset < embedder_field_start) {
593 for (
int i = 0;
i < embedder_field_count;
i++) {
599 DCHECK_EQ(0, GetEmbedderFieldCount(map));
603 if (is_slack_tracking_in_progress) {
604 int end_of_pre_allocated_offset =
605 size - (map->UnusedPropertyFields() *
kTaggedSize);
606 DCHECK_LE(kHeaderSize, end_of_pre_allocated_offset);
609 while (
offset < end_of_pre_allocated_offset) {
628template <
typename T,
template <
typename>
typename HandleType>
630inline typename HandleType<Object>::MaybeType
637 it, value, attributes,
Just(ShouldThrow::kThrowOnError), handling,
645 kExternalObjectValueTag)
651template <CppHeapPo
interTag lower_bound, CppHeapPo
interTag upper_bound>
652void* JSApiWrapper::GetCppHeapWrappable(
654 return reinterpret_cast<void*
>(
655 object_->ReadCppHeapPointerField<lower_bound, upper_bound>(
656 kCppHeapWrappableOffset,
isolate));
659void* JSApiWrapper::GetCppHeapWrappable(
662 return reinterpret_cast<void*
>(
object_->ReadCppHeapPointerField(
663 kCppHeapWrappableOffset, isolate, tag_range));
666template <CppHeapPo
interTag tag>
669 object_->WriteLazilyInitializedCppHeapPointerField<tag>(
670 JSAPIObjectWithEmbedderSlots::kCppHeapWrappableOffset,
isolate,
671 reinterpret_cast<Address
>(instance));
672 WriteBarrier::ForCppHeapPointer(
674 object_->RawCppHeapPointerField(
675 JSAPIObjectWithEmbedderSlots::kCppHeapWrappableOffset),
681 object_->WriteLazilyInitializedCppHeapPointerField(
682 JSAPIObjectWithEmbedderSlots::kCppHeapWrappableOffset, isolate,
683 reinterpret_cast<Address
>(instance), tag);
684 WriteBarrier::ForCppHeapPointer(
686 object_->RawCppHeapPointerField(
687 JSAPIObjectWithEmbedderSlots::kCppHeapWrappableOffset),
691bool JSMessageObject::DidEnsureSourcePositionsAvailable()
const {
692 return shared_info() == Smi::zero();
696void JSMessageObject::EnsureSourcePositionsAvailable(
698 if (message->DidEnsureSourcePositionsAvailable()) {
699 DCHECK(message->script()->has_line_ends());
701 JSMessageObject::InitializeSourcePositions(isolate, message);
705int JSMessageObject::GetStartPosition()
const {
708 return start_position();
711int JSMessageObject::GetEndPosition()
const {
714 return end_position();
722 set_raw_type(
static_cast<int>(value));
734#if VERIFY_HEAP && DEBUG
740 if (ElementsAreSafeToExamine(cage_base)) {
746 CHECK(IsFixedDoubleArray(fixed_array, cage_base) ||
749 CHECK(IsFixedArray(fixed_array, cage_base));
750 CHECK(IsNumberDictionary(fixed_array, cage_base));
755 IsSloppyArgumentsElements(elements(cage_base)));
762 return ElementsAccessor::ForKind(GetElementsKind(cage_base));
842 DCHECK(!elements(cage_base).is_null());
843 return map(cage_base)->has_typed_array_or_rab_gsab_typed_array_elements();
846#define FIXED_TYPED_ELEMENTS_CHECK(Type, type, TYPE, ctype) \
847 DEF_GETTER(JSObject, HasFixed##Type##Elements, bool) { \
848 return map(cage_base)->elements_kind() == TYPE##_ELEMENTS; \
853#undef FIXED_TYPED_ELEMENTS_CHECK
856 return map(cage_base)->has_named_interceptor();
860 return map(cage_base)->has_indexed_interceptor();
865 kPropertiesOrHashOffset,
866 !HasFastProperties(cage_base),
true)
869 DCHECK(HasDictionaryElements(cage_base) ||
870 HasSlowStringWrapperElements(cage_base));
871 return Cast<NumberDictionary>(elements(cage_base));
874void JSReceiver::initialize_properties(
Isolate* isolate) {
876 DCHECK(!HeapLayout::InYoungGeneration(roots.empty_fixed_array()));
877 DCHECK(!HeapLayout::InYoungGeneration(roots.empty_property_dictionary()));
878 DCHECK(!HeapLayout::InYoungGeneration(
879 roots.empty_ordered_property_dictionary()));
880 if (
map(isolate)->is_dictionary_map()) {
883 roots.empty_swiss_property_dictionary());
886 roots.empty_property_dictionary());
889 WRITE_FIELD(*
this, kPropertiesOrHashOffset, roots.empty_fixed_array());
897 ((IsGlobalDictionary(raw_properties_or_hash_obj, cage_base) ||
898 IsPropertyDictionary(raw_properties_or_hash_obj, cage_base)) ==
899 map(cage_base)->is_dictionary_map()));
900 USE(raw_properties_or_hash_obj);
901 return !
map(cage_base)->is_dictionary_map();
905 DCHECK(!IsJSGlobalObject(*
this, cage_base));
906 DCHECK(!HasFastProperties(cage_base));
913 return Cast<NameDictionary>(prop);
917 DCHECK(!IsJSGlobalObject(*
this, cage_base));
918 DCHECK(!HasFastProperties(cage_base));
925 return Cast<SwissNameDictionary>(prop);
931 DCHECK(HasFastProperties(cage_base));
936 return Cast<PropertyArray>(prop);
939std::optional<Tagged<NativeContext>> JSReceiver::GetCreationContext() {
942 DCHECK(IsMapMap(meta_map));
943 Tagged<Object> maybe_native_context = meta_map->native_context_or_null();
944 if (
IsNull(maybe_native_context))
return {};
945 DCHECK(IsNativeContext(maybe_native_context));
946 return Cast<NativeContext>(maybe_native_context);
952 std::optional<Tagged<NativeContext>> maybe_context = GetCreationContext();
953 if (!maybe_context.has_value())
return {};
960 return HasPropertyOrElement(isolate,
object,
PropertyKey(isolate, name));
967 return HasProperty(&it);
974 return HasProperty(&it);
980 if (IsJSObject(*
object)) {
981 LookupIterator it(isolate,
object, index,
object, LookupIterator::OWN);
982 return HasProperty(&it);
986 JSReceiver::GetOwnPropertyAttributes(isolate,
object, index);
996 return GetPropertyAttributes(&it);
1004 return GetPropertyAttributes(&it);
1009 LookupIterator it(isolate,
object, index,
object, LookupIterator::OWN);
1010 return GetPropertyAttributes(&it);
1016 return GetPropertyAttributes(&it);
1021 LookupIterator it(isolate,
object, index,
object, LookupIterator::OWN);
1022 return GetPropertyAttributes(&it);
1026 return *GetCreationContext();
1029bool JSGlobalObject::IsDetached() {
1030 return global_proxy()->IsDetachedFrom(*
this);
1038inline int JSGlobalProxy::SizeWithEmbedderFields(
int embedder_field_count) {
1049static inline
bool ShouldConvertToSlowElements(uint32_t used_elements,
1050 uint32_t new_capacity) {
1051 uint32_t size_threshold = NumberDictionary::kPreferFastElementsSizeFactor *
1052 NumberDictionary::ComputeCapacity(used_elements) *
1053 NumberDictionary::kEntrySize;
1054 return size_threshold <= new_capacity;
1060 uint32_t* new_capacity) {
1061 static_assert(JSObject::kMaxUncheckedOldFastElementsLength <=
1062 JSObject::kMaxUncheckedFastElementsLength);
1063 if (index < capacity) {
1064 *new_capacity = capacity;
1067 if (index - capacity >= JSObject::kMaxGap)
return true;
1068 *new_capacity = JSObject::NewElementsCapacity(index + 1);
1070 if (*new_capacity <= JSObject::kMaxUncheckedOldFastElementsLength ||
1071 (*new_capacity <= JSObject::kMaxUncheckedFastElementsLength &&
1072 HeapLayout::InYoungGeneration(
object))) {
V8_INLINE T FromJust() const &
V8_INLINE void store_smi(Tagged< Smi > value)
V8_INLINE Tagged< Object > load_tagged() const
V8_INLINE void Initialize(Tagged< Object > initial_value)
constexpr Address ptr() const
PropertyLocation location() const
Representation representation() const
PropertyKind kind() const
V8_WARN_UNUSED_RESULT bool AdvanceFollowingProxies()
Tagged< T > GetCurrent() const
constexpr bool IsDouble() const
#define V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL
#define MAYBE_RETURN_NULL(call)
#define MAYBE_RETURN(call, value)
#define FIXED_TYPED_ELEMENTS_CHECK(Type, type, TYPE, ctype)
@ DONT_ALLOW_DOUBLE_ELEMENTS
@ ALLOW_CONVERTED_DOUBLE_ELEMENTS
@ ALLOW_COPIED_DOUBLE_ELEMENTS
MessageTemplate MessageTemplateFromInt(int message_id)
bool IsSlowArgumentsElementsKind(ElementsKind kind)
constexpr int kTaggedSize
constexpr bool IsHoleyElementsKind(ElementsKind kind)
bool IsNumber(Tagged< Object > obj)
ReadOnlyRoots GetReadOnlyRoots()
bool IsSealedElementsKind(ElementsKind kind)
constexpr int kEmbedderDataSlotSize
bool IsCustomElementsReceiverMap(Tagged< Map > map)
constexpr bool IsSmiElementsKind(ElementsKind kind)
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
constexpr uint64_t kHoleNanInt64
bool IsAnyNonextensibleElementsKind(ElementsKind kind)
constexpr bool IsObjectElementsKind(ElementsKind kind)
bool IsNonextensibleElementsKind(ElementsKind kind)
@ SLOW_STRING_WRAPPER_ELEMENTS
@ FAST_STRING_WRAPPER_ELEMENTS
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
const int kVariableSizeSentinel
bool IsSmiOrObjectElementsKind(ElementsKind kind)
bool IsFastArgumentsElementsKind(ElementsKind kind)
bool IsFastPackedElementsKind(ElementsKind kind)
V8_INLINE PtrComprCageBase GetPtrComprCageBase()
constexpr int kTaggedSizeLog2
constexpr int kEmbedderDataSlotSizeInTaggedSlots
ElementsKind GetHoleyElementsKind(ElementsKind packed_kind)
bool IsShared(Tagged< Object > obj)
bool IsSloppyArgumentsElementsKind(ElementsKind kind)
DONT_OVERRIDE DISABLE_ALLOCATION_SITES HOLEY_ELEMENTS
bool IsFastElementsKind(ElementsKind kind)
DONT_OVERRIDE DISABLE_ALLOCATION_SITES DISABLE_ALLOCATION_SITES HOLEY_DOUBLE_ELEMENTS
bool IsDictionaryElementsKind(ElementsKind kind)
static bool ShouldConvertToSlowElements(uint32_t used_elements, uint32_t new_capacity)
bool IsJSApiWrapperObject(Tagged< Map > map)
bool IsStringWrapperElementsKind(ElementsKind kind)
constexpr bool IsDoubleElementsKind(ElementsKind kind)
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset IsNull(value)||IsJSProxy(value)||IsWasmObject(value)||(IsJSObject(value) &&(HeapLayout
Maybe< T > Just(const T &t)
#define SEQ_CST_COMPARE_AND_SWAP_FIELD(p, offset, expected, value)
#define EXTERNAL_POINTER_ACCESSORS(holder, name, type, offset, tag)
#define ACCESSORS(holder, name, type, offset)
#define RELEASE_ACQUIRE_ACCESSORS_CHECKED2(holder, name, type, offset, get_condition, set_condition)
#define WRITE_FIELD(p, offset, value)
#define TQ_OBJECT_CONSTRUCTORS_IMPL(Type)
#define SMI_ACCESSORS(holder, name, offset)
#define CONDITIONAL_WRITE_BARRIER(object, offset, value, mode)
#define SEQ_CST_WRITE_FIELD(p, offset, value)
#define SEQ_CST_SWAP_FIELD(p, offset, value)
#define RELAXED_WRITE_FIELD(p, offset, value)
#define RELAXED_ACCESSORS(holder, name, type, offset)
#define NEVER_READ_ONLY_SPACE_IMPL(Type)
#define DEF_GETTER(Camel, Lower, Bit)
#define DCHECK_LE(v1, v2)
#define CHECK_IMPLIES(lhs, rhs)
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
#define V8_WARN_UNUSED_RESULT
std::unique_ptr< ValueMirror > value
std::unique_ptr< ValueMirror > key