// Copyright 2018 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_HEAP_OBJECT_H_ #define V8_OBJECTS_HEAP_OBJECT_H_ #include "src/globals.h" #include "src/objects.h" // Has to be the last include (doesn't have include guards): #include "src/objects/object-macros.h" namespace v8 { namespace internal { // This is the new way to represent the Object class. It is temporarily // separate to allow an incremental transition. // For a design overview, see https://goo.gl/Ph4CGz. class ObjectPtr { public: constexpr ObjectPtr() : ptr_(kNullAddress) {} explicit constexpr ObjectPtr(Address ptr) : ptr_(ptr) {} static ObjectPtr cast(Object* obj) { return ObjectPtr(obj->ptr()); } // Enable incremental transition. operator Object*() const { return reinterpret_cast<Object*>(ptr()); } // Make clang on Linux catch what MSVC complains about on Windows: operator bool() const = delete; bool operator==(const ObjectPtr other) const { return this->ptr() == other.ptr(); } bool operator!=(const ObjectPtr other) const { return this->ptr() != other.ptr(); } // Usage in std::set requires operator<. bool operator<(const ObjectPtr other) const { return this->ptr() < other.ptr(); } // Returns the tagged "(heap) object pointer" representation of this object. constexpr Address ptr() const { return ptr_; } ObjectPtr* operator->() { return this; } const ObjectPtr* operator->() const { return this; } #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 #define DECL_STRUCT_PREDICATE(NAME, Name, name) V8_INLINE bool Is##Name() const; STRUCT_LIST(DECL_STRUCT_PREDICATE) #undef DECL_STRUCT_PREDICATE #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 inline bool IsHashTableBase() const; V8_INLINE bool IsSmallOrderedHashTable() const; inline bool IsObject() const { return true; } inline double Number() const; inline bool ToInt32(int32_t* value) const; inline bool ToUint32(uint32_t* value) const; // ECMA-262 9.2. bool BooleanValue(Isolate* isolate); inline bool FilterKey(PropertyFilter filter); // 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); // 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; // // 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; } #ifdef VERIFY_HEAP void ObjectVerify(Isolate* isolate) { reinterpret_cast<Object*>(ptr())->ObjectVerify(isolate); } // Verify a pointer is a valid object pointer. static void VerifyPointer(Isolate* isolate, Object* p); #endif inline void VerifyApiCallResultType(); inline void ShortPrint(FILE* out = stdout); void ShortPrint(std::ostream& os); // NOLINT inline void Print(); inline void Print(std::ostream& os); // For use with std::unordered_set. struct Hasher { size_t operator()(const ObjectPtr o) const { return std::hash<v8::internal::Address>{}(o.ptr()); } }; private: friend class FullObjectSlot; Address ptr_; }; // In heap-objects.h to be usable without heap-objects-inl.h inclusion. bool ObjectPtr::IsSmi() const { return HAS_SMI_TAG(ptr()); } bool ObjectPtr::IsHeapObject() const { DCHECK_EQ(!IsSmi(), Internals::HasHeapObjectTag(ptr())); return !IsSmi(); } // Replacement for HeapObject; temporarily separate for incremental transition: class HeapObjectPtr : public ObjectPtr { public: inline Map map() const; inline void set_map(Map value); inline void set_map_after_allocation( Map value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER); // The no-write-barrier version. This is OK if the object is white and in // new space, or if the value is an immortal immutable object, like the maps // of primitive (non-JS) objects like strings, heap numbers etc. inline void set_map_no_write_barrier(Map value); inline MapWordSlot map_slot() const; inline MapWord map_word() const; inline void set_map_word(MapWord map_word); // Set the map using release store inline void synchronized_set_map(Map value); inline void synchronized_set_map_word(MapWord map_word); inline WriteBarrierMode GetWriteBarrierMode( const DisallowHeapAllocation& promise); // Enable incremental transition. operator HeapObject*() { return reinterpret_cast<HeapObject*>(ptr()); } operator const HeapObject*() const { return reinterpret_cast<const HeapObject*>(ptr()); } bool is_null() const { return ptr() == kNullAddress; } bool IsHeapObjectPtr() const { return IsHeapObject(); } inline ReadOnlyRoots GetReadOnlyRoots() const; #define IS_TYPE_FUNCTION_DECL(Type) V8_INLINE bool Is##Type() const; HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL) #undef IS_TYPE_FUNCTION_DECL V8_INLINE bool IsExternal(Isolate* isolate) const; // Untagged aligned address. inline Address address() const { return ptr() - kHeapObjectTag; } inline int Size() const; inline int SizeFromMap(Map map) const; inline ObjectSlot RawField(int byte_offset) const; inline MaybeObjectSlot RawMaybeWeakField(int byte_offset) const; #ifdef OBJECT_PRINT void PrintHeader(std::ostream& os, const char* id); // NOLINT #endif void HeapObjectVerify(Isolate* isolate); #ifdef VERIFY_HEAP inline void VerifyObjectField(Isolate* isolate, int offset); inline void VerifySmiField(int offset); inline void VerifyMaybeObjectField(Isolate* isolate, int offset); static void VerifyHeapPointer(Isolate* isolate, Object* p); #endif static const int kMapOffset = HeapObject::kMapOffset; static const int kHeaderSize = HeapObject::kHeaderSize; inline Address GetFieldAddress(int field_offset) const; DECL_CAST2(HeapObjectPtr) inline bool NeedsRehashing() const; protected: // Special-purpose constructor for subclasses that have fast paths where // their ptr() is a Smi. enum class AllowInlineSmiStorage { kRequireHeapObjectTag, kAllowBeingASmi }; inline HeapObjectPtr(Address ptr, AllowInlineSmiStorage allow_smi); OBJECT_CONSTRUCTORS(HeapObjectPtr, ObjectPtr) }; // Replacement for NeverReadOnlySpaceObject, temporarily separate for // incremental transition. // Helper class for objects that can never be in RO space. // TODO(leszeks): Add checks in the factory that we never allocate these objects // in RO space. // TODO(3770): Get rid of the duplication. class NeverReadOnlySpaceObjectPtr { public: // The Heap the object was allocated in. Used also to access Isolate. static inline Heap* GetHeap(const HeapObjectPtr object); // Convenience method to get current isolate. static inline Isolate* GetIsolate(const HeapObjectPtr object); }; } // namespace internal } // namespace v8 #include "src/objects/object-macros-undef.h" #endif // V8_OBJECTS_HEAP_OBJECT_H_