[handles] Sanitize Handle and friends.
authorbmeurer <bmeurer@chromium.org>
Tue, 5 May 2015 12:48:14 +0000 (05:48 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 5 May 2015 12:48:17 +0000 (12:48 +0000)
This almost allows us to get rid of handles-inl.h, once we fix the
cyclic dependencies (follow up CL).

R=yangguo@chromium.org

Review URL: https://codereview.chromium.org/1128533002

Cr-Commit-Position: refs/heads/master@{#28222}

src/handles-inl.h
src/handles.cc
src/handles.h

index 34b3f32..725726d 100644 (file)
 // 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!
index d9b130f..c5410ab 100644 (file)
@@ -2,14 +2,64 @@
 // 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();
@@ -19,12 +69,73 @@ int HandleScope::NumberOfHandles(Isolate* isolate) {
 }
 
 
+// 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,
@@ -58,12 +169,6 @@ Object** HandleScope::Extend(Isolate* isolate) {
 }
 
 
-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);
@@ -127,4 +232,33 @@ DeferredHandles* DeferredHandleScope::Detach() {
   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
index eb57f0e..36d10ac 100644 (file)
 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,114 @@ 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(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;
 };
@@ -150,9 +199,9 @@ inline Handle<T> handle(T* t, Isolate* isolate) {
 
 
 // Convenience wrapper.
-template<class T>
+template <class T>
 inline Handle<T> handle(T* t) {
-  return Handle<T>(t, t->GetIsolate());
+  return Handle<T>(t);
 }
 
 
@@ -163,10 +212,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 +224,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 +251,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 +314,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 {
+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_