blob: 577e83a9041e2157af393cf4179ee66b9c1ff36e [file] [log] [blame]
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001// Copyright 2011 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
5#ifndef V8_HANDLES_H_
6#define V8_HANDLES_H_
7
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/objects.h"
Steve Blocka7e24c12009-10-30 11:49:00 +00009
10namespace v8 {
11namespace internal {
12
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013// A Handle can be converted into a MaybeHandle. Converting a MaybeHandle
14// into a Handle requires checking that it does not point to NULL. This
15// ensures NULL checks before use.
16// Do not use MaybeHandle as argument type.
17
18template<typename T>
19class MaybeHandle {
20 public:
21 INLINE(MaybeHandle()) : location_(NULL) { }
22
23 // Constructor for handling automatic up casting from Handle.
24 // Ex. Handle<JSArray> can be passed when MaybeHandle<Object> is expected.
25 template <class S> MaybeHandle(Handle<S> handle) {
26#ifdef DEBUG
27 T* a = NULL;
28 S* b = NULL;
29 a = b; // Fake assignment to enforce type checks.
30 USE(a);
31#endif
32 this->location_ = reinterpret_cast<T**>(handle.location());
33 }
34
35 // Constructor for handling automatic up casting.
36 // Ex. MaybeHandle<JSArray> can be passed when Handle<Object> is expected.
37 template <class S> MaybeHandle(MaybeHandle<S> maybe_handle) {
38#ifdef DEBUG
39 T* a = NULL;
40 S* b = NULL;
41 a = b; // Fake assignment to enforce type checks.
42 USE(a);
43#endif
44 location_ = reinterpret_cast<T**>(maybe_handle.location_);
45 }
46
47 INLINE(void Assert() const) { DCHECK(location_ != NULL); }
48 INLINE(void Check() const) { CHECK(location_ != NULL); }
49
50 INLINE(Handle<T> ToHandleChecked()) const {
51 Check();
52 return Handle<T>(location_);
53 }
54
55 // Convert to a Handle with a type that can be upcasted to.
56 template <class S> INLINE(bool ToHandle(Handle<S>* out)) {
57 if (location_ == NULL) {
58 *out = Handle<T>::null();
59 return false;
60 } else {
61 *out = Handle<T>(location_);
62 return true;
63 }
64 }
65
66 bool is_null() const { return location_ == NULL; }
67
68 protected:
69 T** location_;
70
71 // MaybeHandles of different classes are allowed to access each
72 // other's location_.
73 template<class S> friend class MaybeHandle;
74};
75
Steve Blocka7e24c12009-10-30 11:49:00 +000076// ----------------------------------------------------------------------------
77// A Handle provides a reference to an object that survives relocation by
78// the garbage collector.
79// Handles are only valid within a HandleScope.
80// When a handle is created for an object a cell is allocated in the heap.
81
Ben Murdoche0cee9b2011-05-25 10:26:03 +010082template<typename T>
Steve Blocka7e24c12009-10-30 11:49:00 +000083class Handle {
84 public:
Steve Block6ded16b2010-05-10 14:33:55 +010085 INLINE(explicit Handle(T** location)) { location_ = location; }
Steve Blocka7e24c12009-10-30 11:49:00 +000086 INLINE(explicit Handle(T* obj));
Steve Block44f0eee2011-05-26 01:26:41 +010087 INLINE(Handle(T* obj, Isolate* isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000088
Ben Murdochb8a8cc12014-11-26 15:28:44 +000089 // TODO(yangguo): Values that contain empty handles should be declared as
90 // MaybeHandle to force validation before being used as handles.
91 INLINE(Handle()) : location_(NULL) { }
Steve Blocka7e24c12009-10-30 11:49:00 +000092
93 // Constructor for handling automatic up casting.
94 // Ex. Handle<JSFunction> can be passed when Handle<Object> is expected.
95 template <class S> Handle(Handle<S> handle) {
96#ifdef DEBUG
97 T* a = NULL;
98 S* b = NULL;
99 a = b; // Fake assignment to enforce type checks.
100 USE(a);
101#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000102 location_ = reinterpret_cast<T**>(handle.location_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000103 }
104
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000105 INLINE(T* operator->() const) { return operator*(); }
Steve Blocka7e24c12009-10-30 11:49:00 +0000106
107 // Check if this handle refers to the exact same object as the other handle.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000108 INLINE(bool is_identical_to(const Handle<T> other) const);
Steve Blocka7e24c12009-10-30 11:49:00 +0000109
110 // Provides the C++ dereference operator.
111 INLINE(T* operator*() const);
112
113 // Returns the address to where the raw pointer is stored.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000114 INLINE(T** location() const);
Steve Blocka7e24c12009-10-30 11:49:00 +0000115
116 template <class S> static Handle<T> cast(Handle<S> that) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000117 T::cast(*reinterpret_cast<T**>(that.location_));
118 return Handle<T>(reinterpret_cast<T**>(that.location_));
Steve Blocka7e24c12009-10-30 11:49:00 +0000119 }
120
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000121 // TODO(yangguo): Values that contain empty handles should be declared as
122 // MaybeHandle to force validation before being used as handles.
Steve Blocka7e24c12009-10-30 11:49:00 +0000123 static Handle<T> null() { return Handle<T>(); }
Steve Block44f0eee2011-05-26 01:26:41 +0100124 bool is_null() const { return location_ == NULL; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000125
126 // Closes the given scope, but lets this handle escape. See
127 // implementation in api.h.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000128 inline Handle<T> EscapeFrom(v8::EscapableHandleScope* scope);
129
130#ifdef DEBUG
131 enum DereferenceCheckMode { INCLUDE_DEFERRED_CHECK, NO_DEFERRED_CHECK };
132
133 bool IsDereferenceAllowed(DereferenceCheckMode mode) const;
134#endif // DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +0000135
136 private:
137 T** location_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000138
139 // Handles of different classes are allowed to access each other's location_.
140 template<class S> friend class Handle;
Steve Blocka7e24c12009-10-30 11:49:00 +0000141};
142
143
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000144// Convenience wrapper.
145template<class T>
146inline Handle<T> handle(T* t, Isolate* isolate) {
147 return Handle<T>(t, isolate);
148}
149
150
151// Convenience wrapper.
152template<class T>
153inline Handle<T> handle(T* t) {
154 return Handle<T>(t, t->GetIsolate());
155}
156
157
158// Key comparison function for Map handles.
159inline bool operator<(const Handle<Map>& lhs, const Handle<Map>& rhs) {
160 // This is safe because maps don't move.
161 return *lhs < *rhs;
162}
163
164
165class DeferredHandles;
166class HandleScopeImplementer;
167
168
Steve Blocka7e24c12009-10-30 11:49:00 +0000169// A stack-allocated class that governs a number of local handles.
170// After a handle scope has been created, all local handles will be
171// allocated within that handle scope until either the handle scope is
172// deleted or another handle scope is created. If there is already a
173// handle scope and a new one is created, all allocations will take
174// place in the new handle scope until it is deleted. After that,
175// new handles will again be allocated in the original handle scope.
176//
177// After the handle scope of a local handle has been deleted the
178// garbage collector will no longer track the object stored in the
179// handle and may deallocate it. The behavior of accessing a handle
180// for which the handle scope has been deleted is undefined.
181class HandleScope {
182 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100183 explicit inline HandleScope(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000184
Steve Block44f0eee2011-05-26 01:26:41 +0100185 inline ~HandleScope();
Steve Blocka7e24c12009-10-30 11:49:00 +0000186
187 // Counts the number of allocated handles.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000188 static int NumberOfHandles(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000189
190 // Creates a new handle with the given value.
191 template <typename T>
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192 static inline T** CreateHandle(Isolate* isolate, T* value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000193
Steve Blockd0582a62009-12-15 09:54:21 +0000194 // Deallocates any extensions used by the current scope.
Steve Block44f0eee2011-05-26 01:26:41 +0100195 static void DeleteExtensions(Isolate* isolate);
Steve Blockd0582a62009-12-15 09:54:21 +0000196
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000197 static Address current_next_address(Isolate* isolate);
198 static Address current_limit_address(Isolate* isolate);
199 static Address current_level_address(Isolate* isolate);
Steve Blockd0582a62009-12-15 09:54:21 +0000200
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100201 // Closes the HandleScope (invalidating all handles
202 // created in the scope of the HandleScope) and returns
203 // a Handle backed by the parent scope holding the
204 // value of the argument handle.
205 template <typename T>
Steve Block44f0eee2011-05-26 01:26:41 +0100206 Handle<T> CloseAndEscape(Handle<T> handle_value);
207
208 Isolate* isolate() { return isolate_; }
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100209
Steve Blocka7e24c12009-10-30 11:49:00 +0000210 private:
211 // Prevent heap allocation or illegal handle scopes.
212 HandleScope(const HandleScope&);
213 void operator=(const HandleScope&);
214 void* operator new(size_t size);
215 void operator delete(void* size_t);
216
Steve Block44f0eee2011-05-26 01:26:41 +0100217 Isolate* isolate_;
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100218 Object** prev_next_;
219 Object** prev_limit_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000220
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000221 // Close the handle scope resetting limits to a previous state.
222 static inline void CloseScope(Isolate* isolate,
223 Object** prev_next,
224 Object** prev_limit);
Steve Blocka7e24c12009-10-30 11:49:00 +0000225
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000226 // Extend the handle scope making room for more handles.
227 static internal::Object** Extend(Isolate* isolate);
228
229#ifdef ENABLE_HANDLE_ZAPPING
Steve Blocka7e24c12009-10-30 11:49:00 +0000230 // Zaps the handles in the half-open interval [start, end).
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000231 static void ZapRange(Object** start, Object** end);
232#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000233
234 friend class v8::HandleScope;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000235 friend class v8::internal::DeferredHandles;
236 friend class v8::internal::HandleScopeImplementer;
237 friend class v8::internal::Isolate;
Steve Blocka7e24c12009-10-30 11:49:00 +0000238};
239
240
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000241class DeferredHandles;
Steve Blocka7e24c12009-10-30 11:49:00 +0000242
243
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000244class DeferredHandleScope {
245 public:
246 explicit DeferredHandleScope(Isolate* isolate);
247 // The DeferredHandles object returned stores the Handles created
248 // since the creation of this DeferredHandleScope. The Handles are
249 // alive as long as the DeferredHandles object is alive.
250 DeferredHandles* Detach();
251 ~DeferredHandleScope();
Steve Blocka7e24c12009-10-30 11:49:00 +0000252
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000253 private:
254 Object** prev_limit_;
255 Object** prev_next_;
256 HandleScopeImplementer* impl_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000257
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000258#ifdef DEBUG
259 bool handles_detached_;
260 int prev_level_;
261#endif
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100262
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000263 friend class HandleScopeImplementer;
264};
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000265
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000266
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000267// Seal off the current HandleScope so that new handles can only be created
268// if a new HandleScope is entered.
269class SealHandleScope BASE_EMBEDDED {
Steve Blocka7e24c12009-10-30 11:49:00 +0000270 public:
271#ifndef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000272 explicit SealHandleScope(Isolate* isolate) {}
273 ~SealHandleScope() {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000274#else
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000275 explicit inline SealHandleScope(Isolate* isolate);
276 inline ~SealHandleScope();
Steve Blocka7e24c12009-10-30 11:49:00 +0000277 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000278 Isolate* isolate_;
279 Object** limit_;
John Reck59135872010-11-02 12:39:01 -0700280 int level_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000281#endif
282};
283
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000284struct HandleScopeData {
285 internal::Object** next;
286 internal::Object** limit;
287 int level;
288
289 void Initialize() {
290 next = limit = NULL;
291 level = 0;
292 }
293};
294
Steve Blocka7e24c12009-10-30 11:49:00 +0000295} } // namespace v8::internal
296
297#endif // V8_HANDLES_H_