1 | // Copyright 2018 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_MAYBE_OBJECT_H_ |
6 | #define V8_OBJECTS_MAYBE_OBJECT_H_ |
7 | |
8 | #include "include/v8-internal.h" |
9 | #include "include/v8.h" |
10 | #include "src/globals.h" |
11 | #include "src/objects.h" |
12 | #include "src/objects/smi.h" |
13 | |
14 | namespace v8 { |
15 | namespace internal { |
16 | |
17 | class HeapObject; |
18 | class Isolate; |
19 | class StringStream; |
20 | |
21 | // A MaybeObject is either a SMI, a strong reference to a HeapObject, a weak |
22 | // reference to a HeapObject, or a cleared weak reference. It's used for |
23 | // implementing in-place weak references (see design doc: goo.gl/j6SdcK ) |
24 | class MaybeObject { |
25 | public: |
26 | MaybeObject() : ptr_(kNullAddress) {} |
27 | explicit MaybeObject(Address ptr) : ptr_(ptr) {} |
28 | |
29 | bool operator==(const MaybeObject& other) const { return ptr_ == other.ptr_; } |
30 | bool operator!=(const MaybeObject& other) const { return ptr_ != other.ptr_; } |
31 | |
32 | Address ptr() const { return ptr_; } |
33 | |
34 | // Enable incremental transition of client code. |
35 | MaybeObject* operator->() { return this; } |
36 | const MaybeObject* operator->() const { return this; } |
37 | |
38 | bool IsSmi() const { return HAS_SMI_TAG(ptr_); } |
39 | inline bool ToSmi(Smi* value); |
40 | inline Smi ToSmi() const; |
41 | |
42 | bool IsCleared() const { |
43 | return static_cast<uint32_t>(ptr_) == kClearedWeakHeapObjectLower32; |
44 | } |
45 | |
46 | inline bool IsStrongOrWeak() const; |
47 | inline bool IsStrong() const; |
48 | |
49 | // If this MaybeObject is a strong pointer to a HeapObject, returns true and |
50 | // sets *result. Otherwise returns false. |
51 | inline bool GetHeapObjectIfStrong(HeapObject* result) const; |
52 | |
53 | // DCHECKs that this MaybeObject is a strong pointer to a HeapObject and |
54 | // returns the HeapObject. |
55 | inline HeapObject GetHeapObjectAssumeStrong() const; |
56 | |
57 | inline bool IsWeak() const; |
58 | inline bool IsWeakOrCleared() const; |
59 | |
60 | // If this MaybeObject is a weak pointer to a HeapObject, returns true and |
61 | // sets *result. Otherwise returns false. |
62 | inline bool GetHeapObjectIfWeak(HeapObject* result) const; |
63 | |
64 | // DCHECKs that this MaybeObject is a weak pointer to a HeapObject and |
65 | // returns the HeapObject. |
66 | inline HeapObject GetHeapObjectAssumeWeak() const; |
67 | |
68 | // If this MaybeObject is a strong or weak pointer to a HeapObject, returns |
69 | // true and sets *result. Otherwise returns false. |
70 | inline bool GetHeapObject(HeapObject* result) const; |
71 | inline bool GetHeapObject(HeapObject* result, |
72 | HeapObjectReferenceType* reference_type) const; |
73 | |
74 | // DCHECKs that this MaybeObject is a strong or a weak pointer to a HeapObject |
75 | // and returns the HeapObject. |
76 | inline HeapObject GetHeapObject() const; |
77 | |
78 | // DCHECKs that this MaybeObject is a strong or a weak pointer to a HeapObject |
79 | // or a SMI and returns the HeapObject or SMI. |
80 | inline Object GetHeapObjectOrSmi() const; |
81 | |
82 | inline bool IsObject() const; |
83 | template <typename T> |
84 | T cast() const { |
85 | DCHECK(!HasWeakHeapObjectTag(ptr_)); |
86 | return T::cast(Object(ptr_)); |
87 | } |
88 | |
89 | static MaybeObject FromSmi(Smi smi) { |
90 | DCHECK(HAS_SMI_TAG(smi->ptr())); |
91 | return MaybeObject(smi->ptr()); |
92 | } |
93 | |
94 | static MaybeObject FromObject(Object object) { |
95 | DCHECK(!HasWeakHeapObjectTag(object.ptr())); |
96 | return MaybeObject(object.ptr()); |
97 | } |
98 | |
99 | static inline MaybeObject MakeWeak(MaybeObject object); |
100 | |
101 | #ifdef VERIFY_HEAP |
102 | static void VerifyMaybeObjectPointer(Isolate* isolate, MaybeObject p); |
103 | #endif |
104 | |
105 | // Prints this object without details. |
106 | void ShortPrint(FILE* out = stdout); |
107 | |
108 | // Prints this object without details to a message accumulator. |
109 | void ShortPrint(StringStream* accumulator); |
110 | |
111 | void ShortPrint(std::ostream& os); |
112 | |
113 | #ifdef OBJECT_PRINT |
114 | void Print(); |
115 | void Print(std::ostream& os); |
116 | #else |
117 | void Print() { ShortPrint(); } |
118 | void Print(std::ostream& os) { ShortPrint(os); } |
119 | #endif |
120 | |
121 | private: |
122 | Address ptr_; |
123 | }; |
124 | |
125 | // A HeapObjectReference is either a strong reference to a HeapObject, a weak |
126 | // reference to a HeapObject, or a cleared weak reference. |
127 | class HeapObjectReference : public MaybeObject { |
128 | public: |
129 | explicit HeapObjectReference(Address address) : MaybeObject(address) {} |
130 | explicit HeapObjectReference(Object object) : MaybeObject(object->ptr()) {} |
131 | |
132 | static HeapObjectReference Strong(Object object) { |
133 | DCHECK(!object->IsSmi()); |
134 | DCHECK(!HasWeakHeapObjectTag(object)); |
135 | return HeapObjectReference(object); |
136 | } |
137 | |
138 | static HeapObjectReference Weak(Object object) { |
139 | DCHECK(!object->IsSmi()); |
140 | DCHECK(!HasWeakHeapObjectTag(object)); |
141 | return HeapObjectReference(object->ptr() | kWeakHeapObjectMask); |
142 | } |
143 | |
144 | V8_INLINE static HeapObjectReference ClearedValue(Isolate* isolate); |
145 | |
146 | template <typename THeapObjectSlot> |
147 | V8_INLINE static void Update(THeapObjectSlot slot, HeapObject value); |
148 | }; |
149 | |
150 | } // namespace internal |
151 | } // namespace v8 |
152 | |
153 | #endif // V8_OBJECTS_MAYBE_OBJECT_H_ |
154 | |