OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_HANDLES_H_ | 5 #ifndef V8_HANDLES_H_ |
6 #define V8_HANDLES_H_ | 6 #define V8_HANDLES_H_ |
7 | 7 |
8 #include "src/objects.h" | 8 #include "src/objects.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
11 namespace internal { | 11 namespace internal { |
12 | 12 |
13 // Forward declarations. | |
14 class DeferredHandles; | |
15 class HandleScopeImplementer; | |
16 | |
17 | |
18 // ---------------------------------------------------------------------------- | |
19 // Base class for Handle instantiations. Don't use directly. | |
20 class HandleBase { | |
21 public: | |
22 V8_INLINE explicit HandleBase(Object** location) : location_(location) {} | |
23 V8_INLINE explicit HandleBase(Object* object, Isolate* isolate); | |
24 | |
25 // Check if this handle refers to the exact same object as the other handle. | |
26 V8_INLINE bool is_identical_to(const HandleBase that) const { | |
27 // Dereferencing deferred handles to check object equality is safe. | |
28 SLOW_DCHECK((this->location_ == NULL || | |
29 this->IsDereferenceAllowed(NO_DEFERRED_CHECK)) && | |
30 (that.location_ == NULL || | |
31 that.IsDereferenceAllowed(NO_DEFERRED_CHECK))); | |
32 if (this->location_ == that.location_) return true; | |
33 if (this->location_ == NULL || that.location_ == NULL) return false; | |
34 return *this->location_ == *that.location_; | |
35 } | |
36 | |
37 V8_INLINE bool is_null() const { return location_ == nullptr; } | |
38 | |
39 protected: | |
40 // Provides the C++ dereference operator. | |
41 V8_INLINE Object* operator*() const { | |
42 SLOW_DCHECK(IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK)); | |
43 return *location_; | |
44 } | |
45 | |
46 // Returns the address to where the raw pointer is stored. | |
47 V8_INLINE Object** location() const { | |
48 SLOW_DCHECK(location_ == NULL || | |
49 IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK)); | |
50 return location_; | |
51 } | |
52 | |
53 enum DereferenceCheckMode { INCLUDE_DEFERRED_CHECK, NO_DEFERRED_CHECK }; | |
54 #ifdef DEBUG | |
55 bool IsDereferenceAllowed(DereferenceCheckMode mode) const; | |
56 #else | |
57 V8_INLINE | |
58 bool IsDereferenceAllowed(DereferenceCheckMode mode) const { return true; } | |
59 #endif // DEBUG | |
60 | |
61 Object** location_; | |
62 }; | |
63 | |
64 | |
65 // ---------------------------------------------------------------------------- | |
66 // A Handle provides a reference to an object that survives relocation by | |
67 // the garbage collector. | |
68 // Handles are only valid within a HandleScope. | |
69 // When a handle is created for an object a cell is allocated in the heap. | |
70 template <typename T> | |
71 class Handle final : public HandleBase { | |
72 public: | |
73 V8_INLINE explicit Handle(T** location = nullptr) | |
74 : HandleBase(reinterpret_cast<Object**>(location)) { | |
75 Object* a = nullptr; | |
76 T* b = nullptr; | |
77 a = b; // Fake assignment to enforce type checks. | |
78 USE(a); | |
79 } | |
80 V8_INLINE explicit Handle(T* object) : Handle(object, object->GetIsolate()) {} | |
81 V8_INLINE Handle(T* object, Isolate* isolate) : HandleBase(object, isolate) {} | |
82 | |
83 // Constructor for handling automatic up casting. | |
84 // Ex. Handle<JSFunction> can be passed when Handle<Object> is expected. | |
85 template <typename S> | |
86 V8_INLINE Handle(Handle<S> handle) | |
87 : HandleBase(handle) { | |
88 T* a = nullptr; | |
89 S* b = nullptr; | |
90 a = b; // Fake assignment to enforce type checks. | |
91 USE(a); | |
92 } | |
93 | |
94 V8_INLINE T* operator->() const { return operator*(); } | |
95 | |
96 // Provides the C++ dereference operator. | |
97 V8_INLINE T* operator*() const { | |
98 return reinterpret_cast<T*>(HandleBase::operator*()); | |
99 } | |
100 | |
101 // Returns the address to where the raw pointer is stored. | |
102 V8_INLINE T** location() const { | |
103 return reinterpret_cast<T**>(HandleBase::location()); | |
104 } | |
105 | |
106 template <typename S> | |
107 static const Handle<T> cast(Handle<S> that) { | |
108 T::cast(*reinterpret_cast<T**>(that.location_)); | |
109 return Handle<T>(reinterpret_cast<T**>(that.location_)); | |
110 } | |
111 | |
112 // TODO(yangguo): Values that contain empty handles should be declared as | |
113 // MaybeHandle to force validation before being used as handles. | |
114 static const Handle<T> null() { return Handle<T>(); } | |
115 | |
116 private: | |
117 // Handles of different classes are allowed to access each other's location_. | |
118 template <typename> | |
119 friend class Handle; | |
120 // MaybeHandle is allowed to access location_. | |
121 template <typename> | |
122 friend class MaybeHandle; | |
123 }; | |
124 | |
125 template <typename T> | |
126 V8_INLINE Handle<T> handle(T* object, Isolate* isolate) { | |
127 return Handle<T>(object, isolate); | |
128 } | |
129 | |
130 template <typename T> | |
131 V8_INLINE Handle<T> handle(T* object) { | |
132 return Handle<T>(object); | |
133 } | |
134 | |
135 | |
136 // ---------------------------------------------------------------------------- | |
137 // A Handle can be converted into a MaybeHandle. Converting a MaybeHandle | 13 // A Handle can be converted into a MaybeHandle. Converting a MaybeHandle |
138 // into a Handle requires checking that it does not point to NULL. This | 14 // into a Handle requires checking that it does not point to NULL. This |
139 // ensures NULL checks before use. | 15 // ensures NULL checks before use. |
140 // Do not use MaybeHandle as argument type. | 16 // Do not use MaybeHandle as argument type. |
141 template <typename T> | 17 |
142 class MaybeHandle final { | 18 template<typename T> |
| 19 class MaybeHandle { |
143 public: | 20 public: |
144 V8_INLINE MaybeHandle() {} | 21 INLINE(MaybeHandle()) : location_(NULL) { } |
145 V8_INLINE ~MaybeHandle() {} | |
146 | 22 |
147 // Constructor for handling automatic up casting from Handle. | 23 // Constructor for handling automatic up casting from Handle. |
148 // Ex. Handle<JSArray> can be passed when MaybeHandle<Object> is expected. | 24 // Ex. Handle<JSArray> can be passed when MaybeHandle<Object> is expected. |
149 template <typename S> | 25 template <class S> MaybeHandle(Handle<S> handle) { |
150 V8_INLINE MaybeHandle(Handle<S> handle) | 26 #ifdef DEBUG |
151 : location_(reinterpret_cast<T**>(handle.location_)) { | 27 T* a = NULL; |
152 T* a = nullptr; | 28 S* b = NULL; |
153 S* b = nullptr; | |
154 a = b; // Fake assignment to enforce type checks. | 29 a = b; // Fake assignment to enforce type checks. |
155 USE(a); | 30 USE(a); |
| 31 #endif |
| 32 this->location_ = reinterpret_cast<T**>(handle.location()); |
156 } | 33 } |
157 | 34 |
158 // Constructor for handling automatic up casting. | 35 // Constructor for handling automatic up casting. |
159 // Ex. MaybeHandle<JSArray> can be passed when Handle<Object> is expected. | 36 // Ex. MaybeHandle<JSArray> can be passed when Handle<Object> is expected. |
160 template <typename S> | 37 template <class S> MaybeHandle(MaybeHandle<S> maybe_handle) { |
161 V8_INLINE MaybeHandle(MaybeHandle<S> maybe_handle) | 38 #ifdef DEBUG |
162 : location_(reinterpret_cast<T**>(maybe_handle.location_)) { | 39 T* a = NULL; |
163 T* a = nullptr; | 40 S* b = NULL; |
164 S* b = nullptr; | |
165 a = b; // Fake assignment to enforce type checks. | 41 a = b; // Fake assignment to enforce type checks. |
166 USE(a); | 42 USE(a); |
| 43 #endif |
| 44 location_ = reinterpret_cast<T**>(maybe_handle.location_); |
167 } | 45 } |
168 | 46 |
169 V8_INLINE void Assert() const { DCHECK_NOT_NULL(location_); } | 47 INLINE(void Assert() const) { DCHECK(location_ != NULL); } |
170 V8_INLINE void Check() const { CHECK_NOT_NULL(location_); } | 48 INLINE(void Check() const) { CHECK(location_ != NULL); } |
171 | 49 |
172 V8_INLINE Handle<T> ToHandleChecked() const { | 50 INLINE(Handle<T> ToHandleChecked()) const { |
173 Check(); | 51 Check(); |
174 return Handle<T>(location_); | 52 return Handle<T>(location_); |
175 } | 53 } |
176 | 54 |
177 // Convert to a Handle with a type that can be upcasted to. | 55 // Convert to a Handle with a type that can be upcasted to. |
178 template <typename S> | 56 template <class S> |
179 V8_INLINE bool ToHandle(Handle<S>* out) const { | 57 V8_INLINE bool ToHandle(Handle<S>* out) const { |
180 if (location_ == nullptr) { | 58 if (location_ == NULL) { |
181 *out = Handle<T>::null(); | 59 *out = Handle<T>::null(); |
182 return false; | 60 return false; |
183 } else { | 61 } else { |
184 *out = Handle<T>(location_); | 62 *out = Handle<T>(location_); |
185 return true; | 63 return true; |
186 } | 64 } |
187 } | 65 } |
188 | 66 |
189 bool is_null() const { return location_ == nullptr; } | 67 bool is_null() const { return location_ == NULL; } |
190 | 68 |
191 template <typename S> | 69 template <typename S> |
192 V8_INLINE bool operator==(MaybeHandle<S> that) const { | 70 bool operator==(MaybeHandle<S> that) const { |
193 return this->location_ == that.location_; | 71 return this->location_ == that.location_; |
194 } | 72 } |
195 template <typename S> | 73 template <typename S> |
196 V8_INLINE bool operator!=(MaybeHandle<S> that) const { | 74 bool operator!=(MaybeHandle<S> that) const { |
197 return this->location_ != that.location_; | 75 return !(*this == that); |
198 } | 76 } |
199 | 77 |
| 78 |
200 protected: | 79 protected: |
201 T** location_ = nullptr; | 80 T** location_; |
202 | 81 |
203 // MaybeHandles of different classes are allowed to access each | 82 // MaybeHandles of different classes are allowed to access each |
204 // other's location_. | 83 // other's location_. |
205 template <typename> | 84 template<class S> friend class MaybeHandle; |
206 friend class MaybeHandle; | |
207 // Utility functions are allowed to access location_. | |
208 template <typename S> | 85 template <typename S> |
209 friend size_t hash_value(MaybeHandle<S>); | 86 friend size_t hash_value(MaybeHandle<S>); |
210 }; | 87 }; |
211 | 88 |
212 template <typename T> | 89 template <typename S> |
213 V8_INLINE size_t hash_value(MaybeHandle<T> maybe_handle) { | 90 inline size_t hash_value(MaybeHandle<S> maybe_handle) { |
214 uintptr_t v = bit_cast<uintptr_t>(maybe_handle.location_); | 91 return bit_cast<size_t>(maybe_handle.location_); |
215 DCHECK_EQ(0u, v & ((1u << kPointerSizeLog2) - 1)); | |
216 return v >> kPointerSizeLog2; | |
217 } | 92 } |
218 | 93 |
219 | 94 |
| 95 // ---------------------------------------------------------------------------- |
| 96 // A Handle provides a reference to an object that survives relocation by |
| 97 // the garbage collector. |
| 98 // Handles are only valid within a HandleScope. |
| 99 // When a handle is created for an object a cell is allocated in the heap. |
| 100 |
| 101 template<typename T> |
| 102 class Handle { |
| 103 public: |
| 104 INLINE(explicit Handle(T** location)) { location_ = location; } |
| 105 INLINE(explicit Handle(T* obj)); |
| 106 INLINE(Handle(T* obj, Isolate* isolate)); |
| 107 |
| 108 // TODO(yangguo): Values that contain empty handles should be declared as |
| 109 // MaybeHandle to force validation before being used as handles. |
| 110 INLINE(Handle()) : location_(NULL) { } |
| 111 |
| 112 // Constructor for handling automatic up casting. |
| 113 // Ex. Handle<JSFunction> can be passed when Handle<Object> is expected. |
| 114 template <class S> Handle(Handle<S> handle) { |
| 115 #ifdef DEBUG |
| 116 T* a = NULL; |
| 117 S* b = NULL; |
| 118 a = b; // Fake assignment to enforce type checks. |
| 119 USE(a); |
| 120 #endif |
| 121 location_ = reinterpret_cast<T**>(handle.location_); |
| 122 } |
| 123 |
| 124 INLINE(T* operator->() const) { return operator*(); } |
| 125 |
| 126 // Check if this handle refers to the exact same object as the other handle. |
| 127 INLINE(bool is_identical_to(const Handle<T> other) const); |
| 128 |
| 129 // Provides the C++ dereference operator. |
| 130 INLINE(T* operator*() const); |
| 131 |
| 132 // Returns the address to where the raw pointer is stored. |
| 133 INLINE(T** location() const); |
| 134 |
| 135 template <class S> static Handle<T> cast(Handle<S> that) { |
| 136 T::cast(*reinterpret_cast<T**>(that.location_)); |
| 137 return Handle<T>(reinterpret_cast<T**>(that.location_)); |
| 138 } |
| 139 |
| 140 // TODO(yangguo): Values that contain empty handles should be declared as |
| 141 // MaybeHandle to force validation before being used as handles. |
| 142 static Handle<T> null() { return Handle<T>(); } |
| 143 bool is_null() const { return location_ == NULL; } |
| 144 |
| 145 // Closes the given scope, but lets this handle escape. See |
| 146 // implementation in api.h. |
| 147 inline Handle<T> EscapeFrom(v8::EscapableHandleScope* scope); |
| 148 |
| 149 #ifdef DEBUG |
| 150 enum DereferenceCheckMode { INCLUDE_DEFERRED_CHECK, NO_DEFERRED_CHECK }; |
| 151 |
| 152 bool IsDereferenceAllowed(DereferenceCheckMode mode) const; |
| 153 #endif // DEBUG |
| 154 |
| 155 private: |
| 156 T** location_; |
| 157 |
| 158 // Handles of different classes are allowed to access each other's location_. |
| 159 template<class S> friend class Handle; |
| 160 }; |
| 161 |
| 162 |
| 163 // Convenience wrapper. |
| 164 template<class T> |
| 165 inline Handle<T> handle(T* t, Isolate* isolate) { |
| 166 return Handle<T>(t, isolate); |
| 167 } |
| 168 |
| 169 |
| 170 // Convenience wrapper. |
| 171 template<class T> |
| 172 inline Handle<T> handle(T* t) { |
| 173 return Handle<T>(t, t->GetIsolate()); |
| 174 } |
| 175 |
| 176 |
| 177 class DeferredHandles; |
| 178 class HandleScopeImplementer; |
| 179 |
| 180 |
220 // A stack-allocated class that governs a number of local handles. | 181 // A stack-allocated class that governs a number of local handles. |
221 // After a handle scope has been created, all local handles will be | 182 // After a handle scope has been created, all local handles will be |
222 // allocated within that handle scope until either the handle scope is | 183 // allocated within that handle scope until either the handle scope is |
223 // deleted or another handle scope is created. If there is already a | 184 // deleted or another handle scope is created. If there is already a |
224 // handle scope and a new one is created, all allocations will take | 185 // handle scope and a new one is created, all allocations will take |
225 // place in the new handle scope until it is deleted. After that, | 186 // place in the new handle scope until it is deleted. After that, |
226 // new handles will again be allocated in the original handle scope. | 187 // new handles will again be allocated in the original handle scope. |
227 // | 188 // |
228 // After the handle scope of a local handle has been deleted the | 189 // After the handle scope of a local handle has been deleted the |
229 // garbage collector will no longer track the object stored in the | 190 // garbage collector will no longer track the object stored in the |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 Isolate* isolate_; | 234 Isolate* isolate_; |
274 Object** prev_next_; | 235 Object** prev_next_; |
275 Object** prev_limit_; | 236 Object** prev_limit_; |
276 | 237 |
277 // Close the handle scope resetting limits to a previous state. | 238 // Close the handle scope resetting limits to a previous state. |
278 static inline void CloseScope(Isolate* isolate, | 239 static inline void CloseScope(Isolate* isolate, |
279 Object** prev_next, | 240 Object** prev_next, |
280 Object** prev_limit); | 241 Object** prev_limit); |
281 | 242 |
282 // Extend the handle scope making room for more handles. | 243 // Extend the handle scope making room for more handles. |
283 static Object** Extend(Isolate* isolate); | 244 static internal::Object** Extend(Isolate* isolate); |
284 | 245 |
285 #ifdef ENABLE_HANDLE_ZAPPING | 246 #ifdef ENABLE_HANDLE_ZAPPING |
286 // Zaps the handles in the half-open interval [start, end). | 247 // Zaps the handles in the half-open interval [start, end). |
287 static void ZapRange(Object** start, Object** end); | 248 static void ZapRange(Object** start, Object** end); |
288 #endif | 249 #endif |
289 | 250 |
290 friend class v8::HandleScope; | 251 friend class v8::HandleScope; |
291 friend class DeferredHandles; | 252 friend class v8::internal::DeferredHandles; |
292 friend class HandleScopeImplementer; | 253 friend class v8::internal::HandleScopeImplementer; |
293 friend class Isolate; | 254 friend class v8::internal::Isolate; |
294 }; | 255 }; |
295 | 256 |
296 | 257 |
297 class DeferredHandleScope final { | 258 class DeferredHandles; |
| 259 |
| 260 |
| 261 class DeferredHandleScope { |
298 public: | 262 public: |
299 explicit DeferredHandleScope(Isolate* isolate); | 263 explicit DeferredHandleScope(Isolate* isolate); |
300 // The DeferredHandles object returned stores the Handles created | 264 // The DeferredHandles object returned stores the Handles created |
301 // since the creation of this DeferredHandleScope. The Handles are | 265 // since the creation of this DeferredHandleScope. The Handles are |
302 // alive as long as the DeferredHandles object is alive. | 266 // alive as long as the DeferredHandles object is alive. |
303 DeferredHandles* Detach(); | 267 DeferredHandles* Detach(); |
304 ~DeferredHandleScope(); | 268 ~DeferredHandleScope(); |
305 | 269 |
306 private: | 270 private: |
307 Object** prev_limit_; | 271 Object** prev_limit_; |
308 Object** prev_next_; | 272 Object** prev_next_; |
309 HandleScopeImplementer* impl_; | 273 HandleScopeImplementer* impl_; |
310 | 274 |
311 #ifdef DEBUG | 275 #ifdef DEBUG |
312 bool handles_detached_; | 276 bool handles_detached_; |
313 int prev_level_; | 277 int prev_level_; |
314 #endif | 278 #endif |
315 | 279 |
316 friend class HandleScopeImplementer; | 280 friend class HandleScopeImplementer; |
317 }; | 281 }; |
318 | 282 |
319 | 283 |
320 // Seal off the current HandleScope so that new handles can only be created | 284 // Seal off the current HandleScope so that new handles can only be created |
321 // if a new HandleScope is entered. | 285 // if a new HandleScope is entered. |
322 class SealHandleScope final { | 286 class SealHandleScope BASE_EMBEDDED { |
323 public: | 287 public: |
324 #ifndef DEBUG | 288 #ifndef DEBUG |
325 explicit SealHandleScope(Isolate* isolate) {} | 289 explicit SealHandleScope(Isolate* isolate) {} |
326 ~SealHandleScope() {} | 290 ~SealHandleScope() {} |
327 #else | 291 #else |
328 explicit inline SealHandleScope(Isolate* isolate); | 292 explicit inline SealHandleScope(Isolate* isolate); |
329 inline ~SealHandleScope(); | 293 inline ~SealHandleScope(); |
330 private: | 294 private: |
331 Isolate* isolate_; | 295 Isolate* isolate_; |
332 Object** limit_; | 296 Object** limit_; |
333 int level_; | 297 int level_; |
334 #endif | 298 #endif |
335 }; | 299 }; |
336 | 300 |
337 | 301 struct HandleScopeData { |
338 struct HandleScopeData final { | 302 internal::Object** next; |
339 Object** next; | 303 internal::Object** limit; |
340 Object** limit; | |
341 int level; | 304 int level; |
342 | 305 |
343 void Initialize() { | 306 void Initialize() { |
344 next = limit = NULL; | 307 next = limit = NULL; |
345 level = 0; | 308 level = 0; |
346 } | 309 } |
347 }; | 310 }; |
348 | 311 |
349 } // namespace internal | 312 } } // namespace v8::internal |
350 } // namespace v8 | |
351 | 313 |
352 #endif // V8_HANDLES_H_ | 314 #endif // V8_HANDLES_H_ |
OLD | NEW |