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