| // 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_MAYBE_OBJECT_H_ |
| #define V8_OBJECTS_MAYBE_OBJECT_H_ |
| |
| #include "include/v8-internal.h" |
| #include "include/v8.h" |
| #include "src/globals.h" |
| #include "src/objects.h" |
| #include "src/objects/slots.h" |
| #include "src/objects/smi.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| class HeapObject; |
| class Isolate; |
| class StringStream; |
| |
| // A MaybeObject is either a SMI, a strong reference to a HeapObject, a weak |
| // reference to a HeapObject, or a cleared weak reference. It's used for |
| // implementing in-place weak references (see design doc: goo.gl/j6SdcK ) |
| class MaybeObject { |
| public: |
| MaybeObject() : ptr_(kNullAddress) {} |
| explicit MaybeObject(Address ptr) : ptr_(ptr) {} |
| |
| bool operator==(const MaybeObject& other) const { return ptr_ == other.ptr_; } |
| bool operator!=(const MaybeObject& other) const { return ptr_ != other.ptr_; } |
| |
| Address ptr() const { return ptr_; } |
| |
| // Enable incremental transition of client code. |
| MaybeObject* operator->() { return this; } |
| const MaybeObject* operator->() const { return this; } |
| |
| bool IsSmi() const { return HAS_SMI_TAG(ptr_); } |
| inline bool ToSmi(Smi* value); |
| inline Smi ToSmi() const; |
| |
| bool IsCleared() const { |
| return static_cast<uint32_t>(ptr_) == kClearedWeakHeapObjectLower32; |
| } |
| |
| inline bool IsStrongOrWeak() const; |
| inline bool IsStrong() const; |
| |
| // If this MaybeObject is a strong pointer to a HeapObject, returns true and |
| // sets *result. Otherwise returns false. |
| inline bool GetHeapObjectIfStrong(HeapObject** result) const; |
| |
| // DCHECKs that this MaybeObject is a strong pointer to a HeapObject and |
| // returns the HeapObject. |
| inline HeapObject* GetHeapObjectAssumeStrong() const; |
| |
| inline bool IsWeak() const; |
| inline bool IsWeakOrCleared() const; |
| |
| // If this MaybeObject is a weak pointer to a HeapObject, returns true and |
| // sets *result. Otherwise returns false. |
| inline bool GetHeapObjectIfWeak(HeapObject** result) const; |
| |
| // DCHECKs that this MaybeObject is a weak pointer to a HeapObject and |
| // returns the HeapObject. |
| inline HeapObject* GetHeapObjectAssumeWeak() const; |
| |
| // If this MaybeObject is a strong or weak pointer to a HeapObject, returns |
| // true and sets *result. Otherwise returns false. |
| inline bool GetHeapObject(HeapObject** result) const; |
| inline bool GetHeapObject(HeapObject** result, |
| HeapObjectReferenceType* reference_type) const; |
| |
| // DCHECKs that this MaybeObject is a strong or a weak pointer to a HeapObject |
| // and returns the HeapObject. |
| inline HeapObject* GetHeapObject() const; |
| |
| // DCHECKs that this MaybeObject is a strong or a weak pointer to a HeapObject |
| // or a SMI and returns the HeapObject or SMI. |
| inline Object* GetHeapObjectOrSmi() const; |
| |
| inline bool IsObject() const; |
| template <typename T, typename = typename std::enable_if< |
| std::is_base_of<Object, T>::value>::type> |
| T* cast() const { |
| DCHECK(!HasWeakHeapObjectTag(ptr_)); |
| return T::cast(reinterpret_cast<Object*>(ptr_)); |
| } |
| // Replacement for the above, temporarily separate for incremental transition. |
| // TODO(3770): Get rid of the duplication. |
| template <typename T, typename = typename std::enable_if< |
| std::is_base_of<ObjectPtr, T>::value>::type> |
| T cast() const { |
| DCHECK(!HasWeakHeapObjectTag(ptr_)); |
| return T::cast(ObjectPtr(ptr_)); |
| } |
| |
| static MaybeObject FromSmi(Smi smi) { |
| DCHECK(HAS_SMI_TAG(smi->ptr())); |
| return MaybeObject(smi->ptr()); |
| } |
| |
| static MaybeObject FromObject(Object* object) { |
| DCHECK(!HasWeakHeapObjectTag(object)); |
| return MaybeObject(object->ptr()); |
| } |
| |
| static MaybeObject FromObject(ObjectPtr object) { |
| DCHECK(!HasWeakHeapObjectTag(object.ptr())); |
| return MaybeObject(object.ptr()); |
| } |
| |
| static inline MaybeObject MakeWeak(MaybeObject object); |
| |
| #ifdef VERIFY_HEAP |
| static void VerifyMaybeObjectPointer(Isolate* isolate, MaybeObject p); |
| #endif |
| |
| // Prints this object without details. |
| void ShortPrint(FILE* out = stdout); |
| |
| // Prints this object without details to a message accumulator. |
| void ShortPrint(StringStream* accumulator); |
| |
| void ShortPrint(std::ostream& os); |
| |
| #ifdef OBJECT_PRINT |
| void Print(); |
| void Print(std::ostream& os); |
| #else |
| void Print() { ShortPrint(); } |
| void Print(std::ostream& os) { ShortPrint(os); } |
| #endif |
| |
| private: |
| Address ptr_; |
| }; |
| |
| // A HeapObjectReference is either a strong reference to a HeapObject, a weak |
| // reference to a HeapObject, or a cleared weak reference. |
| class HeapObjectReference : public MaybeObject { |
| public: |
| explicit HeapObjectReference(Address address) : MaybeObject(address) {} |
| explicit HeapObjectReference(Object* object) : MaybeObject(object->ptr()) {} |
| |
| static HeapObjectReference Strong(Object* object) { |
| DCHECK(!object->IsSmi()); |
| DCHECK(!HasWeakHeapObjectTag(object)); |
| return HeapObjectReference(object); |
| } |
| |
| static HeapObjectReference Weak(Object* object) { |
| DCHECK(!object->IsSmi()); |
| DCHECK(!HasWeakHeapObjectTag(object)); |
| return HeapObjectReference(object->ptr() | kWeakHeapObjectMask); |
| } |
| |
| V8_INLINE static HeapObjectReference ClearedValue(Isolate* isolate); |
| |
| template <typename THeapObjectSlot> |
| V8_INLINE static void Update(THeapObjectSlot slot, HeapObject* value); |
| }; |
| |
| } // namespace internal |
| } // namespace v8 |
| |
| #endif // V8_OBJECTS_MAYBE_OBJECT_H_ |