• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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