Index: src/handles.h |
diff --git a/src/handles.h b/src/handles.h |
index 162b6d282f2cdae48f3f3141a17f5f6e5a124e57..841a83ba6044f81a7bc418792fcf3465b0eab38b 100644 |
--- a/src/handles.h |
+++ b/src/handles.h |
@@ -10,172 +10,211 @@ |
namespace v8 { |
namespace internal { |
-// A Handle can be converted into a MaybeHandle. Converting a MaybeHandle |
-// into a Handle requires checking that it does not point to NULL. This |
-// ensures NULL checks before use. |
-// Do not use MaybeHandle as argument type. |
+// Forward declarations. |
+class DeferredHandles; |
+class HandleScopeImplementer; |
-template<typename T> |
-class MaybeHandle { |
- public: |
- INLINE(MaybeHandle()) : location_(NULL) { } |
- // Constructor for handling automatic up casting from Handle. |
- // Ex. Handle<JSArray> can be passed when MaybeHandle<Object> is expected. |
- template <class S> MaybeHandle(Handle<S> handle) { |
-#ifdef DEBUG |
- T* a = NULL; |
- S* b = NULL; |
- a = b; // Fake assignment to enforce type checks. |
- USE(a); |
-#endif |
- this->location_ = reinterpret_cast<T**>(handle.location()); |
- } |
+// ---------------------------------------------------------------------------- |
+// Base class for Handle instantiations. Don't use directly. |
+class HandleBase { |
+ public: |
+ V8_INLINE explicit HandleBase(Object** location) : location_(location) {} |
+ V8_INLINE explicit HandleBase(Object* object, Isolate* isolate); |
- // Constructor for handling automatic up casting. |
- // Ex. MaybeHandle<JSArray> can be passed when Handle<Object> is expected. |
- template <class S> MaybeHandle(MaybeHandle<S> maybe_handle) { |
-#ifdef DEBUG |
- T* a = NULL; |
- S* b = NULL; |
- a = b; // Fake assignment to enforce type checks. |
- USE(a); |
-#endif |
- location_ = reinterpret_cast<T**>(maybe_handle.location_); |
+ // Check if this handle refers to the exact same object as the other handle. |
+ V8_INLINE bool is_identical_to(const HandleBase that) const { |
+ // Dereferencing deferred handles to check object equality is safe. |
+ SLOW_DCHECK((this->location_ == NULL || |
+ this->IsDereferenceAllowed(NO_DEFERRED_CHECK)) && |
+ (that.location_ == NULL || |
+ that.IsDereferenceAllowed(NO_DEFERRED_CHECK))); |
+ if (this->location_ == that.location_) return true; |
+ if (this->location_ == NULL || that.location_ == NULL) return false; |
+ return *this->location_ == *that.location_; |
} |
- INLINE(void Assert() const) { DCHECK(location_ != NULL); } |
- INLINE(void Check() const) { CHECK(location_ != NULL); } |
- |
- INLINE(Handle<T> ToHandleChecked()) const { |
- Check(); |
- return Handle<T>(location_); |
- } |
+ V8_INLINE bool is_null() const { return location_ == nullptr; } |
- // Convert to a Handle with a type that can be upcasted to. |
- template <class S> |
- V8_INLINE bool ToHandle(Handle<S>* out) const { |
- if (location_ == NULL) { |
- *out = Handle<T>::null(); |
- return false; |
- } else { |
- *out = Handle<T>(location_); |
- return true; |
- } |
+ protected: |
+ // Provides the C++ dereference operator. |
+ V8_INLINE Object* operator*() const { |
+ SLOW_DCHECK(IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK)); |
+ return *location_; |
} |
- bool is_null() const { return location_ == NULL; } |
- |
- template <typename S> |
- bool operator==(MaybeHandle<S> that) const { |
- return this->location_ == that.location_; |
- } |
- template <typename S> |
- bool operator!=(MaybeHandle<S> that) const { |
- return !(*this == that); |
+ // Returns the address to where the raw pointer is stored. |
+ V8_INLINE Object** location() const { |
+ SLOW_DCHECK(location_ == NULL || |
+ IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK)); |
+ return location_; |
} |
+ enum DereferenceCheckMode { INCLUDE_DEFERRED_CHECK, NO_DEFERRED_CHECK }; |
+#ifdef DEBUG |
+ bool IsDereferenceAllowed(DereferenceCheckMode mode) const; |
+#else |
+ V8_INLINE |
+ bool IsDereferenceAllowed(DereferenceCheckMode mode) const { return true; } |
+#endif // DEBUG |
- protected: |
- T** location_; |
- |
- // MaybeHandles of different classes are allowed to access each |
- // other's location_. |
- template<class S> friend class MaybeHandle; |
- template <typename S> |
- friend size_t hash_value(MaybeHandle<S>); |
+ Object** location_; |
}; |
-template <typename S> |
-inline size_t hash_value(MaybeHandle<S> maybe_handle) { |
- return bit_cast<size_t>(maybe_handle.location_); |
-} |
- |
// ---------------------------------------------------------------------------- |
// A Handle provides a reference to an object that survives relocation by |
// the garbage collector. |
// Handles are only valid within a HandleScope. |
// When a handle is created for an object a cell is allocated in the heap. |
- |
-template<typename T> |
-class Handle { |
+template <typename T> |
+class Handle final : public HandleBase { |
public: |
- INLINE(explicit Handle(T** location)) { location_ = location; } |
- INLINE(explicit Handle(T* obj)); |
- INLINE(Handle(T* obj, Isolate* isolate)); |
- |
- // TODO(yangguo): Values that contain empty handles should be declared as |
- // MaybeHandle to force validation before being used as handles. |
- INLINE(Handle()) : location_(NULL) { } |
+ V8_INLINE explicit Handle(T** location = nullptr) |
+ : HandleBase(reinterpret_cast<Object**>(location)) { |
+ Object* a = nullptr; |
+ T* b = nullptr; |
+ a = b; // Fake assignment to enforce type checks. |
+ USE(a); |
+ } |
+ V8_INLINE explicit Handle(T* object) : Handle(object, object->GetIsolate()) {} |
+ V8_INLINE Handle(T* object, Isolate* isolate) : HandleBase(object, isolate) {} |
// Constructor for handling automatic up casting. |
// Ex. Handle<JSFunction> can be passed when Handle<Object> is expected. |
- template <class S> Handle(Handle<S> handle) { |
-#ifdef DEBUG |
- T* a = NULL; |
- S* b = NULL; |
+ template <typename S> |
+ V8_INLINE Handle(Handle<S> handle) |
+ : HandleBase(handle) { |
+ T* a = nullptr; |
+ S* b = nullptr; |
a = b; // Fake assignment to enforce type checks. |
USE(a); |
-#endif |
- location_ = reinterpret_cast<T**>(handle.location_); |
} |
- INLINE(T* operator->() const) { return operator*(); } |
- |
- // Check if this handle refers to the exact same object as the other handle. |
- INLINE(bool is_identical_to(const Handle<T> other) const); |
+ V8_INLINE T* operator->() const { return operator*(); } |
// Provides the C++ dereference operator. |
- INLINE(T* operator*() const); |
+ V8_INLINE T* operator*() const { |
+ return reinterpret_cast<T*>(HandleBase::operator*()); |
+ } |
// Returns the address to where the raw pointer is stored. |
- INLINE(T** location() const); |
+ V8_INLINE T** location() const { |
+ return reinterpret_cast<T**>(HandleBase::location()); |
+ } |
- template <class S> static Handle<T> cast(Handle<S> that) { |
+ template <typename S> |
+ static const Handle<T> cast(Handle<S> that) { |
T::cast(*reinterpret_cast<T**>(that.location_)); |
return Handle<T>(reinterpret_cast<T**>(that.location_)); |
} |
// TODO(yangguo): Values that contain empty handles should be declared as |
// MaybeHandle to force validation before being used as handles. |
- static Handle<T> null() { return Handle<T>(); } |
- bool is_null() const { return location_ == NULL; } |
- |
- // Closes the given scope, but lets this handle escape. See |
- // implementation in api.h. |
- inline Handle<T> EscapeFrom(v8::EscapableHandleScope* scope); |
- |
-#ifdef DEBUG |
- enum DereferenceCheckMode { INCLUDE_DEFERRED_CHECK, NO_DEFERRED_CHECK }; |
- |
- bool IsDereferenceAllowed(DereferenceCheckMode mode) const; |
-#endif // DEBUG |
+ static const Handle<T> null() { return Handle<T>(); } |
private: |
- T** location_; |
- |
// Handles of different classes are allowed to access each other's location_. |
- template<class S> friend class Handle; |
+ template <typename> |
+ friend class Handle; |
+ // MaybeHandle is allowed to access location_. |
+ template <typename> |
+ friend class MaybeHandle; |
}; |
+template <typename T> |
+V8_INLINE Handle<T> handle(T* object, Isolate* isolate) { |
+ return Handle<T>(object, isolate); |
+} |
-// Convenience wrapper. |
-template<class T> |
-inline Handle<T> handle(T* t, Isolate* isolate) { |
- return Handle<T>(t, isolate); |
+template <typename T> |
+V8_INLINE Handle<T> handle(T* object) { |
+ return Handle<T>(object); |
} |
-// Convenience wrapper. |
-template<class T> |
-inline Handle<T> handle(T* t) { |
- return Handle<T>(t, t->GetIsolate()); |
-} |
+// ---------------------------------------------------------------------------- |
+// A Handle can be converted into a MaybeHandle. Converting a MaybeHandle |
+// into a Handle requires checking that it does not point to NULL. This |
+// ensures NULL checks before use. |
+// Do not use MaybeHandle as argument type. |
+template <typename T> |
+class MaybeHandle final { |
+ public: |
+ V8_INLINE MaybeHandle() {} |
+ V8_INLINE ~MaybeHandle() {} |
+ // Constructor for handling automatic up casting from Handle. |
+ // Ex. Handle<JSArray> can be passed when MaybeHandle<Object> is expected. |
+ template <typename S> |
+ V8_INLINE MaybeHandle(Handle<S> handle) |
+ : location_(reinterpret_cast<T**>(handle.location_)) { |
+ T* a = nullptr; |
+ S* b = nullptr; |
+ a = b; // Fake assignment to enforce type checks. |
+ USE(a); |
+ } |
-class DeferredHandles; |
-class HandleScopeImplementer; |
+ // Constructor for handling automatic up casting. |
+ // Ex. MaybeHandle<JSArray> can be passed when Handle<Object> is expected. |
+ template <typename S> |
+ V8_INLINE MaybeHandle(MaybeHandle<S> maybe_handle) |
+ : location_(reinterpret_cast<T**>(maybe_handle.location_)) { |
+ T* a = nullptr; |
+ S* b = nullptr; |
+ a = b; // Fake assignment to enforce type checks. |
+ USE(a); |
+ } |
+ |
+ V8_INLINE void Assert() const { DCHECK_NOT_NULL(location_); } |
+ V8_INLINE void Check() const { CHECK_NOT_NULL(location_); } |
+ |
+ V8_INLINE Handle<T> ToHandleChecked() const { |
+ Check(); |
+ return Handle<T>(location_); |
+ } |
+ |
+ // Convert to a Handle with a type that can be upcasted to. |
+ template <typename S> |
+ V8_INLINE bool ToHandle(Handle<S>* out) const { |
+ if (location_ == nullptr) { |
+ *out = Handle<T>::null(); |
+ return false; |
+ } else { |
+ *out = Handle<T>(location_); |
+ return true; |
+ } |
+ } |
+ |
+ bool is_null() const { return location_ == nullptr; } |
+ |
+ template <typename S> |
+ V8_INLINE bool operator==(MaybeHandle<S> that) const { |
+ return this->location_ == that.location_; |
+ } |
+ template <typename S> |
+ V8_INLINE bool operator!=(MaybeHandle<S> that) const { |
+ return this->location_ != that.location_; |
+ } |
+ |
+ protected: |
+ T** location_ = nullptr; |
+ |
+ // MaybeHandles of different classes are allowed to access each |
+ // other's location_. |
+ template <typename> |
+ friend class MaybeHandle; |
+ // Utility functions are allowed to access location_. |
+ template <typename S> |
+ friend size_t hash_value(MaybeHandle<S>); |
+}; |
+ |
+template <typename T> |
+V8_INLINE size_t hash_value(MaybeHandle<T> maybe_handle) { |
+ uintptr_t v = bit_cast<uintptr_t>(maybe_handle.location_); |
+ DCHECK_EQ(0u, v & ((1u << kPointerSizeLog2) - 1)); |
+ return v >> kPointerSizeLog2; |
+} |
// A stack-allocated class that governs a number of local handles. |
@@ -241,7 +280,7 @@ class HandleScope { |
Object** prev_limit); |
// Extend the handle scope making room for more handles. |
- static internal::Object** Extend(Isolate* isolate); |
+ static Object** Extend(Isolate* isolate); |
#ifdef ENABLE_HANDLE_ZAPPING |
// Zaps the handles in the half-open interval [start, end). |
@@ -249,16 +288,13 @@ class HandleScope { |
#endif |
friend class v8::HandleScope; |
- friend class v8::internal::DeferredHandles; |
- friend class v8::internal::HandleScopeImplementer; |
- friend class v8::internal::Isolate; |
+ friend class DeferredHandles; |
+ friend class HandleScopeImplementer; |
+ friend class Isolate; |
}; |
-class DeferredHandles; |
- |
- |
-class DeferredHandleScope { |
+class DeferredHandleScope final { |
public: |
explicit DeferredHandleScope(Isolate* isolate); |
// The DeferredHandles object returned stores the Handles created |
@@ -283,7 +319,7 @@ class DeferredHandleScope { |
// Seal off the current HandleScope so that new handles can only be created |
// if a new HandleScope is entered. |
-class SealHandleScope BASE_EMBEDDED { |
+class SealHandleScope final { |
public: |
#ifndef DEBUG |
explicit SealHandleScope(Isolate* isolate) {} |
@@ -298,9 +334,10 @@ class SealHandleScope BASE_EMBEDDED { |
#endif |
}; |
-struct HandleScopeData { |
- internal::Object** next; |
- internal::Object** limit; |
+ |
+struct HandleScopeData final { |
+ Object** next; |
+ Object** limit; |
int level; |
void Initialize() { |
@@ -309,6 +346,7 @@ struct HandleScopeData { |
} |
}; |
-} } // namespace v8::internal |
+} // namespace internal |
+} // namespace v8 |
#endif // V8_HANDLES_H_ |