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