Fix handle zapping interaction with NoHandleAllocation.
authormstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 29 May 2013 11:09:01 +0000 (11:09 +0000)
committermstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 29 May 2013 11:09:01 +0000 (11:09 +0000)
This makes sure that closed handle scopes are properly zapped even if an
enclosing NoHandleAllocation shrunk the limit. It also unifies the code
that performs scope closing for internal and external handle scopes.

R=svenpanne@chromium.org
TEST=cctest/test-api/NestedLockersNoTryCatch

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14876 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

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

index 85b98370934292329b274c4170a8de6378aafd2d..c2c7930f48ca5b3ee49696481f8c402fef43287e 100644 (file)
@@ -679,19 +679,7 @@ HandleScope::~HandleScope() {
 
 
 void HandleScope::Leave() {
-  v8::ImplementationUtilities::HandleScopeData* current =
-      isolate_->handle_scope_data();
-  current->level--;
-  ASSERT(current->level >= 0);
-  current->next = prev_next_;
-  if (current->limit != prev_limit_) {
-    current->limit = prev_limit_;
-    i::HandleScope::DeleteExtensions(isolate_);
-  }
-
-#ifdef ENABLE_EXTRA_CHECKS
-  i::HandleScope::ZapRange(prev_next_, prev_limit_);
-#endif
+  return i::HandleScope::CloseScope(isolate_, prev_next_, prev_limit_);
 }
 
 
index 12d6e3d08229343644b3f571933c15543b90c19b..62380ce651249d86548c37679c9b2deb248c1bfd 100644 (file)
--- a/src/api.h
+++ b/src/api.h
@@ -637,7 +637,12 @@ void HandleScopeImplementer::DeleteExtensions(internal::Object** prev_limit) {
     internal::Object** block_limit = block_start + kHandleBlockSize;
 #ifdef DEBUG
     // NoHandleAllocation may make the prev_limit to point inside the block.
-    if (block_start <= prev_limit && prev_limit <= block_limit) break;
+    if (block_start <= prev_limit && prev_limit <= block_limit) {
+#ifdef ENABLE_EXTRA_CHECKS
+      internal::HandleScope::ZapRange(prev_limit, block_limit);
+#endif
+      break;
+    }
 #else
     if (prev_limit == block_limit) break;
 #endif
index 4f5e9fe720e0b68710ee9e2e6dc23709513c6f89..14687e3bd28086ff8d79935511b383e04ea27037 100644 (file)
@@ -122,31 +122,37 @@ HandleScope::HandleScope(Isolate* isolate) {
 
 
 HandleScope::~HandleScope() {
-  CloseScope();
+  CloseScope(isolate_, prev_next_, prev_limit_);
 }
 
-void HandleScope::CloseScope() {
+
+void HandleScope::CloseScope(Isolate* isolate,
+                             Object** prev_next,
+                             Object** prev_limit) {
   v8::ImplementationUtilities::HandleScopeData* current =
-      isolate_->handle_scope_data();
-  current->next = prev_next_;
+      isolate->handle_scope_data();
+
+  current->next = prev_next;
   current->level--;
-  if (current->limit != prev_limit_) {
-    current->limit = prev_limit_;
-    DeleteExtensions(isolate_);
+  if (current->limit != prev_limit) {
+    current->limit = prev_limit;
+    DeleteExtensions(isolate);
   }
+
 #ifdef ENABLE_EXTRA_CHECKS
-  ZapRange(prev_next_, prev_limit_);
+  ZapRange(prev_next, prev_limit);
 #endif
 }
 
 
 template <typename T>
 Handle<T> HandleScope::CloseAndEscape(Handle<T> handle_value) {
-  T* value = *handle_value;
-  // Throw away all handles in the current scope.
-  CloseScope();
   v8::ImplementationUtilities::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.
   ASSERT(current->level > 0);
   Handle<T> result(CreateHandle<T>(isolate_, value));
@@ -180,15 +186,14 @@ T** HandleScope::CreateHandle(Isolate* isolate, T* value) {
 #ifdef DEBUG
 inline NoHandleAllocation::NoHandleAllocation(Isolate* isolate)
     : isolate_(isolate) {
-  v8::ImplementationUtilities::HandleScopeData* current =
-      isolate_->handle_scope_data();
-
   active_ = !isolate->optimizing_compiler_thread()->IsOptimizerThread();
   if (active_) {
     // Shrink the current handle scope to make it impossible to do
     // handle allocations without an explicit handle scope.
+    v8::ImplementationUtilities::HandleScopeData* current =
+        isolate_->handle_scope_data();
+    limit_ = current->limit;
     current->limit = current->next;
-
     level_ = current->level;
     current->level = 0;
   }
@@ -199,10 +204,12 @@ inline NoHandleAllocation::~NoHandleAllocation() {
   if (active_) {
     // Restore state in current handle scope to re-enable handle
     // allocations.
-    v8::ImplementationUtilities::HandleScopeData* data =
+    v8::ImplementationUtilities::HandleScopeData* current =
         isolate_->handle_scope_data();
-    ASSERT_EQ(0, data->level);
-    data->level = level_;
+    ASSERT_EQ(0, current->level);
+    current->level = level_;
+    ASSERT_EQ(current->next, current->limit);
+    current->limit = limit_;
   }
 }
 
index 938d43b8a4e8ba418f85b7eb5ccd2a5ccfb6aad3..29ece281e0984d3fe9224860b3aa2703911cddd1 100644 (file)
@@ -155,18 +155,21 @@ class HandleScope {
   void* operator new(size_t size);
   void operator delete(void* size_t);
 
-  inline void CloseScope();
-
   Isolate* isolate_;
   Object** prev_next_;
   Object** prev_limit_;
 
+  // Close the handle scope resetting limits to a previous state.
+  static inline 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);
 
 #ifdef ENABLE_EXTRA_CHECKS
   // Zaps the handles in the half-open interval [start, end).
-  static void ZapRange(internal::Object** start, internal::Object** end);
+  static void ZapRange(Object** start, Object** end);
 #endif
 
   friend class v8::HandleScope;
@@ -337,6 +340,7 @@ class NoHandleAllocation BASE_EMBEDDED {
   inline ~NoHandleAllocation();
  private:
   Isolate* isolate_;
+  Object** limit_;
   int level_;
   bool active_;
 #endif