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