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: 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 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: 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. 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. 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 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. 123 static Handle<T> null() { return Handle<T>(); } 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> 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> 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 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 272 explicit SealHandleScope(Isolate* isolate) {} 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 289 void Initialize() { 290 next = limit = NULL; 291 level = 0; 292 } 293 }; 294 295 } } // namespace v8::internal 296 297 #endif // V8_HANDLES_H_ 298