// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-//
-
-#ifndef V8_HANDLES_INL_H_
-#define V8_HANDLES_INL_H_
#include "src/api.h"
#include "src/handles.h"
#include "src/heap/heap.h"
#include "src/isolate.h"
-namespace v8 {
-namespace internal {
-
-template<typename T>
-Handle<T>::Handle(T* obj) {
- location_ = HandleScope::CreateHandle(obj->GetIsolate(), obj);
-}
-
-
-template<typename T>
-Handle<T>::Handle(T* obj, Isolate* isolate) {
- location_ = HandleScope::CreateHandle(isolate, obj);
-}
-
-
-template <typename T>
-inline bool Handle<T>::is_identical_to(const Handle<T> o) const {
- // Dereferencing deferred handles to check object equality is safe.
- SLOW_DCHECK(
- (location_ == NULL || IsDereferenceAllowed(NO_DEFERRED_CHECK)) &&
- (o.location_ == NULL || o.IsDereferenceAllowed(NO_DEFERRED_CHECK)));
- if (location_ == o.location_) return true;
- if (location_ == NULL || o.location_ == NULL) return false;
- return *location_ == *o.location_;
-}
-
-
-template <typename T>
-inline T* Handle<T>::operator*() const {
- SLOW_DCHECK(IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
- return *bit_cast<T**>(location_);
-}
-
-template <typename T>
-inline T** Handle<T>::location() const {
- SLOW_DCHECK(location_ == NULL ||
- IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
- return location_;
-}
-
-#ifdef DEBUG
-template <typename T>
-bool Handle<T>::IsDereferenceAllowed(DereferenceCheckMode mode) const {
- DCHECK(location_ != NULL);
- Object* object = *bit_cast<T**>(location_);
- if (object->IsSmi()) return true;
- HeapObject* heap_object = HeapObject::cast(object);
- Heap* heap = heap_object->GetHeap();
- Object** handle = reinterpret_cast<Object**>(location_);
- Object** roots_array_start = heap->roots_array_start();
- if (roots_array_start <= handle &&
- handle < roots_array_start + Heap::kStrongRootListLength &&
- heap->RootCanBeTreatedAsConstant(
- static_cast<Heap::RootListIndex>(handle - roots_array_start))) {
- return true;
- }
- if (!AllowHandleDereference::IsAllowed()) return false;
- if (mode == INCLUDE_DEFERRED_CHECK &&
- !AllowDeferredHandleDereference::IsAllowed()) {
- // Accessing cells, maps and internalized strings is safe.
- if (heap_object->IsCell()) return true;
- if (heap_object->IsMap()) return true;
- if (heap_object->IsInternalizedString()) return true;
- return !heap->isolate()->IsDeferredHandle(handle);
- }
- return true;
-}
-#endif
-
-
-
-HandleScope::HandleScope(Isolate* isolate) {
- HandleScopeData* current = isolate->handle_scope_data();
- isolate_ = isolate;
- prev_next_ = current->next;
- prev_limit_ = current->limit;
- current->level++;
-}
-
-
-HandleScope::~HandleScope() {
- CloseScope(isolate_, prev_next_, prev_limit_);
-}
-
-
-void HandleScope::CloseScope(Isolate* isolate,
- Object** prev_next,
- Object** prev_limit) {
- HandleScopeData* current = isolate->handle_scope_data();
-
- std::swap(current->next, prev_next);
- current->level--;
- if (current->limit != prev_limit) {
- current->limit = prev_limit;
- DeleteExtensions(isolate);
-#ifdef ENABLE_HANDLE_ZAPPING
- ZapRange(current->next, prev_limit);
- } else {
- ZapRange(current->next, prev_next);
-#endif
- }
-}
-
-
-template <typename T>
-Handle<T> HandleScope::CloseAndEscape(Handle<T> handle_value) {
- HandleScopeData* current = isolate_->handle_scope_data();
-
- T* value = *handle_value;
- // Throw away all handles in the current scope.
- CloseScope(isolate_, prev_next_, prev_limit_);
- // Allocate one handle in the parent scope.
- DCHECK(current->level > 0);
- Handle<T> result(CreateHandle<T>(isolate_, value));
- // Reinitialize the current scope (so that it's ready
- // to be used or closed again).
- prev_next_ = current->next;
- prev_limit_ = current->limit;
- current->level++;
- return result;
-}
-
-
-template <typename T>
-T** HandleScope::CreateHandle(Isolate* isolate, T* value) {
- DCHECK(AllowHandleAllocation::IsAllowed());
- HandleScopeData* current = isolate->handle_scope_data();
-
- internal::Object** cur = current->next;
- if (cur == current->limit) cur = Extend(isolate);
- // Update the current next field, set the value in the created
- // handle, and return the result.
- DCHECK(cur < current->limit);
- current->next = cur + 1;
-
- T** result = reinterpret_cast<T**>(cur);
- *result = value;
- return result;
-}
-
-
-#ifdef DEBUG
-inline SealHandleScope::SealHandleScope(Isolate* isolate) : isolate_(isolate) {
- // Make sure the current thread is allowed to create handles to begin with.
- CHECK(AllowHandleAllocation::IsAllowed());
- HandleScopeData* current = isolate_->handle_scope_data();
- // Shrink the current handle scope to make it impossible to do
- // handle allocations without an explicit handle scope.
- limit_ = current->limit;
- current->limit = current->next;
- level_ = current->level;
- current->level = 0;
-}
-
-
-inline SealHandleScope::~SealHandleScope() {
- // Restore state in current handle scope to re-enable handle
- // allocations.
- HandleScopeData* current = isolate_->handle_scope_data();
- DCHECK_EQ(0, current->level);
- current->level = level_;
- DCHECK_EQ(current->next, current->limit);
- current->limit = limit_;
-}
-
-#endif
-
-} } // namespace v8::internal
-
-#endif // V8_HANDLES_INL_H_
+// TODO(bmeurer): Break all include cycles and remove this file!
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-
#include "src/handles.h"
+#include "src/api.h"
+#include "src/isolate.h"
+
namespace v8 {
namespace internal {
+HandleBase::HandleBase(HeapObject* object)
+ : HandleBase(object, object->GetIsolate()) {}
+
+
+HandleBase::HandleBase(Object* object, Isolate* isolate)
+ : HandleBase(HandleScope::CreateHandle(isolate, object)) {}
+
+
+#ifdef DEBUG
+
+bool HandleBase::IsDereferenceAllowed(DereferenceCheckMode mode) const {
+ DCHECK_NOT_NULL(location_);
+ Object* const object = *location_;
+ if (object->IsSmi()) return true;
+ HeapObject* const heap_object = HeapObject::cast(object);
+ Heap* const heap = heap_object->GetHeap();
+ Object** roots_array_start = heap->roots_array_start();
+ if (roots_array_start <= location_ &&
+ location_ < roots_array_start + Heap::kStrongRootListLength &&
+ heap->RootCanBeTreatedAsConstant(
+ static_cast<Heap::RootListIndex>(location_ - roots_array_start))) {
+ return true;
+ }
+ if (!AllowHandleDereference::IsAllowed()) return false;
+ if (mode == INCLUDE_DEFERRED_CHECK &&
+ !AllowDeferredHandleDereference::IsAllowed()) {
+ // Accessing cells, maps and internalized strings is safe.
+ if (heap_object->IsCell()) return true;
+ if (heap_object->IsMap()) return true;
+ if (heap_object->IsInternalizedString()) return true;
+ return !heap->isolate()->IsDeferredHandle(location_);
+ }
+ return true;
+}
+
+#endif // DEBUG
+
+
+HandleScope::HandleScope(Isolate* isolate) : isolate_(isolate) {
+ HandleScopeData* const current = isolate->handle_scope_data();
+ prev_next_ = current->next;
+ prev_limit_ = current->limit;
+ current->level++;
+}
+
+HandleScope::~HandleScope() { CloseScope(isolate_, prev_next_, prev_limit_); }
+
+
+// static
int HandleScope::NumberOfHandles(Isolate* isolate) {
HandleScopeImplementer* impl = isolate->handle_scope_implementer();
int n = impl->blocks()->length();
}
+// static
+Object** HandleScope::CreateHandle(Isolate* isolate, Object* value) {
+ DCHECK(AllowHandleAllocation::IsAllowed());
+ HandleScopeData* const current = isolate->handle_scope_data();
+
+ Object** result = current->next;
+ if (result == current->limit) result = Extend(isolate);
+ // Update the current next field, set the value in the created
+ // handle, and return the result.
+ DCHECK_LT(result, current->limit);
+ current->next = result + 1;
+
+ *result = value;
+ return result;
+}
+
+
+// static
+void HandleScope::DeleteExtensions(Isolate* isolate) {
+ HandleScopeData* const current = isolate->handle_scope_data();
+ isolate->handle_scope_implementer()->DeleteExtensions(current->limit);
+}
+
+
+Handle<Object> HandleScope::CloseAndEscape(Handle<Object> handle) {
+ HandleScopeData* const current = isolate_->handle_scope_data();
+
+ Object* value = *handle;
+ // Throw away all handles in the current scope.
+ CloseScope(isolate_, prev_next_, prev_limit_);
+ // Allocate one handle in the parent scope.
+ DCHECK_LT(0, current->level);
+ Handle<Object> result(CreateHandle(isolate_, value));
+ // Reinitialize the current scope (so that it's ready
+ // to be used or closed again).
+ prev_next_ = current->next;
+ prev_limit_ = current->limit;
+ current->level++;
+ return result;
+}
+
+
+// static
+void HandleScope::CloseScope(Isolate* isolate, Object** prev_next,
+ Object** prev_limit) {
+ HandleScopeData* const current = isolate->handle_scope_data();
+
+ std::swap(current->next, prev_next);
+ current->level--;
+ if (current->limit != prev_limit) {
+ current->limit = prev_limit;
+ DeleteExtensions(isolate);
+#ifdef ENABLE_HANDLE_ZAPPING
+ ZapRange(current->next, prev_limit);
+ } else {
+ ZapRange(current->next, prev_next);
+#endif
+ }
+}
+
+
+// static
Object** HandleScope::Extend(Isolate* isolate) {
HandleScopeData* current = isolate->handle_scope_data();
Object** result = current->next;
-
- DCHECK(result == current->limit);
+ DCHECK_EQ(result, current->limit);
// Make sure there's at least one scope on the stack and that the
// top of the scope stack isn't a barrier.
if (!Utils::ApiCheck(current->level != 0,
}
-void HandleScope::DeleteExtensions(Isolate* isolate) {
- HandleScopeData* current = isolate->handle_scope_data();
- isolate->handle_scope_implementer()->DeleteExtensions(current->limit);
-}
-
-
#ifdef ENABLE_HANDLE_ZAPPING
void HandleScope::ZapRange(Object** start, Object** end) {
DCHECK(end - start <= kHandleBlockSize);
return deferred;
}
-} } // namespace v8::internal
+
+#ifdef DEBUG
+
+SealHandleScope::SealHandleScope(Isolate* isolate) : isolate_(isolate) {
+ // Make sure the current thread is allowed to create handles to begin with.
+ CHECK(AllowHandleAllocation::IsAllowed());
+ HandleScopeData* const current = isolate_->handle_scope_data();
+ // Shrink the current handle scope to make it impossible to do
+ // handle allocations without an explicit handle scope.
+ limit_ = current->limit;
+ current->limit = current->next;
+ level_ = current->level;
+ current->level = 0;
+}
+
+
+SealHandleScope::~SealHandleScope() {
+ // Restore state in current handle scope to re-enable handle
+ // allocations.
+ HandleScopeData* const current = isolate_->handle_scope_data();
+ DCHECK_EQ(0, current->level);
+ current->level = level_;
+ DCHECK_EQ(current->next, current->limit);
+ current->limit = limit_;
+}
+
+#endif // DEBUG
+
+} // namespace internal
+} // namespace v8
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
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_);
}
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(is_null() || IsDereferenceAllowed(NO_DEFERRED_CHECK));
+ SLOW_DCHECK(other.is_null() ||
+ 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_;
+ }
+
+ 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;
};
// Convenience wrapper.
-template<class T>
+template <class T>
inline Handle<T> handle(T* t) {
- return Handle<T>(t, t->GetIsolate());
+ return Handle<T>(t);
}
}
-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
// 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);
// 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 {
// 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) {}
~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_