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