Index: src/handles.h |
diff --git a/src/handles.h b/src/handles.h |
index eb57f0e26089383c9d7fe9f57a8cba5f41a111e2..b97badaea9cbcadeb13114fb43da099a1d8a9dab 100644 |
--- a/src/handles.h |
+++ b/src/handles.h |
@@ -10,22 +10,26 @@ |
namespace v8 { |
namespace internal { |
+// Forward declarations. |
+class DeferredHandles; |
+class HandleScopeImplementer; |
+ |
+ |
// 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 { |
public: |
- INLINE(MaybeHandle()) : location_(NULL) { } |
+ V8_INLINE MaybeHandle() : location_(nullptr) {} |
// 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; |
+ T* a = nullptr; |
+ S* b = nullptr; |
a = b; // Fake assignment to enforce type checks. |
USE(a); |
#endif |
@@ -44,10 +48,10 @@ class MaybeHandle { |
location_ = reinterpret_cast<T**>(maybe_handle.location_); |
} |
- INLINE(void Assert() const) { DCHECK(location_ != NULL); } |
- INLINE(void Check() const) { CHECK(location_ != NULL); } |
+ V8_INLINE void Assert() const { DCHECK_NOT_NULL(location_); } |
+ V8_INLINE void Check() const { CHECK_NOT_NULL(location_); } |
- INLINE(Handle<T> ToHandleChecked()) const { |
+ V8_INLINE Handle<T> ToHandleChecked() const { |
Check(); |
return Handle<T>(location_); |
} |
@@ -74,69 +78,116 @@ class MaybeHandle { |
template<class S> friend class MaybeHandle; |
}; |
+ |
+// Base class for Handles. Don't use this directly. |
+class HandleBase { |
+ public: |
+ V8_INLINE explicit HandleBase(Object** location = nullptr) |
+ : location_(location) {} |
+ V8_INLINE explicit HandleBase(HandleBase const& other) |
+ : location_(other.location_) {} |
+ explicit HandleBase(HeapObject* object); |
+ explicit HandleBase(Object* object, Isolate* isolate); |
+ V8_INLINE ~HandleBase() {} |
+ |
+ // Check if this handle refers to the exact same object as the other handle. |
+ V8_INLINE bool is_identical_to(HandleBase const& other) const { |
+ // Dereferencing deferred handles to check object equality is safe. |
+ SLOW_DCHECK(location_ == nullptr || |
+ IsDereferenceAllowed(NO_DEFERRED_CHECK)); |
+ SLOW_DCHECK(other.location_ == nullptr || |
+ other.IsDereferenceAllowed(NO_DEFERRED_CHECK)); |
+ if (location_ == other.location_) return true; |
+ if (location_ == nullptr || other.location_ == nullptr) return false; |
+ return *location_ == *other.location_; |
+ } |
+ |
+ // Check if this handle is a NULL handle. |
+ V8_INLINE bool is_null() const { return location_ == nullptr; } |
+ |
+ protected: |
+ // Provides the C++ deference operator. |
+ V8_INLINE Object* operator*() const { |
+ SLOW_DCHECK(IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK)); |
+ return *location_; |
+ } |
+ |
+ // Returns the address to where the raw pointer is stored. |
+ V8_INLINE Object** location() const { |
+ SLOW_DCHECK(location_ == nullptr || |
+ IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK)); |
+ return location_; |
+ } |
+ |
+ private: |
+ enum DereferenceCheckMode { INCLUDE_DEFERRED_CHECK, NO_DEFERRED_CHECK }; |
+#ifdef DEBUG |
+ bool IsDereferenceAllowed(DereferenceCheckMode mode) const; |
+#else |
+ V8_INLINE bool IsDereferenceAllowed(DereferenceCheckMode) const { |
+ return true; |
+ } |
+#endif // DEBUG |
+ |
+ Object** 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)); |
+ V8_INLINE explicit Handle(T** location) |
+ : HandleBase(reinterpret_cast<Object**>(location)) {} |
+ V8_INLINE explicit Handle(T* object) : HandleBase(object) {} |
+ V8_INLINE Handle(T* object, Isolate* isolate) : HandleBase(object, 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 Handle() {} |
// 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 <class S> |
+ V8_INLINE Handle(Handle<S> const& other) |
+ : HandleBase(other) { |
+ 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) { |
- T::cast(*reinterpret_cast<T**>(that.location_)); |
- return Handle<T>(reinterpret_cast<T**>(that.location_)); |
+ template <class S> |
+ V8_INLINE static Handle<T> cast(Handle<S> const& other) { |
+ T::cast(*reinterpret_cast<T**>(other.location())); |
+ return Handle<T>(reinterpret_cast<T**>(other.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 |
- |
private: |
- T** location_; |
- |
// Handles of different classes are allowed to access each other's location_. |
template<class S> friend class Handle; |
}; |
@@ -163,10 +214,6 @@ inline bool operator<(const Handle<Map>& lhs, const Handle<Map>& rhs) { |
} |
-class DeferredHandles; |
-class HandleScopeImplementer; |
- |
- |
// A stack-allocated class that governs a number of local handles. |
// After a handle scope has been created, all local handles will be |
// allocated within that handle scope until either the handle scope is |
@@ -179,18 +226,21 @@ class HandleScopeImplementer; |
// garbage collector will no longer track the object stored in the |
// handle and may deallocate it. The behavior of accessing a handle |
// for which the handle scope has been deleted is undefined. |
-class HandleScope { |
+class HandleScope final { |
public: |
- explicit inline HandleScope(Isolate* isolate); |
- |
- inline ~HandleScope(); |
+ explicit HandleScope(Isolate* isolate); |
+ ~HandleScope(); |
// Counts the number of allocated handles. |
static int NumberOfHandles(Isolate* isolate); |
// Creates a new handle with the given value. |
+ static Object** CreateHandle(Isolate* isolate, Object* value); |
template <typename T> |
- static inline T** CreateHandle(Isolate* isolate, T* value); |
+ static T** CreateHandle(Isolate* isolate, T* value) { |
+ return reinterpret_cast<T**>( |
+ CreateHandle(isolate, static_cast<Object*>(value))); |
+ } |
// Deallocates any extensions used by the current scope. |
static void DeleteExtensions(Isolate* isolate); |
@@ -203,43 +253,42 @@ class HandleScope { |
// created in the scope of the HandleScope) and returns |
// a Handle backed by the parent scope holding the |
// value of the argument handle. |
+ Handle<Object> CloseAndEscape(Handle<Object> handle); |
template <typename T> |
- Handle<T> CloseAndEscape(Handle<T> handle_value); |
+ Handle<T> CloseAndEscape(Handle<T> handle) { |
+ return Handle<T>::cast(CloseAndEscape(Handle<Object>::cast(handle))); |
+ } |
- Isolate* isolate() { return isolate_; } |
+ Isolate* isolate() const { return isolate_; } |
private: |
- // Prevent heap allocation or illegal handle scopes. |
- HandleScope(const HandleScope&); |
- void operator=(const HandleScope&); |
- void* operator new(size_t size); |
- void operator delete(void* size_t); |
+ friend class v8::HandleScope; |
+ friend class v8::internal::DeferredHandles; |
+ friend class v8::internal::HandleScopeImplementer; |
+ friend class v8::internal::Isolate; |
- Isolate* isolate_; |
- Object** prev_next_; |
- Object** prev_limit_; |
+ // Prevent heap allocation or illegal handle scopes. |
+ void* operator new(size_t size) = delete; |
+ void operator delete(void* size_t) = delete; |
// Close the handle scope resetting limits to a previous state. |
- static inline void CloseScope(Isolate* isolate, |
- Object** prev_next, |
- Object** prev_limit); |
+ static void CloseScope(Isolate* isolate, Object** prev_next, |
+ 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). |
static void ZapRange(Object** start, Object** end); |
#endif |
- friend class v8::HandleScope; |
- friend class v8::internal::DeferredHandles; |
- friend class v8::internal::HandleScopeImplementer; |
- friend class v8::internal::Isolate; |
-}; |
- |
+ Isolate* const isolate_; |
+ Object** prev_next_; |
+ Object** prev_limit_; |
-class DeferredHandles; |
+ DISALLOW_COPY_AND_ASSIGN(HandleScope); |
+}; |
class DeferredHandleScope { |
@@ -267,32 +316,38 @@ 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 { |
Yang
2015/05/05 11:01:31
Why are we getting rid of BASE_EMBEDDED here?
Benedikt Meurer
2015/05/05 12:11:15
Because it's crap and doesn't work as intended, as
|
+class SealHandleScope final { |
public: |
#ifndef DEBUG |
explicit SealHandleScope(Isolate* isolate) {} |
~SealHandleScope() {} |
#else |
- explicit inline SealHandleScope(Isolate* isolate); |
- inline ~SealHandleScope(); |
+ explicit SealHandleScope(Isolate* isolate); |
+ ~SealHandleScope(); |
+ |
private: |
- Isolate* isolate_; |
+ Isolate* const isolate_; |
Object** limit_; |
int level_; |
-#endif |
+#endif // DEBUG |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(SealHandleScope); |
}; |
+ |
struct HandleScopeData { |
internal::Object** next; |
internal::Object** limit; |
int level; |
void Initialize() { |
- next = limit = NULL; |
+ next = limit = nullptr; |
level = 0; |
} |
}; |
-} } // namespace v8::internal |
+} // namespace internal |
+} // namespace v8 |
#endif // V8_HANDLES_H_ |