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
3 // found in the LICENSE file.
4
5 #ifndef V8_HANDLES_H_
6 #define V8_HANDLES_H_
7
8 #include "src/objects.h"
9
10 namespace v8 {
11 namespace internal {
12
13 // 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
18 template<typename T>
19 class MaybeHandle {
20 public:
INLINE(MaybeHandle ())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.
MaybeHandle(Handle<S> handle)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.
MaybeHandle(MaybeHandle<S> maybe_handle)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
INLINE(void Assert ()const)47 INLINE(void Assert() const) { DCHECK(location_ != NULL); }
INLINE(void Check ()const)48 INLINE(void Check() const) { CHECK(location_ != NULL); }
49
INLINE(Handle<T> ToHandleChecked ())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.
INLINE(bool ToHandle (Handle<S> * out))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
is_null()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
76 // ----------------------------------------------------------------------------
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
82 template<typename T>
83 class Handle {
84 public:
INLINE(explicit Handle (T ** location))85 INLINE(explicit Handle(T** location)) { location_ = location; }
86 INLINE(explicit Handle(T* obj));
87 INLINE(Handle(T* obj, Isolate* isolate));
88
89 // TODO(yangguo): Values that contain empty handles should be declared as
90 // MaybeHandle to force validation before being used as handles.
INLINE(Handle ())91 INLINE(Handle()) : location_(NULL) { }
92
93 // Constructor for handling automatic up casting.
94 // Ex. Handle<JSFunction> can be passed when Handle<Object> is expected.
Handle(Handle<S> handle)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
102 location_ = reinterpret_cast<T**>(handle.location_);
103 }
104
105 INLINE(T* operator->() const) { return operator*(); }
106
107 // Check if this handle refers to the exact same object as the other handle.
108 INLINE(bool is_identical_to(const Handle<T> other) const);
109
110 // Provides the C++ dereference operator.
111 INLINE(T* operator*() const);
112
113 // Returns the address to where the raw pointer is stored.
114 INLINE(T** location() const);
115
cast(Handle<S> that)116 template <class S> static Handle<T> cast(Handle<S> that) {
117 T::cast(*reinterpret_cast<T**>(that.location_));
118 return Handle<T>(reinterpret_cast<T**>(that.location_));
119 }
120
121 // TODO(yangguo): Values that contain empty handles should be declared as
122 // MaybeHandle to force validation before being used as handles.
null()123 static Handle<T> null() { return Handle<T>(); }
is_null()124 bool is_null() const { return location_ == NULL; }
125
126 // Closes the given scope, but lets this handle escape. See
127 // implementation in api.h.
128 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
135
136 private:
137 T** location_;
138
139 // Handles of different classes are allowed to access each other's location_.
140 template<class S> friend class Handle;
141 };
142
143
144 // Convenience wrapper.
145 template<class T>
handle(T * t,Isolate * isolate)146 inline Handle<T> handle(T* t, Isolate* isolate) {
147 return Handle<T>(t, isolate);
148 }
149
150
151 // Convenience wrapper.
152 template<class T>
handle(T * t)153 inline Handle<T> handle(T* t) {
154 return Handle<T>(t, t->GetIsolate());
155 }
156
157
158 // Key comparison function for Map handles.
159 inline 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
165 class DeferredHandles;
166 class HandleScopeImplementer;
167
168
169 // 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.
181 class HandleScope {
182 public:
183 explicit inline HandleScope(Isolate* isolate);
184
185 inline ~HandleScope();
186
187 // Counts the number of allocated handles.
188 static int NumberOfHandles(Isolate* isolate);
189
190 // Creates a new handle with the given value.
191 template <typename T>
192 static inline T** CreateHandle(Isolate* isolate, T* value);
193
194 // Deallocates any extensions used by the current scope.
195 static void DeleteExtensions(Isolate* isolate);
196
197 static Address current_next_address(Isolate* isolate);
198 static Address current_limit_address(Isolate* isolate);
199 static Address current_level_address(Isolate* isolate);
200
201 // 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>
206 Handle<T> CloseAndEscape(Handle<T> handle_value);
207
isolate()208 Isolate* isolate() { return isolate_; }
209
210 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
217 Isolate* isolate_;
218 Object** prev_next_;
219 Object** prev_limit_;
220
221 // 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);
225
226 // Extend the handle scope making room for more handles.
227 static internal::Object** Extend(Isolate* isolate);
228
229 #ifdef ENABLE_HANDLE_ZAPPING
230 // Zaps the handles in the half-open interval [start, end).
231 static void ZapRange(Object** start, Object** end);
232 #endif
233
234 friend class v8::HandleScope;
235 friend class v8::internal::DeferredHandles;
236 friend class v8::internal::HandleScopeImplementer;
237 friend class v8::internal::Isolate;
238 };
239
240
241 class DeferredHandles;
242
243
244 class 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();
252
253 private:
254 Object** prev_limit_;
255 Object** prev_next_;
256 HandleScopeImplementer* impl_;
257
258 #ifdef DEBUG
259 bool handles_detached_;
260 int prev_level_;
261 #endif
262
263 friend class HandleScopeImplementer;
264 };
265
266
267 // Seal off the current HandleScope so that new handles can only be created
268 // if a new HandleScope is entered.
269 class SealHandleScope BASE_EMBEDDED {
270 public:
271 #ifndef DEBUG
SealHandleScope(Isolate * isolate)272 explicit SealHandleScope(Isolate* isolate) {}
~SealHandleScope()273 ~SealHandleScope() {}
274 #else
275 explicit inline SealHandleScope(Isolate* isolate);
276 inline ~SealHandleScope();
277 private:
278 Isolate* isolate_;
279 Object** limit_;
280 int level_;
281 #endif
282 };
283
284 struct HandleScopeData {
285 internal::Object** next;
286 internal::Object** limit;
287 int level;
288
InitializeHandleScopeData289 void Initialize() {
290 next = limit = NULL;
291 level = 0;
292 }
293 };
294
295 } } // namespace v8::internal
296
297 #endif // V8_HANDLES_H_
298