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_INL_H_
6#define V8_OBJECTS_MAYBE_OBJECT_INL_H_
7
8#include "src/objects/maybe-object.h"
9
10#ifdef V8_COMPRESS_POINTERS
11#include "src/isolate.h"
12#endif
13#include "src/objects/heap-object-inl.h"
14#include "src/objects/slots-inl.h"
15#include "src/objects/smi-inl.h"
16
17namespace v8 {
18namespace internal {
19
20bool MaybeObject::ToSmi(Smi* value) {
21 if (HAS_SMI_TAG(ptr_)) {
22 *value = Smi::cast(Object(ptr_));
23 return true;
24 }
25 return false;
26}
27
28Smi MaybeObject::ToSmi() const {
29 DCHECK(HAS_SMI_TAG(ptr_));
30 return Smi::cast(Object(ptr_));
31}
32
33bool MaybeObject::IsStrongOrWeak() const {
34 if (IsSmi() || IsCleared()) {
35 return false;
36 }
37 return true;
38}
39
40bool MaybeObject::GetHeapObject(HeapObject* result) const {
41 if (IsSmi() || IsCleared()) {
42 return false;
43 }
44 *result = GetHeapObject();
45 return true;
46}
47
48bool MaybeObject::GetHeapObject(HeapObject* result,
49 HeapObjectReferenceType* reference_type) const {
50 if (IsSmi() || IsCleared()) {
51 return false;
52 }
53 *reference_type = HasWeakHeapObjectTag(ptr_)
54 ? HeapObjectReferenceType::WEAK
55 : HeapObjectReferenceType::STRONG;
56 *result = GetHeapObject();
57 return true;
58}
59
60bool MaybeObject::IsStrong() const {
61 return !HasWeakHeapObjectTag(ptr_) && !IsSmi();
62}
63
64bool MaybeObject::GetHeapObjectIfStrong(HeapObject* result) const {
65 if (!HasWeakHeapObjectTag(ptr_) && !IsSmi()) {
66 *result = HeapObject::cast(Object(ptr_));
67 return true;
68 }
69 return false;
70}
71
72HeapObject MaybeObject::GetHeapObjectAssumeStrong() const {
73 DCHECK(IsStrong());
74 return HeapObject::cast(Object(ptr_));
75}
76
77bool MaybeObject::IsWeak() const {
78 return HasWeakHeapObjectTag(ptr_) && !IsCleared();
79}
80
81bool MaybeObject::IsWeakOrCleared() const { return HasWeakHeapObjectTag(ptr_); }
82
83bool MaybeObject::GetHeapObjectIfWeak(HeapObject* result) const {
84 if (IsWeak()) {
85 *result = GetHeapObject();
86 return true;
87 }
88 return false;
89}
90
91HeapObject MaybeObject::GetHeapObjectAssumeWeak() const {
92 DCHECK(IsWeak());
93 return GetHeapObject();
94}
95
96HeapObject MaybeObject::GetHeapObject() const {
97 DCHECK(!IsSmi());
98 DCHECK(!IsCleared());
99 return HeapObject::cast(Object(ptr_ & ~kWeakHeapObjectMask));
100}
101
102Object MaybeObject::GetHeapObjectOrSmi() const {
103 if (IsSmi()) {
104 return Object(ptr_);
105 }
106 return GetHeapObject();
107}
108
109bool MaybeObject::IsObject() const { return IsSmi() || IsStrong(); }
110
111MaybeObject MaybeObject::MakeWeak(MaybeObject object) {
112 DCHECK(object.IsStrongOrWeak());
113 return MaybeObject(object.ptr_ | kWeakHeapObjectMask);
114}
115
116// static
117HeapObjectReference HeapObjectReference::ClearedValue(Isolate* isolate) {
118 // Construct cleared weak ref value.
119 Address raw_value = kClearedWeakHeapObjectLower32;
120#ifdef V8_COMPRESS_POINTERS
121 // This is necessary to make pointer decompression computation also
122 // suitable for cleared weak references.
123 Address isolate_root = isolate->isolate_root();
124 raw_value |= isolate_root;
125 DCHECK_EQ(raw_value & (~static_cast<Address>(kClearedWeakHeapObjectLower32)),
126 isolate_root);
127#endif
128 // The rest of the code will check only the lower 32-bits.
129 DCHECK_EQ(kClearedWeakHeapObjectLower32, static_cast<uint32_t>(raw_value));
130 return HeapObjectReference(raw_value);
131}
132
133template <typename THeapObjectSlot>
134void HeapObjectReference::Update(THeapObjectSlot slot, HeapObject value) {
135 static_assert(std::is_same<THeapObjectSlot, FullHeapObjectSlot>::value ||
136 std::is_same<THeapObjectSlot, HeapObjectSlot>::value,
137 "Only FullHeapObjectSlot and HeapObjectSlot are expected here");
138 Address old_value = (*slot).ptr();
139 DCHECK(!HAS_SMI_TAG(old_value));
140 Address new_value = value->ptr();
141 DCHECK(Internals::HasHeapObjectTag(new_value));
142
143#ifdef DEBUG
144 bool weak_before = HasWeakHeapObjectTag(old_value);
145#endif
146
147 slot.store(
148 HeapObjectReference(new_value | (old_value & kWeakHeapObjectMask)));
149
150#ifdef DEBUG
151 bool weak_after = HasWeakHeapObjectTag((*slot).ptr());
152 DCHECK_EQ(weak_before, weak_after);
153#endif
154}
155
156} // namespace internal
157} // namespace v8
158
159#endif // V8_OBJECTS_MAYBE_OBJECT_INL_H_
160