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
14namespace v8 {
15namespace internal {
16
17class HeapObject;
18class Isolate;
19class 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 )
24class 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.
127class 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