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