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