// 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" namespace v8 { namespace internal { class HeapObject; class Smi; 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); bool IsCleared() const { return ptr_ == kClearedWeakHeapObject; } 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> T* cast() const { DCHECK(!HasWeakHeapObjectTag(ptr_)); return T::cast(reinterpret_cast<Object*>(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 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); } static HeapObjectReference ClearedValue() { return HeapObjectReference(kClearedWeakHeapObject); } static inline void Update(HeapObjectSlot slot, HeapObject* value); }; } // namespace internal } // namespace v8 #endif // V8_OBJECTS_MAYBE_OBJECT_H_