1 // Copyright 2006-2008 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_HANDLES_HANDLES_INL_H_
6 #define V8_HANDLES_HANDLES_INL_H_
7
8 #include "src/execution/isolate.h"
9 #include "src/execution/local-isolate.h"
10 #include "src/handles/handles.h"
11 #include "src/handles/local-handles-inl.h"
12 #include "src/objects/objects.h"
13 #include "src/sanitizer/msan.h"
14
15 namespace v8 {
16 namespace internal {
17
18 class LocalHeap;
19
HandleBase(Address object,Isolate * isolate)20 HandleBase::HandleBase(Address object, Isolate* isolate)
21 : location_(HandleScope::GetHandle(isolate, object)) {}
22
HandleBase(Address object,LocalIsolate * isolate)23 HandleBase::HandleBase(Address object, LocalIsolate* isolate)
24 : location_(LocalHandleScope::GetHandle(isolate->heap(), object)) {}
25
HandleBase(Address object,LocalHeap * local_heap)26 HandleBase::HandleBase(Address object, LocalHeap* local_heap)
27 : location_(LocalHandleScope::GetHandle(local_heap, object)) {}
28
is_identical_to(const HandleBase that)29 bool HandleBase::is_identical_to(const HandleBase that) const {
30 SLOW_DCHECK((this->location_ == nullptr || this->IsDereferenceAllowed()) &&
31 (that.location_ == nullptr || that.IsDereferenceAllowed()));
32 if (this->location_ == that.location_) return true;
33 if (this->location_ == nullptr || that.location_ == nullptr) return false;
34 return Object(*this->location_) == Object(*that.location_);
35 }
36
37 // Allocate a new handle for the object, do not canonicalize.
38 template <typename T>
New(T object,Isolate * isolate)39 Handle<T> Handle<T>::New(T object, Isolate* isolate) {
40 return Handle(HandleScope::CreateHandle(isolate, object.ptr()));
41 }
42
43 template <typename T>
44 template <typename S>
cast(Handle<S> that)45 const Handle<T> Handle<T>::cast(Handle<S> that) {
46 T::cast(*FullObjectSlot(that.location()));
47 return Handle<T>(that.location_);
48 }
49
50 template <typename T>
Handle(T object,Isolate * isolate)51 Handle<T>::Handle(T object, Isolate* isolate)
52 : HandleBase(object.ptr(), isolate) {}
53
54 template <typename T>
Handle(T object,LocalIsolate * isolate)55 Handle<T>::Handle(T object, LocalIsolate* isolate)
56 : HandleBase(object.ptr(), isolate) {}
57
58 template <typename T>
Handle(T object,LocalHeap * local_heap)59 Handle<T>::Handle(T object, LocalHeap* local_heap)
60 : HandleBase(object.ptr(), local_heap) {}
61
62 template <typename T>
handle(T object,Isolate * isolate)63 V8_INLINE Handle<T> handle(T object, Isolate* isolate) {
64 return Handle<T>(object, isolate);
65 }
66
67 template <typename T>
handle(T object,LocalIsolate * isolate)68 V8_INLINE Handle<T> handle(T object, LocalIsolate* isolate) {
69 return Handle<T>(object, isolate);
70 }
71
72 template <typename T>
handle(T object,LocalHeap * local_heap)73 V8_INLINE Handle<T> handle(T object, LocalHeap* local_heap) {
74 return Handle<T>(object, local_heap);
75 }
76
77 template <typename T>
78 inline std::ostream& operator<<(std::ostream& os, Handle<T> handle) {
79 return os << Brief(*handle);
80 }
81
HandleScope(Isolate * isolate)82 HandleScope::HandleScope(Isolate* isolate) {
83 HandleScopeData* data = isolate->handle_scope_data();
84 isolate_ = isolate;
85 prev_next_ = data->next;
86 prev_limit_ = data->limit;
87 data->level++;
88 }
89
HandleScope(HandleScope && other)90 HandleScope::HandleScope(HandleScope&& other) V8_NOEXCEPT
91 : isolate_(other.isolate_),
92 prev_next_(other.prev_next_),
93 prev_limit_(other.prev_limit_) {
94 other.isolate_ = nullptr;
95 }
96
~HandleScope()97 HandleScope::~HandleScope() {
98 if (isolate_ == nullptr) return;
99 CloseScope(isolate_, prev_next_, prev_limit_);
100 }
101
102 HandleScope& HandleScope::operator=(HandleScope&& other) V8_NOEXCEPT {
103 if (isolate_ == nullptr) {
104 isolate_ = other.isolate_;
105 } else {
106 DCHECK_EQ(isolate_, other.isolate_);
107 CloseScope(isolate_, prev_next_, prev_limit_);
108 }
109 prev_next_ = other.prev_next_;
110 prev_limit_ = other.prev_limit_;
111 other.isolate_ = nullptr;
112 return *this;
113 }
114
CloseScope(Isolate * isolate,Address * prev_next,Address * prev_limit)115 void HandleScope::CloseScope(Isolate* isolate, Address* prev_next,
116 Address* prev_limit) {
117 #ifdef DEBUG
118 int before = FLAG_check_handle_count ? NumberOfHandles(isolate) : 0;
119 #endif
120 DCHECK_NOT_NULL(isolate);
121 HandleScopeData* current = isolate->handle_scope_data();
122
123 std::swap(current->next, prev_next);
124 current->level--;
125 Address* limit = prev_next;
126 if (current->limit != prev_limit) {
127 current->limit = prev_limit;
128 limit = prev_limit;
129 DeleteExtensions(isolate);
130 }
131 #ifdef ENABLE_HANDLE_ZAPPING
132 ZapRange(current->next, limit);
133 #endif
134 MSAN_ALLOCATED_UNINITIALIZED_MEMORY(
135 current->next,
136 static_cast<size_t>(reinterpret_cast<Address>(limit) -
137 reinterpret_cast<Address>(current->next)));
138 #ifdef DEBUG
139 int after = FLAG_check_handle_count ? NumberOfHandles(isolate) : 0;
140 DCHECK_LT(after - before, kCheckHandleThreshold);
141 DCHECK_LT(before, kCheckHandleThreshold);
142 #endif
143 }
144
145 template <typename T>
CloseAndEscape(Handle<T> handle_value)146 Handle<T> HandleScope::CloseAndEscape(Handle<T> handle_value) {
147 HandleScopeData* current = isolate_->handle_scope_data();
148 T value = *handle_value;
149 // Throw away all handles in the current scope.
150 CloseScope(isolate_, prev_next_, prev_limit_);
151 // Allocate one handle in the parent scope.
152 DCHECK(current->level > current->sealed_level);
153 Handle<T> result(value, isolate_);
154 // Reinitialize the current scope (so that it's ready
155 // to be used or closed again).
156 prev_next_ = current->next;
157 prev_limit_ = current->limit;
158 current->level++;
159 return result;
160 }
161
CreateHandle(Isolate * isolate,Address value)162 Address* HandleScope::CreateHandle(Isolate* isolate, Address value) {
163 DCHECK(AllowHandleAllocation::IsAllowed());
164 HandleScopeData* data = isolate->handle_scope_data();
165 Address* result = data->next;
166 if (result == data->limit) {
167 result = Extend(isolate);
168 }
169 // Update the current next field, set the value in the created handle,
170 // and return the result.
171 DCHECK_LT(reinterpret_cast<Address>(result),
172 reinterpret_cast<Address>(data->limit));
173 data->next = reinterpret_cast<Address*>(reinterpret_cast<Address>(result) +
174 sizeof(Address));
175 *result = value;
176 return result;
177 }
178
GetHandle(Isolate * isolate,Address value)179 Address* HandleScope::GetHandle(Isolate* isolate, Address value) {
180 DCHECK(AllowHandleAllocation::IsAllowed());
181 HandleScopeData* data = isolate->handle_scope_data();
182 CanonicalHandleScope* canonical = data->canonical_scope;
183 return canonical ? canonical->Lookup(value) : CreateHandle(isolate, value);
184 }
185
186 #ifdef DEBUG
SealHandleScope(Isolate * isolate)187 inline SealHandleScope::SealHandleScope(Isolate* isolate) : isolate_(isolate) {
188 // Make sure the current thread is allowed to create handles to begin with.
189 DCHECK(AllowHandleAllocation::IsAllowed());
190 HandleScopeData* current = isolate_->handle_scope_data();
191 // Shrink the current handle scope to make it impossible to do
192 // handle allocations without an explicit handle scope.
193 prev_limit_ = current->limit;
194 current->limit = current->next;
195 prev_sealed_level_ = current->sealed_level;
196 current->sealed_level = current->level;
197 }
198
~SealHandleScope()199 inline SealHandleScope::~SealHandleScope() {
200 // Restore state in current handle scope to re-enable handle
201 // allocations.
202 HandleScopeData* current = isolate_->handle_scope_data();
203 DCHECK_EQ(current->next, current->limit);
204 current->limit = prev_limit_;
205 DCHECK_EQ(current->level, current->sealed_level);
206 current->sealed_level = prev_sealed_level_;
207 }
208
209 #endif
210
211 } // namespace internal
212 } // namespace v8
213
214 #endif // V8_HANDLES_HANDLES_INL_H_
215