1 // Copyright 2019 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_OBJECTS_TAGGED_IMPL_H_ 6 #define V8_OBJECTS_TAGGED_IMPL_H_ 7 8 #include "include/v8-internal.h" 9 #include "src/common/globals.h" 10 11 namespace v8 { 12 namespace internal { 13 14 // An TaggedImpl is a base class for Object (which is either a Smi or a strong 15 // reference to a HeapObject) and MaybeObject (which is either a Smi, a strong 16 // reference to a HeapObject, a weak reference to a HeapObject, or a cleared 17 // weak reference. 18 // This class provides storage and one canonical implementation of various 19 // predicates that check Smi and heap object tags' values and also take into 20 // account whether the tagged value is expected to be weak reference to a 21 // HeapObject or cleared weak reference. 22 template <HeapObjectReferenceType kRefType, typename StorageType> 23 class TaggedImpl { 24 public: 25 static_assert(std::is_same<StorageType, Address>::value || 26 std::is_same<StorageType, Tagged_t>::value, 27 "StorageType must be either Address or Tagged_t"); 28 29 // True for those TaggedImpl instantiations that represent uncompressed 30 // tagged values and false for TaggedImpl instantiations that represent 31 // compressed tagged values. 32 static const bool kIsFull = sizeof(StorageType) == kSystemPointerSize; 33 34 static const bool kCanBeWeak = kRefType == HeapObjectReferenceType::WEAK; 35 TaggedImpl()36 constexpr TaggedImpl() : ptr_{} {} TaggedImpl(StorageType ptr)37 explicit constexpr TaggedImpl(StorageType ptr) : ptr_(ptr) {} 38 39 // Make clang on Linux catch what MSVC complains about on Windows: 40 operator bool() const = delete; 41 42 template <typename U> 43 constexpr bool operator==(TaggedImpl<kRefType, U> other) const { 44 static_assert( 45 std::is_same<U, Address>::value || std::is_same<U, Tagged_t>::value, 46 "U must be either Address or Tagged_t"); 47 return static_cast<Tagged_t>(ptr_) == static_cast<Tagged_t>(other.ptr()); 48 } 49 template <typename U> 50 constexpr bool operator!=(TaggedImpl<kRefType, U> other) const { 51 static_assert( 52 std::is_same<U, Address>::value || std::is_same<U, Tagged_t>::value, 53 "U must be either Address or Tagged_t"); 54 return static_cast<Tagged_t>(ptr_) != static_cast<Tagged_t>(other.ptr()); 55 } 56 57 // For using in std::set and std::map. 58 constexpr bool operator<(TaggedImpl other) const { 59 return static_cast<Tagged_t>(ptr_) < static_cast<Tagged_t>(other.ptr()); 60 } 61 ptr()62 constexpr StorageType ptr() const { return ptr_; } 63 64 // Returns true if this tagged value is a strong pointer to a HeapObject or 65 // Smi. IsObject()66 constexpr inline bool IsObject() const { return !IsWeakOrCleared(); } 67 68 // Returns true if this tagged value is a Smi. IsSmi()69 constexpr bool IsSmi() const { return HAS_SMI_TAG(ptr_); } 70 inline bool ToSmi(Smi* value) const; 71 inline Smi ToSmi() const; 72 73 // Returns true if this tagged value is a strong pointer to a HeapObject. IsHeapObject()74 constexpr inline bool IsHeapObject() const { return IsStrong(); } 75 76 // Returns true if this tagged value is a cleared weak reference. IsCleared()77 constexpr inline bool IsCleared() const { 78 return kCanBeWeak && 79 (static_cast<uint32_t>(ptr_) == kClearedWeakHeapObjectLower32); 80 } 81 82 // Returns true if this tagged value is a strong or weak pointer to a 83 // HeapObject. IsStrongOrWeak()84 constexpr inline bool IsStrongOrWeak() const { 85 return !IsSmi() && !IsCleared(); 86 } 87 88 // Returns true if this tagged value is a strong pointer to a HeapObject. IsStrong()89 constexpr inline bool IsStrong() const { 90 DCHECK(kCanBeWeak || (!IsSmi() == HAS_STRONG_HEAP_OBJECT_TAG(ptr_))); 91 return kCanBeWeak ? HAS_STRONG_HEAP_OBJECT_TAG(ptr_) : !IsSmi(); 92 } 93 94 // Returns true if this tagged value is a weak pointer to a HeapObject. IsWeak()95 constexpr inline bool IsWeak() const { 96 return IsWeakOrCleared() && !IsCleared(); 97 } 98 99 // Returns true if this tagged value is a weak pointer to a HeapObject or 100 // cleared weak reference. IsWeakOrCleared()101 constexpr inline bool IsWeakOrCleared() const { 102 return kCanBeWeak && HAS_WEAK_HEAP_OBJECT_TAG(ptr_); 103 } 104 105 // 106 // The following set of methods get HeapObject out of the tagged value 107 // which may involve decompression in which case the isolate root is required. 108 // If the pointer compression is not enabled then the variants with 109 // isolate parameter will be exactly the same as the ones witout isolate 110 // parameter. 111 // 112 113 // If this tagged value is a strong pointer to a HeapObject, returns true and 114 // sets *result. Otherwise returns false. 115 inline bool GetHeapObjectIfStrong(HeapObject* result) const; 116 inline bool GetHeapObjectIfStrong(Isolate* isolate, HeapObject* result) const; 117 118 // DCHECKs that this tagged value is a strong pointer to a HeapObject and 119 // returns the HeapObject. 120 inline HeapObject GetHeapObjectAssumeStrong() const; 121 inline HeapObject GetHeapObjectAssumeStrong(Isolate* isolate) const; 122 123 // If this tagged value is a weak pointer to a HeapObject, returns true and 124 // sets *result. Otherwise returns false. 125 inline bool GetHeapObjectIfWeak(HeapObject* result) const; 126 inline bool GetHeapObjectIfWeak(Isolate* isolate, HeapObject* result) const; 127 128 // DCHECKs that this tagged value is a weak pointer to a HeapObject and 129 // returns the HeapObject. 130 inline HeapObject GetHeapObjectAssumeWeak() const; 131 inline HeapObject GetHeapObjectAssumeWeak(Isolate* isolate) const; 132 133 // If this tagged value is a strong or weak pointer to a HeapObject, returns 134 // true and sets *result. Otherwise returns false. 135 inline bool GetHeapObject(HeapObject* result) const; 136 inline bool GetHeapObject(Isolate* isolate, HeapObject* result) const; 137 138 inline bool GetHeapObject(HeapObject* result, 139 HeapObjectReferenceType* reference_type) const; 140 inline bool GetHeapObject(Isolate* isolate, HeapObject* result, 141 HeapObjectReferenceType* reference_type) const; 142 143 // DCHECKs that this tagged value is a strong or a weak pointer to a 144 // HeapObject and returns the HeapObject. 145 inline HeapObject GetHeapObject() const; 146 inline HeapObject GetHeapObject(Isolate* isolate) const; 147 148 // DCHECKs that this tagged value is a strong or a weak pointer to a 149 // HeapObject or a Smi and returns the HeapObject or Smi. 150 inline Object GetHeapObjectOrSmi() const; 151 inline Object GetHeapObjectOrSmi(Isolate* isolate) const; 152 153 // Cast operation is available only for full non-weak tagged values. 154 template <typename T> cast()155 T cast() const { 156 CHECK(kIsFull); 157 DCHECK(!HAS_WEAK_HEAP_OBJECT_TAG(ptr_)); 158 return T::cast(Object(ptr_)); 159 } 160 161 // Prints this object without details. 162 void ShortPrint(FILE* out = stdout); 163 164 // Prints this object without details to a message accumulator. 165 void ShortPrint(StringStream* accumulator); 166 167 void ShortPrint(std::ostream& os); 168 169 #ifdef OBJECT_PRINT 170 void Print(); 171 void Print(std::ostream& os); 172 #else Print()173 void Print() { ShortPrint(); } Print(std::ostream & os)174 void Print(std::ostream& os) { ShortPrint(os); } 175 #endif 176 177 private: 178 friend class CompressedObjectSlot; 179 friend class FullObjectSlot; 180 181 StorageType ptr_; 182 }; 183 184 } // namespace internal 185 } // namespace v8 186 187 #endif // V8_OBJECTS_TAGGED_IMPL_H_ 188