// Copyright 2015 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_OBJECTS_H_ #define V8_OBJECTS_H_ #include <iosfwd> #include <memory> #include "include/v8-internal.h" #include "include/v8.h" #include "include/v8config.h" #include "src/assert-scope.h" #include "src/base/bits.h" #include "src/base/build_config.h" #include "src/base/flags.h" #include "src/base/logging.h" #include "src/checks.h" #include "src/constants-arch.h" #include "src/elements-kind.h" #include "src/field-index.h" #include "src/flags.h" #include "src/message-template.h" #include "src/objects-definitions.h" #include "src/property-details.h" #include "src/utils.h" // Has to be the last include (doesn't have include guards): #include "src/objects/object-macros.h" // // Most object types in the V8 JavaScript are described in this file. // // Inheritance hierarchy: // - Object // - Smi (immediate small integer) // - HeapObject (superclass for everything allocated in the heap) // - JSReceiver (suitable for property access) // - JSObject // - JSArray // - JSArrayBuffer // - JSArrayBufferView // - JSTypedArray // - JSDataView // - JSBoundFunction // - JSCollection // - JSSet // - JSMap // - JSStringIterator // - JSSetIterator // - JSMapIterator // - JSWeakCollection // - JSWeakMap // - JSWeakSet // - JSRegExp // - JSFunction // - JSGeneratorObject // - JSGlobalObject // - JSGlobalProxy // - JSValue // - JSDate // - JSMessageObject // - JSModuleNamespace // - JSV8BreakIterator // If V8_INTL_SUPPORT enabled. // - JSCollator // If V8_INTL_SUPPORT enabled. // - JSDateTimeFormat // If V8_INTL_SUPPORT enabled. // - JSListFormat // If V8_INTL_SUPPORT enabled. // - JSLocale // If V8_INTL_SUPPORT enabled. // - JSNumberFormat // If V8_INTL_SUPPORT enabled. // - JSPluralRules // If V8_INTL_SUPPORT enabled. // - JSRelativeTimeFormat // If V8_INTL_SUPPORT enabled. // - JSSegmentIterator // If V8_INTL_SUPPORT enabled. // - JSSegmenter // If V8_INTL_SUPPORT enabled. // - WasmExceptionObject // - WasmGlobalObject // - WasmInstanceObject // - WasmMemoryObject // - WasmModuleObject // - WasmTableObject // - JSProxy // - FixedArrayBase // - ByteArray // - BytecodeArray // - FixedArray // - FrameArray // - HashTable // - Dictionary // - StringTable // - StringSet // - CompilationCacheTable // - MapCache // - OrderedHashTable // - OrderedHashSet // - OrderedHashMap // - FeedbackMetadata // - TemplateList // - TransitionArray // - ScopeInfo // - ModuleInfo // - ScriptContextTable // - FixedDoubleArray // - Name // - String // - SeqString // - SeqOneByteString // - SeqTwoByteString // - SlicedString // - ConsString // - ThinString // - ExternalString // - ExternalOneByteString // - ExternalTwoByteString // - InternalizedString // - SeqInternalizedString // - SeqOneByteInternalizedString // - SeqTwoByteInternalizedString // - ConsInternalizedString // - ExternalInternalizedString // - ExternalOneByteInternalizedString // - ExternalTwoByteInternalizedString // - Symbol // - Context // - NativeContext // - HeapNumber // - BigInt // - Cell // - DescriptorArray // - PropertyCell // - PropertyArray // - Code // - AbstractCode, a wrapper around Code or BytecodeArray // - Map // - Oddball // - Foreign // - SmallOrderedHashTable // - SmallOrderedHashMap // - SmallOrderedHashSet // - SharedFunctionInfo // - Struct // - AccessorInfo // - AsmWasmData // - PromiseReaction // - PromiseCapability // - AccessorPair // - AccessCheckInfo // - InterceptorInfo // - CallHandlerInfo // - EnumCache // - TemplateInfo // - FunctionTemplateInfo // - ObjectTemplateInfo // - Script // - DebugInfo // - BreakPoint // - BreakPointInfo // - StackFrameInfo // - StackTraceFrame // - SourcePositionTableWithFrameCache // - CodeCache // - PrototypeInfo // - Microtask // - CallbackTask // - CallableTask // - PromiseReactionJobTask // - PromiseFulfillReactionJobTask // - PromiseRejectReactionJobTask // - PromiseResolveThenableJobTask // - Module // - ModuleInfoEntry // - FeedbackCell // - FeedbackVector // - PreparseData // - UncompiledData // - UncompiledDataWithoutPreparseData // - UncompiledDataWithPreparseData // // Formats of Object::ptr_: // Smi: [31 bit signed int] 0 // HeapObject: [32 bit direct pointer] (4 byte aligned) | 01 namespace v8 { namespace internal { struct InliningPosition; class PropertyDescriptorObject; // SKIP_WRITE_BARRIER skips the write barrier. // UPDATE_WEAK_WRITE_BARRIER skips the marking part of the write barrier and // only performs the generational part. // UPDATE_WRITE_BARRIER is doing the full barrier, marking and generational. enum WriteBarrierMode { SKIP_WRITE_BARRIER, UPDATE_WEAK_WRITE_BARRIER, UPDATE_WRITE_BARRIER }; // PropertyNormalizationMode is used to specify whether to keep // inobject properties when normalizing properties of a JSObject. enum PropertyNormalizationMode { CLEAR_INOBJECT_PROPERTIES, KEEP_INOBJECT_PROPERTIES }; // Indicates whether transitions can be added to a source map or not. enum TransitionFlag { INSERT_TRANSITION, OMIT_TRANSITION }; // Indicates whether the transition is simple: the target map of the transition // either extends the current map with a new property, or it modifies the // property that was added last to the current map. enum SimpleTransitionFlag { SIMPLE_PROPERTY_TRANSITION, PROPERTY_TRANSITION, SPECIAL_TRANSITION }; // Indicates whether we are only interested in the descriptors of a particular // map, or in all descriptors in the descriptor array. enum DescriptorFlag { ALL_DESCRIPTORS, OWN_DESCRIPTORS }; // Instance size sentinel for objects of variable size. const int kVariableSizeSentinel = 0; // We may store the unsigned bit field as signed Smi value and do not // use the sign bit. const int kStubMajorKeyBits = 8; const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1; // Result of an abstract relational comparison of x and y, implemented according // to ES6 section 7.2.11 Abstract Relational Comparison. enum class ComparisonResult { kLessThan, // x < y kEqual, // x = y kGreaterThan, // x > y kUndefined // at least one of x or y was undefined or NaN }; // (Returns false whenever {result} is kUndefined.) bool ComparisonResultToBool(Operation op, ComparisonResult result); enum class OnNonExistent { kThrowReferenceError, kReturnUndefined }; class AbstractCode; class AccessorPair; class AccessCheckInfo; class AllocationSite; class ByteArray; class CachedTemplateObject; class Cell; class ConsString; class DependentCode; class ElementsAccessor; class EnumCache; class FixedArrayBase; class FixedDoubleArray; class FreeSpace; class FunctionLiteral; class FunctionTemplateInfo; class JSAsyncGeneratorObject; class JSGlobalProxy; class JSPromise; class JSProxy; class JSProxyRevocableResult; class KeyAccumulator; class LayoutDescriptor; class LookupIterator; class FieldType; class Module; class ModuleInfoEntry; class MutableHeapNumber; class ObjectHashTable; class ObjectTemplateInfo; class ObjectVisitor; class PreparseData; class PropertyArray; class PropertyCell; class PropertyDescriptor; class PrototypeInfo; class ReadOnlyRoots; class RegExpMatchInfo; class RootVisitor; class SafepointEntry; class ScriptContextTable; class SharedFunctionInfo; class StringStream; class Symbol; class FeedbackCell; class FeedbackMetadata; class FeedbackVector; class UncompiledData; class TemplateInfo; class TransitionArray; class TemplateList; class WasmInstanceObject; class WasmMemoryObject; template <typename T> class ZoneForwardList; #ifdef OBJECT_PRINT #define DECL_PRINTER(Name) void Name##Print(std::ostream& os); // NOLINT #else #define DECL_PRINTER(Name) #endif #define OBJECT_TYPE_LIST(V) \ V(Smi) \ V(LayoutDescriptor) \ V(HeapObject) \ V(Primitive) \ V(Number) \ V(Numeric) #define HEAP_OBJECT_ORDINARY_TYPE_LIST_BASE(V) \ V(AbstractCode) \ V(AccessCheckNeeded) \ V(AllocationSite) \ V(ArrayList) \ V(BigInt) \ V(BigIntWrapper) \ V(ObjectBoilerplateDescription) \ V(Boolean) \ V(BooleanWrapper) \ V(BreakPoint) \ V(BreakPointInfo) \ V(ByteArray) \ V(BytecodeArray) \ V(CachedTemplateObject) \ V(CallHandlerInfo) \ V(Callable) \ V(Cell) \ V(ClassBoilerplate) \ V(Code) \ V(CodeDataContainer) \ V(CompilationCacheTable) \ V(ConsString) \ V(Constructor) \ V(Context) \ V(CoverageInfo) \ V(DataHandler) \ V(DeoptimizationData) \ V(DependentCode) \ V(DescriptorArray) \ V(EmbedderDataArray) \ V(EphemeronHashTable) \ V(EnumCache) \ V(ExternalOneByteString) \ V(ExternalString) \ V(ExternalTwoByteString) \ V(FeedbackCell) \ V(FeedbackMetadata) \ V(FeedbackVector) \ V(Filler) \ V(FixedArray) \ V(FixedArrayBase) \ V(FixedArrayExact) \ V(FixedBigInt64Array) \ V(FixedBigUint64Array) \ V(FixedDoubleArray) \ V(FixedFloat32Array) \ V(FixedFloat64Array) \ V(FixedInt16Array) \ V(FixedInt32Array) \ V(FixedInt8Array) \ V(FixedTypedArrayBase) \ V(FixedUint16Array) \ V(FixedUint32Array) \ V(FixedUint8Array) \ V(FixedUint8ClampedArray) \ V(Foreign) \ V(FrameArray) \ V(FreeSpace) \ V(Function) \ V(GlobalDictionary) \ V(HandlerTable) \ V(HeapNumber) \ V(InternalizedString) \ V(JSArgumentsObject) \ V(JSArgumentsObjectWithLength) \ V(JSArray) \ V(JSArrayBuffer) \ V(JSArrayBufferView) \ V(JSArrayIterator) \ V(JSAsyncFromSyncIterator) \ V(JSAsyncFunctionObject) \ V(JSAsyncGeneratorObject) \ V(JSBoundFunction) \ V(JSCollection) \ V(JSContextExtensionObject) \ V(JSDataView) \ V(JSDate) \ V(JSError) \ V(JSFunction) \ V(JSGeneratorObject) \ V(JSGlobalObject) \ V(JSGlobalProxy) \ V(JSMap) \ V(JSMapIterator) \ V(JSMessageObject) \ V(JSModuleNamespace) \ V(JSObject) \ V(JSPromise) \ V(JSProxy) \ V(JSReceiver) \ V(JSRegExp) \ V(JSRegExpResult) \ V(JSRegExpStringIterator) \ V(JSSet) \ V(JSSetIterator) \ V(JSSloppyArgumentsObject) \ V(JSStringIterator) \ V(JSTypedArray) \ V(JSValue) \ V(JSWeakRef) \ V(JSWeakCollection) \ V(JSFinalizationGroup) \ V(JSFinalizationGroupCleanupIterator) \ V(JSWeakMap) \ V(JSWeakSet) \ V(LoadHandler) \ V(Map) \ V(MapCache) \ V(Microtask) \ V(ModuleInfo) \ V(MutableHeapNumber) \ V(Name) \ V(NameDictionary) \ V(NativeContext) \ V(NormalizedMapCache) \ V(NumberDictionary) \ V(NumberWrapper) \ V(ObjectHashSet) \ V(ObjectHashTable) \ V(Oddball) \ V(OrderedHashMap) \ V(OrderedHashSet) \ V(OrderedNameDictionary) \ V(PreparseData) \ V(PromiseReactionJobTask) \ V(PropertyArray) \ V(PropertyCell) \ V(PropertyDescriptorObject) \ V(RegExpMatchInfo) \ V(ScopeInfo) \ V(ScriptContextTable) \ V(ScriptWrapper) \ V(SeqOneByteString) \ V(SeqString) \ V(SeqTwoByteString) \ V(SharedFunctionInfo) \ V(SimpleNumberDictionary) \ V(SlicedString) \ V(SloppyArgumentsElements) \ V(SmallOrderedHashMap) \ V(SmallOrderedHashSet) \ V(SmallOrderedNameDictionary) \ V(SourcePositionTableWithFrameCache) \ V(StoreHandler) \ V(String) \ V(StringSet) \ V(StringTable) \ V(StringWrapper) \ V(Struct) \ V(Symbol) \ V(SymbolWrapper) \ V(TemplateInfo) \ V(TemplateList) \ V(TemplateObjectDescription) \ V(ThinString) \ V(TransitionArray) \ V(UncompiledData) \ V(UncompiledDataWithPreparseData) \ V(UncompiledDataWithoutPreparseData) \ V(Undetectable) \ V(UniqueName) \ V(WasmExceptionObject) \ V(WasmGlobalObject) \ V(WasmInstanceObject) \ V(WasmMemoryObject) \ V(WasmModuleObject) \ V(WasmTableObject) \ V(WeakFixedArray) \ V(WeakArrayList) \ V(WeakCell) #ifdef V8_INTL_SUPPORT #define HEAP_OBJECT_ORDINARY_TYPE_LIST(V) \ HEAP_OBJECT_ORDINARY_TYPE_LIST_BASE(V) \ V(JSV8BreakIterator) \ V(JSCollator) \ V(JSDateTimeFormat) \ V(JSListFormat) \ V(JSLocale) \ V(JSNumberFormat) \ V(JSPluralRules) \ V(JSRelativeTimeFormat) \ V(JSSegmentIterator) \ V(JSSegmenter) #else #define HEAP_OBJECT_ORDINARY_TYPE_LIST(V) HEAP_OBJECT_ORDINARY_TYPE_LIST_BASE(V) #endif // V8_INTL_SUPPORT #define HEAP_OBJECT_TEMPLATE_TYPE_LIST(V) \ V(Dictionary) \ V(HashTable) #define HEAP_OBJECT_TYPE_LIST(V) \ HEAP_OBJECT_ORDINARY_TYPE_LIST(V) \ HEAP_OBJECT_TEMPLATE_TYPE_LIST(V) #define ODDBALL_LIST(V) \ V(Undefined, undefined_value) \ V(Null, null_value) \ V(TheHole, the_hole_value) \ V(Exception, exception) \ V(Uninitialized, uninitialized_value) \ V(True, true_value) \ V(False, false_value) \ V(ArgumentsMarker, arguments_marker) \ V(OptimizedOut, optimized_out) \ V(StaleRegister, stale_register) // The element types selection for CreateListFromArrayLike. enum class ElementTypes { kAll, kStringAndSymbol }; // TODO(mythria): Move this to a better place. ShouldThrow GetShouldThrow(Isolate* isolate, Maybe<ShouldThrow> should_throw); // Object is the abstract superclass for all classes in the // object hierarchy. // Object does not use any virtual functions to avoid the // allocation of the C++ vtable. // There must only be a single data member in Object: the Address ptr, // containing the tagged heap pointer that this Object instance refers to. // For a design overview, see https://goo.gl/Ph4CGz. class Object { public: constexpr Object() : ptr_(kNullAddress) {} explicit constexpr Object(Address ptr) : ptr_(ptr) {} // Make clang on Linux catch what MSVC complains about on Windows: operator bool() const = delete; bool operator==(const Object that) const { return this->ptr() == that.ptr(); } bool operator!=(const Object that) const { return this->ptr() != that.ptr(); } // Usage in std::set requires operator<. bool operator<(const Object that) const { return this->ptr() < that.ptr(); } // Returns the tagged "(heap) object pointer" representation of this object. constexpr Address ptr() const { return ptr_; } // These operator->() overloads are required for handlified code. Object* operator->() { return this; } const Object* operator->() const { return this; } // Type testing. bool IsObject() const { return true; } #define IS_TYPE_FUNCTION_DECL(Type) V8_INLINE bool Is##Type() const; OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL) HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL) #undef IS_TYPE_FUNCTION_DECL // Oddball checks are faster when they are raw pointer comparisons, so the // isolate/read-only roots overloads should be preferred where possible. #define IS_TYPE_FUNCTION_DECL(Type, Value) \ V8_INLINE bool Is##Type(Isolate* isolate) const; \ V8_INLINE bool Is##Type(ReadOnlyRoots roots) const; \ V8_INLINE bool Is##Type() const; ODDBALL_LIST(IS_TYPE_FUNCTION_DECL) #undef IS_TYPE_FUNCTION_DECL V8_INLINE bool IsNullOrUndefined(Isolate* isolate) const; V8_INLINE bool IsNullOrUndefined(ReadOnlyRoots roots) const; V8_INLINE bool IsNullOrUndefined() const; enum class Conversion { kToNumber, kToNumeric }; #define RETURN_FAILURE(isolate, should_throw, call) \ do { \ if ((should_throw) == kDontThrow) { \ return Just(false); \ } else { \ isolate->Throw(*isolate->factory()->call); \ return Nothing<bool>(); \ } \ } while (false) #define MAYBE_RETURN(call, value) \ do { \ if ((call).IsNothing()) return value; \ } while (false) #define MAYBE_RETURN_NULL(call) MAYBE_RETURN(call, MaybeHandle<Object>()) #define MAYBE_ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call) \ do { \ Isolate* __isolate__ = (isolate); \ if (!(call).To(&dst)) { \ DCHECK(__isolate__->has_pending_exception()); \ return ReadOnlyRoots(__isolate__).exception(); \ } \ } while (false) #define DECL_STRUCT_PREDICATE(NAME, Name, name) V8_INLINE bool Is##Name() const; STRUCT_LIST(DECL_STRUCT_PREDICATE) #undef DECL_STRUCT_PREDICATE // ES6, #sec-isarray. NOT to be confused with %_IsArray. V8_INLINE V8_WARN_UNUSED_RESULT static Maybe<bool> IsArray(Handle<Object> object); V8_INLINE bool IsHashTableBase() const; V8_INLINE bool IsSmallOrderedHashTable() const; // Extract the number. inline double Number() const; V8_INLINE bool IsNaN() const; V8_INLINE bool IsMinusZero() const; V8_EXPORT_PRIVATE bool ToInt32(int32_t* value); inline bool ToUint32(uint32_t* value) const; inline Representation OptimalRepresentation(); inline ElementsKind OptimalElementsKind(); inline bool FitsRepresentation(Representation representation); inline bool FilterKey(PropertyFilter filter); Handle<FieldType> OptimalType(Isolate* isolate, Representation representation); static Handle<Object> NewStorageFor(Isolate* isolate, Handle<Object> object, Representation representation); static Handle<Object> WrapForRead(Isolate* isolate, Handle<Object> object, Representation representation); // Returns true if the object is of the correct type to be used as a // implementation of a JSObject's elements. inline bool HasValidElements(); // ECMA-262 9.2. bool BooleanValue(Isolate* isolate); Object ToBoolean(Isolate* isolate); // ES6 section 7.2.11 Abstract Relational Comparison V8_WARN_UNUSED_RESULT static Maybe<ComparisonResult> Compare( Isolate* isolate, Handle<Object> x, Handle<Object> y); // ES6 section 7.2.12 Abstract Equality Comparison V8_WARN_UNUSED_RESULT static Maybe<bool> Equals(Isolate* isolate, Handle<Object> x, Handle<Object> y); // ES6 section 7.2.13 Strict Equality Comparison bool StrictEquals(Object that); // ES6 section 7.1.13 ToObject // Convert to a JSObject if needed. // native_context is used when creating wrapper object. // // Passing a non-null method_name allows us to give a more informative // error message for those cases where ToObject is being called on // the receiver of a built-in method. V8_WARN_UNUSED_RESULT static inline MaybeHandle<JSReceiver> ToObject( Isolate* isolate, Handle<Object> object, const char* method_name = nullptr); V8_WARN_UNUSED_RESULT static MaybeHandle<JSReceiver> ToObjectImpl( Isolate* isolate, Handle<Object> object, const char* method_name = nullptr); // ES6 section 9.2.1.2, OrdinaryCallBindThis for sloppy callee. V8_WARN_UNUSED_RESULT static MaybeHandle<JSReceiver> ConvertReceiver( Isolate* isolate, Handle<Object> object); // ES6 section 7.1.14 ToPropertyKey V8_WARN_UNUSED_RESULT static inline MaybeHandle<Name> ToName( Isolate* isolate, Handle<Object> input); // ES6 section 7.1.1 ToPrimitive V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> ToPrimitive( Handle<Object> input, ToPrimitiveHint hint = ToPrimitiveHint::kDefault); // ES6 section 7.1.3 ToNumber V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> ToNumber( Isolate* isolate, Handle<Object> input); V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> ToNumeric( Isolate* isolate, Handle<Object> input); // ES6 section 7.1.4 ToInteger V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> ToInteger( Isolate* isolate, Handle<Object> input); // ES6 section 7.1.5 ToInt32 V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> ToInt32( Isolate* isolate, Handle<Object> input); // ES6 section 7.1.6 ToUint32 V8_WARN_UNUSED_RESULT inline static MaybeHandle<Object> ToUint32( Isolate* isolate, Handle<Object> input); // ES6 section 7.1.12 ToString V8_WARN_UNUSED_RESULT static inline MaybeHandle<String> ToString( Isolate* isolate, Handle<Object> input); static Handle<String> NoSideEffectsToString(Isolate* isolate, Handle<Object> input); // ES6 section 7.1.14 ToPropertyKey V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> ToPropertyKey( Isolate* isolate, Handle<Object> value); // ES6 section 7.1.15 ToLength V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> ToLength( Isolate* isolate, Handle<Object> input); // ES6 section 7.1.17 ToIndex V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> ToIndex( Isolate* isolate, Handle<Object> input, MessageTemplate error_index); // ES6 section 7.3.9 GetMethod V8_WARN_UNUSED_RESULT static MaybeHandle<Object> GetMethod( Handle<JSReceiver> receiver, Handle<Name> name); // ES6 section 7.3.17 CreateListFromArrayLike V8_WARN_UNUSED_RESULT static MaybeHandle<FixedArray> CreateListFromArrayLike( Isolate* isolate, Handle<Object> object, ElementTypes element_types); // Get length property and apply ToLength. V8_WARN_UNUSED_RESULT static MaybeHandle<Object> GetLengthFromArrayLike( Isolate* isolate, Handle<JSReceiver> object); // ES6 section 12.5.6 The typeof Operator static Handle<String> TypeOf(Isolate* isolate, Handle<Object> object); // ES6 section 12.7 Additive Operators V8_WARN_UNUSED_RESULT static MaybeHandle<Object> Add(Isolate* isolate, Handle<Object> lhs, Handle<Object> rhs); // ES6 section 12.9 Relational Operators V8_WARN_UNUSED_RESULT static inline Maybe<bool> GreaterThan(Isolate* isolate, Handle<Object> x, Handle<Object> y); V8_WARN_UNUSED_RESULT static inline Maybe<bool> GreaterThanOrEqual( Isolate* isolate, Handle<Object> x, Handle<Object> y); V8_WARN_UNUSED_RESULT static inline Maybe<bool> LessThan(Isolate* isolate, Handle<Object> x, Handle<Object> y); V8_WARN_UNUSED_RESULT static inline Maybe<bool> LessThanOrEqual( Isolate* isolate, Handle<Object> x, Handle<Object> y); // ES6 section 7.3.19 OrdinaryHasInstance (C, O). V8_WARN_UNUSED_RESULT static MaybeHandle<Object> OrdinaryHasInstance( Isolate* isolate, Handle<Object> callable, Handle<Object> object); // ES6 section 12.10.4 Runtime Semantics: InstanceofOperator(O, C) V8_WARN_UNUSED_RESULT static MaybeHandle<Object> InstanceOf( Isolate* isolate, Handle<Object> object, Handle<Object> callable); V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle<Object> GetProperty(LookupIterator* it, OnNonExistent on_non_existent = OnNonExistent::kReturnUndefined); // ES6 [[Set]] (when passed kDontThrow) // Invariants for this and related functions (unless stated otherwise): // 1) When the result is Nothing, an exception is pending. // 2) When passed kThrowOnError, the result is never Just(false). // In some cases, an exception is thrown regardless of the ShouldThrow // argument. These cases are either in accordance with the spec or not // covered by it (eg., concerning API callbacks). V8_WARN_UNUSED_RESULT static Maybe<bool> SetProperty( LookupIterator* it, Handle<Object> value, StoreOrigin store_origin, Maybe<ShouldThrow> should_throw = Nothing<ShouldThrow>()); V8_WARN_UNUSED_RESULT static MaybeHandle<Object> SetProperty( Isolate* isolate, Handle<Object> object, Handle<Name> name, Handle<Object> value, StoreOrigin store_origin = StoreOrigin::kMaybeKeyed, Maybe<ShouldThrow> should_throw = Nothing<ShouldThrow>()); V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> SetPropertyOrElement( Isolate* isolate, Handle<Object> object, Handle<Name> name, Handle<Object> value, Maybe<ShouldThrow> should_throw = Nothing<ShouldThrow>(), StoreOrigin store_origin = StoreOrigin::kMaybeKeyed); V8_WARN_UNUSED_RESULT static Maybe<bool> SetSuperProperty( LookupIterator* it, Handle<Object> value, StoreOrigin store_origin, Maybe<ShouldThrow> should_throw = Nothing<ShouldThrow>()); V8_WARN_UNUSED_RESULT static Maybe<bool> CannotCreateProperty( Isolate* isolate, Handle<Object> receiver, Handle<Object> name, Handle<Object> value, Maybe<ShouldThrow> should_throw); V8_WARN_UNUSED_RESULT static Maybe<bool> WriteToReadOnlyProperty( LookupIterator* it, Handle<Object> value, Maybe<ShouldThrow> should_throw); V8_WARN_UNUSED_RESULT static Maybe<bool> WriteToReadOnlyProperty( Isolate* isolate, Handle<Object> receiver, Handle<Object> name, Handle<Object> value, ShouldThrow should_throw); V8_WARN_UNUSED_RESULT static Maybe<bool> RedefineIncompatibleProperty( Isolate* isolate, Handle<Object> name, Handle<Object> value, Maybe<ShouldThrow> should_throw); V8_WARN_UNUSED_RESULT static Maybe<bool> SetDataProperty( LookupIterator* it, Handle<Object> value); V8_WARN_UNUSED_RESULT static Maybe<bool> AddDataProperty( LookupIterator* it, Handle<Object> value, PropertyAttributes attributes, Maybe<ShouldThrow> should_throw, StoreOrigin store_origin); V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> GetPropertyOrElement( Isolate* isolate, Handle<Object> object, Handle<Name> name); V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> GetPropertyOrElement( Handle<Object> receiver, Handle<Name> name, Handle<JSReceiver> holder); V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> GetProperty( Isolate* isolate, Handle<Object> object, Handle<Name> name); V8_WARN_UNUSED_RESULT static MaybeHandle<Object> GetPropertyWithAccessor( LookupIterator* it); V8_WARN_UNUSED_RESULT static Maybe<bool> SetPropertyWithAccessor( LookupIterator* it, Handle<Object> value, Maybe<ShouldThrow> should_throw); V8_WARN_UNUSED_RESULT static MaybeHandle<Object> GetPropertyWithDefinedGetter( Handle<Object> receiver, Handle<JSReceiver> getter); V8_WARN_UNUSED_RESULT static Maybe<bool> SetPropertyWithDefinedSetter( Handle<Object> receiver, Handle<JSReceiver> setter, Handle<Object> value, Maybe<ShouldThrow> should_throw); V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> GetElement( Isolate* isolate, Handle<Object> object, uint32_t index); V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> SetElement( Isolate* isolate, Handle<Object> object, uint32_t index, Handle<Object> value, ShouldThrow should_throw); // Returns the permanent hash code associated with this object. May return // undefined if not yet created. inline Object GetHash(); // Returns the permanent hash code associated with this object depending on // the actual object type. May create and store a hash code if needed and none // exists. Smi GetOrCreateHash(Isolate* isolate); // Checks whether this object has the same value as the given one. This // function is implemented according to ES5, section 9.12 and can be used // to implement the Object.is function. V8_EXPORT_PRIVATE bool SameValue(Object other); // Checks whether this object has the same value as the given one. // +0 and -0 are treated equal. Everything else is the same as SameValue. // This function is implemented according to ES6, section 7.2.4 and is used // by ES6 Map and Set. bool SameValueZero(Object other); // ES6 section 9.4.2.3 ArraySpeciesCreate (part of it) V8_WARN_UNUSED_RESULT static MaybeHandle<Object> ArraySpeciesConstructor( Isolate* isolate, Handle<Object> original_array); // ES6 section 7.3.20 SpeciesConstructor ( O, defaultConstructor ) V8_WARN_UNUSED_RESULT static MaybeHandle<Object> SpeciesConstructor( Isolate* isolate, Handle<JSReceiver> recv, Handle<JSFunction> default_ctor); // Tries to convert an object to an array length. Returns true and sets the // output parameter if it succeeds. inline bool ToArrayLength(uint32_t* index) const; // Tries to convert an object to an array index. Returns true and sets the // output parameter if it succeeds. Equivalent to ToArrayLength, but does not // allow kMaxUInt32. V8_WARN_UNUSED_RESULT inline bool ToArrayIndex(uint32_t* index) const; // Returns true if the result of iterating over the object is the same // (including observable effects) as simply accessing the properties between 0 // and length. bool IterationHasObservableEffects(); // // The following GetHeapObjectXX methods mimic corresponding functionality // in MaybeObject. Having them here allows us to unify code that processes // ObjectSlots and MaybeObjectSlots. // // If this Object is a strong pointer to a HeapObject, returns true and // sets *result. Otherwise returns false. inline bool GetHeapObjectIfStrong(HeapObject* result) const; // If this Object is a strong pointer to a HeapObject (weak pointers are not // expected), returns true and sets *result. Otherwise returns false. inline bool GetHeapObject(HeapObject* result) const; // DCHECKs that this Object is a strong pointer to a HeapObject and returns // the HeapObject. inline HeapObject GetHeapObject() const; // Always returns false because Object is not expected to be a weak pointer // to a HeapObject. inline bool GetHeapObjectIfWeak(HeapObject* result) const { DCHECK(!HasWeakHeapObjectTag(ptr())); return false; } // Always returns false because Object is not expected to be a weak pointer // to a HeapObject. inline bool IsCleared() const { return false; } DECL_VERIFIER(Object) #ifdef VERIFY_HEAP // Verify a pointer is a valid object pointer. static void VerifyPointer(Isolate* isolate, Object p); #endif inline void VerifyApiCallResultType(); // Prints this object without details. void ShortPrint(FILE* out = stdout) const; // Prints this object without details to a message accumulator. void ShortPrint(StringStream* accumulator) const; void ShortPrint(std::ostream& os) const; // NOLINT inline static Object cast(Object object) { return object; } inline static Object unchecked_cast(Object object) { return object; } // Layout description. static const int kHeaderSize = 0; // Object does not take up any space. #ifdef OBJECT_PRINT // For our gdb macros, we should perhaps change these in the future. void Print() const; // Prints this object with details. void Print(std::ostream& os) const; // NOLINT #else void Print() const { ShortPrint(); } void Print(std::ostream& os) const { ShortPrint(os); } // NOLINT #endif // For use with std::unordered_set. struct Hasher { size_t operator()(const Object o) const { return std::hash<v8::internal::Address>{}(o.ptr()); } }; // For use with std::map. struct Comparer { bool operator()(const Object a, const Object b) const { return a.ptr() < b.ptr(); } }; private: friend class CompressedObjectSlot; friend class FullObjectSlot; friend class LookupIterator; friend class StringStream; // Return the map of the root of object's prototype chain. Map GetPrototypeChainRootMap(Isolate* isolate) const; // Returns a non-SMI for JSReceivers, but returns the hash code for // simple objects. This avoids a double lookup in the cases where // we know we will add the hash to the JSReceiver if it does not // already exist. // // Despite its size, this needs to be inlined for performance // reasons. static inline Object GetSimpleHash(Object object); // Helper for SetProperty and SetSuperProperty. // Return value is only meaningful if [found] is set to true on return. V8_WARN_UNUSED_RESULT static Maybe<bool> SetPropertyInternal( LookupIterator* it, Handle<Object> value, Maybe<ShouldThrow> should_throw, StoreOrigin store_origin, bool* found); V8_WARN_UNUSED_RESULT static MaybeHandle<Name> ConvertToName( Isolate* isolate, Handle<Object> input); V8_WARN_UNUSED_RESULT static MaybeHandle<Object> ConvertToPropertyKey( Isolate* isolate, Handle<Object> value); V8_WARN_UNUSED_RESULT static MaybeHandle<String> ConvertToString( Isolate* isolate, Handle<Object> input); V8_WARN_UNUSED_RESULT static MaybeHandle<Object> ConvertToNumberOrNumeric( Isolate* isolate, Handle<Object> input, Conversion mode); V8_WARN_UNUSED_RESULT static MaybeHandle<Object> ConvertToInteger( Isolate* isolate, Handle<Object> input); V8_WARN_UNUSED_RESULT static MaybeHandle<Object> ConvertToInt32( Isolate* isolate, Handle<Object> input); V8_WARN_UNUSED_RESULT static MaybeHandle<Object> ConvertToUint32( Isolate* isolate, Handle<Object> input); V8_WARN_UNUSED_RESULT static MaybeHandle<Object> ConvertToLength( Isolate* isolate, Handle<Object> input); V8_WARN_UNUSED_RESULT static MaybeHandle<Object> ConvertToIndex( Isolate* isolate, Handle<Object> input, MessageTemplate error_index); Address ptr_; }; V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, const Object& obj); // In objects.h to be usable without objects-inl.h inclusion. bool Object::IsSmi() const { return HAS_SMI_TAG(ptr()); } bool Object::IsHeapObject() const { DCHECK_EQ(!IsSmi(), Internals::HasHeapObjectTag(ptr())); return !IsSmi(); } struct Brief { V8_EXPORT_PRIVATE explicit Brief(const Object v); explicit Brief(const MaybeObject v); // {value} is a tagged heap object reference (weak or strong), equivalent to // a MaybeObject's payload. It has a plain Address type to keep #includes // lightweight. const Address value; }; V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, const Brief& v); // Objects should never have the weak tag; this variant is for overzealous // checking. V8_INLINE static bool HasWeakHeapObjectTag(const Object value) { return ((value->ptr() & kHeapObjectTagMask) == kWeakHeapObjectTag); } // Heap objects typically have a map pointer in their first word. However, // during GC other data (e.g. mark bits, forwarding addresses) is sometimes // encoded in the first word. The class MapWord is an abstraction of the // value in a heap object's first word. class MapWord { public: // Normal state: the map word contains a map pointer. // Create a map word from a map pointer. static inline MapWord FromMap(const Map map); // View this map word as a map pointer. inline Map ToMap() const; // Scavenge collection: the map word of live objects in the from space // contains a forwarding address (a heap object pointer in the to space). // True if this map word is a forwarding address for a scavenge // collection. Only valid during a scavenge collection (specifically, // when all map words are heap object pointers, i.e. not during a full GC). inline bool IsForwardingAddress() const; // Create a map word from a forwarding address. static inline MapWord FromForwardingAddress(HeapObject object); // View this map word as a forwarding address. inline HeapObject ToForwardingAddress(); static inline MapWord FromRawValue(uintptr_t value) { return MapWord(value); } inline uintptr_t ToRawValue() { return value_; } private: // HeapObject calls the private constructor and directly reads the value. friend class HeapObject; explicit MapWord(Address value) : value_(value) {} Address value_; }; template <int start_offset, int end_offset, int size> class FixedBodyDescriptor; template <int start_offset> class FlexibleBodyDescriptor; template <int start_offset> class FlexibleWeakBodyDescriptor; template <class ParentBodyDescriptor, class ChildBodyDescriptor> class SubclassBodyDescriptor; enum EnsureElementsMode { DONT_ALLOW_DOUBLE_ELEMENTS, ALLOW_COPIED_DOUBLE_ELEMENTS, ALLOW_CONVERTED_DOUBLE_ELEMENTS }; // Indicator for one component of an AccessorPair. enum AccessorComponent { ACCESSOR_GETTER, ACCESSOR_SETTER }; enum class GetKeysConversion { kKeepNumbers = static_cast<int>(v8::KeyConversionMode::kKeepNumbers), kConvertToString = static_cast<int>(v8::KeyConversionMode::kConvertToString) }; enum class KeyCollectionMode { kOwnOnly = static_cast<int>(v8::KeyCollectionMode::kOwnOnly), kIncludePrototypes = static_cast<int>(v8::KeyCollectionMode::kIncludePrototypes) }; // Utility superclass for stack-allocated objects that must be updated // on gc. It provides two ways for the gc to update instances, either // iterating or updating after gc. class Relocatable { public: explicit inline Relocatable(Isolate* isolate); inline virtual ~Relocatable(); virtual void IterateInstance(RootVisitor* v) {} virtual void PostGarbageCollection() { } static void PostGarbageCollectionProcessing(Isolate* isolate); static int ArchiveSpacePerThread(); static char* ArchiveState(Isolate* isolate, char* to); static char* RestoreState(Isolate* isolate, char* from); static void Iterate(Isolate* isolate, RootVisitor* v); static void Iterate(RootVisitor* v, Relocatable* top); static char* Iterate(RootVisitor* v, char* t); private: Isolate* isolate_; Relocatable* prev_; }; // BooleanBit is a helper class for setting and getting a bit in an integer. class BooleanBit : public AllStatic { public: static inline bool get(int value, int bit_position) { return (value & (1 << bit_position)) != 0; } static inline int set(int value, int bit_position, bool v) { if (v) { value |= (1 << bit_position); } else { value &= ~(1 << bit_position); } return value; } }; } // NOLINT, false-positive due to second-order macros. } // NOLINT, false-positive due to second-order macros. #include "src/objects/object-macros-undef.h" #endif // V8_OBJECTS_H_