Split handle scopes into an internal version and a version accessible
authoriposva@chromium.org <iposva@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 23 Jan 2009 17:22:23 +0000 (17:22 +0000)
committeriposva@chromium.org <iposva@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 23 Jan 2009 17:22:23 +0000 (17:22 +0000)
through the API. This allows us to verify state on entry through the API.
In this change verification in the API entry is checking that the current
thread holds the V8 lock when a HandleScope is instantiated if a v8::Locker
has ever been used by the V8 instance.
Review URL: http://codereview.chromium.org/18707

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

include/v8.h
src/api.cc
src/api.h
src/apiutils.h [new file with mode: 0644]
src/factory.cc
src/handles-inl.h
src/handles.cc
src/handles.h
src/messages.cc
src/v8threads.cc
tools/v8.xcodeproj/project.pbxproj

index 1876a547caa1a9621fe51a27f63d436a919361bb..fc8b47a4f491f39e6427f1375d522b9618f9ebe8 100644 (file)
@@ -396,19 +396,11 @@ template <class T> class EXPORT_INLINE Persistent : public Handle<T> {
  */
 class EXPORT HandleScope {
  public:
-  HandleScope() : previous_(current_), is_closed_(false) {
-    current_.extensions = 0;
-  }
+  HandleScope();
 
-  ~HandleScope() {
-    // TODO(1245391): In a perfect world, there would be a way of not
-    // having to check for explicitly closed scopes maybe through
-    // subclassing HandleScope?
-    if (!is_closed_) RestorePreviousState();
-  }
+  ~HandleScope();
 
   /**
-   * TODO(1245391): Consider introducing a subclass for this.
    * Closes the handle scope and returns the value as a handle in the
    * previous scope, which is the new current scope after the call.
    */
@@ -432,6 +424,8 @@ class EXPORT HandleScope {
   void* operator new(size_t size);
   void operator delete(void*, size_t);
 
+  // This Data class is accessible internally through a typedef in the
+  // ImplementationUtilities class.
   class EXPORT Data {
    public:
     int extensions;
@@ -443,31 +437,13 @@ class EXPORT HandleScope {
     }
   };
 
-  static Data current_;
-  const Data previous_;
-
-  /**
-   * Re-establishes the previous scope state. Should be called only
-   * once, and only for the current scope.
-   */
-  void RestorePreviousState() {
-    if (current_.extensions > 0) DeleteExtensions();
-    current_ = previous_;
-#ifdef DEBUG
-    ZapRange(current_.next, current_.limit);
-#endif
-  }
+  Data previous_;
 
-  // TODO(1245391): Consider creating a subclass for this.
+  // Allow for the active closing of HandleScopes which allows to pass a handle
+  // from the HandleScope being closed to the next top most HandleScope.
   bool is_closed_;
   void** RawClose(void** value);
 
-  /** Deallocates any extensions used by the current scope.*/
-  static void DeleteExtensions();
-
-  // Zaps the handles in the half-open interval [start, end).
-  static void ZapRange(void** start, void** end);
-
   friend class ImplementationUtilities;
 };
 
@@ -2284,10 +2260,17 @@ class EXPORT Locker {
    */
   static bool IsLocked();
 
+  /**
+   * Returns whether v8::Locker is being used by this V8 instance.
+   */
+  static bool IsActive() { return active_; }
+
  private:
   bool has_lock_;
   bool top_level_;
 
+  static bool active_;
+
   // Disallow copying and assigning.
   Locker(const Locker&);
   void operator=(const Locker&);
index 485a148ce62257987c1d92a7fbfa99c9451e4d07..7fb9b4b91dc4542b0e11d6a8815cfa203e5ec44b 100644 (file)
@@ -36,6 +36,7 @@
 #include "platform.h"
 #include "serialize.h"
 #include "snapshot.h"
+#include "v8threads.h"
 
 
 namespace i = v8::internal;
@@ -73,6 +74,15 @@ namespace v8 {
   } while (false)
 
 
+#define API_ENTRY_CHECK(msg)                                                   \
+  do {                                                                         \
+    if (v8::Locker::IsActive()) {                                              \
+      ApiCheck(i::ThreadManager::IsLockedByCurrentThread(),                    \
+               msg,                                                            \
+               "Entering the V8 API without proper locking in place");         \
+    }                                                                          \
+  } while (false)
+
 // --- D a t a   t h a t   i s   s p e c i f i c   t o   a   t h r e a d ---
 
 
@@ -190,6 +200,19 @@ static void EnsureInitialized(const char* location) {
 }
 
 
+ImplementationUtilities::HandleScopeData*
+    ImplementationUtilities::CurrentHandleScope() {
+  return &i::HandleScope::current_;
+}
+
+
+#ifdef DEBUG
+void ImplementationUtilities::ZapHandleRange(void** begin, void** end) {
+  i::HandleScope::ZapRange(begin, end);
+}
+#endif
+
+
 v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() {
   if (IsDeadCheck("v8::Undefined()")) return v8::Handle<v8::Primitive>();
   EnsureInitialized("v8::Undefined()");
@@ -359,55 +382,26 @@ void V8::DisposeGlobal(void** obj) {
 // --- H a n d l e s ---
 
 
-HandleScope::Data HandleScope::current_ = { -1, NULL, NULL };
+HandleScope::HandleScope() : is_closed_(false) {
+  API_ENTRY_CHECK("HandleScope::HandleScope");
+  i::HandleScope::Enter(&previous_);
+}
 
 
-int HandleScope::NumberOfHandles() {
-  int n = thread_local.Blocks()->length();
-  if (n == 0) return 0;
-  return ((n - 1) * i::kHandleBlockSize) +
-       (current_.next - thread_local.Blocks()->last());
+HandleScope::~HandleScope() {
+  if (!is_closed_) {
+    i::HandleScope::Leave(&previous_);
+  }
 }
 
 
-void** v8::HandleScope::CreateHandle(void* value) {
-  void** result = current_.next;
-  if (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 (!ApiCheck(current_.extensions >= 0,
-                  "v8::HandleScope::CreateHandle()",
-                  "Cannot create a handle without a HandleScope")) {
-      return NULL;
-    }
-    // If there's more room in the last block, we use that. This is used
-    // for fast creation of scopes after scope barriers.
-    if (!thread_local.Blocks()->is_empty()) {
-      void** limit = &thread_local.Blocks()->last()[i::kHandleBlockSize];
-      if (current_.limit != limit) {
-        current_.limit = limit;
-      }
-    }
+int HandleScope::NumberOfHandles() {
+  return i::HandleScope::NumberOfHandles();
+}
 
-    // If we still haven't found a slot for the handle, we extend the
-    // current handle scope by allocating a new handle block.
-    if (result == current_.limit) {
-      // If there's a spare block, use it for growing the current scope.
-      result = thread_local.GetSpareOrNewBlock();
-      // Add the extension to the global list of blocks, but count the
-      // extension as part of the current scope.
-      thread_local.Blocks()->Add(result);
-      current_.extensions++;
-      current_.limit = &result[i::kHandleBlockSize];
-    }
-  }
 
-  // Update the current next field, set the value in the created
-  // handle, and return the result.
-  ASSERT(result < current_.limit);
-  current_.next = result + 1;
-  *result = value;
-  return result;
+void** v8::HandleScope::CreateHandle(void* value) {
+  return i::HandleScope::CreateHandle(value);
 }
 
 
@@ -436,20 +430,6 @@ void Context::Exit() {
 }
 
 
-void v8::HandleScope::DeleteExtensions() {
-  ASSERT(current_.extensions != 0);
-  thread_local.DeleteExtensions(current_.extensions);
-}
-
-
-void HandleScope::ZapRange(void** start, void** end) {
-  if (start == NULL) return;
-  for (void** p = start; p < end; p++) {
-    *p = reinterpret_cast<void*>(v8::internal::kHandleZapValue);
-  }
-}
-
-
 void** v8::HandleScope::RawClose(void** value) {
   if (!ApiCheck(!is_closed_,
                 "v8::HandleScope::Close()",
@@ -461,7 +441,7 @@ void** v8::HandleScope::RawClose(void** value) {
   // Read the result before popping the handle block.
   i::Object* result = reinterpret_cast<i::Object*>(*value);
   is_closed_ = true;
-  RestorePreviousState();
+  i::HandleScope::Leave(&previous_);
 
   // Allocate a new handle on the previous handle block.
   i::Handle<i::Object> handle(result);
@@ -2951,8 +2931,8 @@ char* HandleScopeImplementer::ArchiveThread(char* storage) {
 
 
 char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) {
-  ImplementationUtilities::HandleScopeData* current =
-      ImplementationUtilities::CurrentHandleScope();
+  v8::ImplementationUtilities::HandleScopeData* current =
+      v8::ImplementationUtilities::CurrentHandleScope();
   handle_scope_data_ = *current;
   memcpy(storage, this, sizeof(*this));
 
@@ -2975,7 +2955,7 @@ char* HandleScopeImplementer::RestoreThread(char* storage) {
 
 char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
   memcpy(this, storage, sizeof(*this));
-  *ImplementationUtilities::CurrentHandleScope() = handle_scope_data_;
+  *v8::ImplementationUtilities::CurrentHandleScope() = handle_scope_data_;
   return storage + ArchiveSpacePerThread();
 }
 
@@ -2983,7 +2963,7 @@ char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
 void HandleScopeImplementer::Iterate(
     ObjectVisitor* v,
     List<void**>* blocks,
-    ImplementationUtilities::HandleScopeData* handle_data) {
+    v8::ImplementationUtilities::HandleScopeData* handle_data) {
   // Iterate over all handles in the blocks except for the last.
   for (int i = blocks->length() - 2; i >= 0; --i) {
     Object** block =
@@ -3000,8 +2980,8 @@ void HandleScopeImplementer::Iterate(
 
 
 void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
-  ImplementationUtilities::HandleScopeData* current =
-      ImplementationUtilities::CurrentHandleScope();
+  v8::ImplementationUtilities::HandleScopeData* current =
+      v8::ImplementationUtilities::CurrentHandleScope();
   Iterate(v, thread_local.Blocks(), current);
 }
 
@@ -3010,7 +2990,7 @@ char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
   HandleScopeImplementer* thread_local =
       reinterpret_cast<HandleScopeImplementer*>(storage);
   List<void**>* blocks_of_archived_thread = thread_local->Blocks();
-  ImplementationUtilities::HandleScopeData* handle_data_of_archived_thread =
+  v8::ImplementationUtilities::HandleScopeData* handle_data_of_archived_thread =
       &thread_local->handle_scope_data_;
   Iterate(v, blocks_of_archived_thread, handle_data_of_archived_thread);
 
index f4cea8b6ab4d6076ebafc3521550539e9fe00dbe..85b13ec9a670296e926440016f0c30cb1ec0da0d 100644 (file)
--- a/src/api.h
+++ b/src/api.h
@@ -28,6 +28,7 @@
 #ifndef V8_API_H_
 #define V8_API_H_
 
+#include "apiutils.h"
 #include "factory.h"
 
 namespace v8 {
@@ -159,45 +160,6 @@ class RegisteredExtension {
 };
 
 
-class ImplementationUtilities {
- public:
-  static v8::Handle<v8::Primitive> Undefined();
-  static v8::Handle<v8::Primitive> Null();
-  static v8::Handle<v8::Boolean> True();
-  static v8::Handle<v8::Boolean> False();
-
-  static int GetNameCount(ExtensionConfiguration* that) {
-    return that->name_count_;
-  }
-
-  static const char** GetNames(ExtensionConfiguration* that) {
-    return that->names_;
-  }
-
-  static v8::Arguments NewArguments(Local<Value> data,
-                                    Local<Object> holder,
-                                    Local<Function> callee,
-                                    bool is_construct_call,
-                                    void** argv, int argc) {
-    return v8::Arguments(data, holder, callee, is_construct_call, argv, argc);
-  }
-
-  // Introduce an alias for the handle scope data to allow non-friends
-  // to access the HandleScope data.
-  typedef v8::HandleScope::Data HandleScopeData;
-
-  static HandleScopeData* CurrentHandleScope() {
-    return &v8::HandleScope::current_;
-  }
-
-#ifdef DEBUG
-  static void ZapHandleRange(void** begin, void** end) {
-    v8::HandleScope::ZapRange(begin, end);
-  }
-#endif
-};
-
-
 class Utils {
  public:
   static bool ReportApiFailure(const char* location, const char* message);
@@ -275,7 +237,7 @@ static inline T* ToApi(v8::internal::Handle<v8::internal::Object> obj) {
 
 template <class T>
 v8::internal::Handle<T> v8::internal::Handle<T>::EscapeFrom(
-    HandleScope* scope) {
+    v8::HandleScope* scope) {
   return Utils::OpenHandle(*scope->Close(Utils::ToLocal(*this)));
 }
 
@@ -408,11 +370,11 @@ class HandleScopeImplementer {
   List<Handle<Object> > saved_contexts_;
   bool ignore_out_of_memory;
   // This is only used for threading support.
-  ImplementationUtilities::HandleScopeData handle_scope_data_;
+  v8::ImplementationUtilities::HandleScopeData handle_scope_data_;
 
   static void Iterate(ObjectVisitor* v,
-                      List<void**>* blocks,
-                      ImplementationUtilities::HandleScopeData* handle_data);
+      List<void**>* blocks,
+      v8::ImplementationUtilities::HandleScopeData* handle_data);
   char* RestoreThreadHelper(char* from);
   char* ArchiveThreadHelper(char* to);
 
@@ -474,13 +436,14 @@ void HandleScopeImplementer::DeleteExtensions(int extensions) {
   for (int i = extensions; i > 1; --i) {
     void** block = blocks.RemoveLast();
 #ifdef DEBUG
-    ImplementationUtilities::ZapHandleRange(block, &block[kHandleBlockSize]);
+    v8::ImplementationUtilities::ZapHandleRange(block,
+                                                &block[kHandleBlockSize]);
 #endif
     DeleteArray(block);
   }
   spare = reinterpret_cast<Object**>(blocks.RemoveLast());
 #ifdef DEBUG
-  ImplementationUtilities::ZapHandleRange(
+  v8::ImplementationUtilities::ZapHandleRange(
       reinterpret_cast<void**>(spare),
       reinterpret_cast<void**>(&spare[kHandleBlockSize]));
 #endif
diff --git a/src/apiutils.h b/src/apiutils.h
new file mode 100644 (file)
index 0000000..5745343
--- /dev/null
@@ -0,0 +1,69 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_APIUTILS_H_
+#define V8_APIUTILS_H_
+
+namespace v8 {
+
+class ImplementationUtilities {
+ public:
+  static v8::Handle<v8::Primitive> Undefined();
+  static v8::Handle<v8::Primitive> Null();
+  static v8::Handle<v8::Boolean> True();
+  static v8::Handle<v8::Boolean> False();
+
+  static int GetNameCount(ExtensionConfiguration* that) {
+    return that->name_count_;
+  }
+
+  static const char** GetNames(ExtensionConfiguration* that) {
+    return that->names_;
+  }
+
+  static v8::Arguments NewArguments(Local<Value> data,
+                                    Local<Object> holder,
+                                    Local<Function> callee,
+                                    bool is_construct_call,
+                                    void** argv, int argc) {
+    return v8::Arguments(data, holder, callee, is_construct_call, argv, argc);
+  }
+
+  // Introduce an alias for the handle scope data to allow non-friends
+  // to access the HandleScope data.
+  typedef v8::HandleScope::Data HandleScopeData;
+
+  static HandleScopeData* CurrentHandleScope();
+
+#ifdef DEBUG
+  static void ZapHandleRange(void** begin, void** end);
+#endif
+};
+
+}  // namespace v8
+
+#endif  // V8_APIUTILS_H_
index c49f58a9388d22996a9f3034e7b6a30323fcb482..52d3bad9fcc71e924f09781facee6af58d6c658f 100644 (file)
@@ -327,7 +327,7 @@ Handle<Object> Factory::NewReferenceError(Handle<String> message) {
 
 Handle<Object> Factory::NewError(const char* maker, const char* type,
     Vector< Handle<Object> > args) {
-  HandleScope scope;
+  v8::HandleScope scope;  // Instantiate a closeable HandleScope for EscapeFrom.
   Handle<FixedArray> array = Factory::NewFixedArray(args.length());
   for (int i = 0; i < args.length(); i++) {
     array->set(i, *args[i]);
index 0f804d7a9d07d10c173ddd367e400bdb023f4abb..e5899e3ac94f6dbe478c1530cd98df94d3430452 100644 (file)
@@ -29,6 +29,7 @@
 #ifndef V8_HANDLES_INL_H_
 #define V8_HANDLES_INL_H_
 
+#include "apiutils.h"
 #include "handles.h"
 #include "api.h"
 
@@ -51,8 +52,8 @@ inline T* Handle<T>::operator*() const {
 
 #ifdef DEBUG
 inline NoHandleAllocation::NoHandleAllocation() {
-  ImplementationUtilities::HandleScopeData* current =
-      ImplementationUtilities::CurrentHandleScope();
+  v8::ImplementationUtilities::HandleScopeData* current =
+      v8::ImplementationUtilities::CurrentHandleScope();
   extensions_ = current->extensions;
   // Shrink the current handle scope to make it impossible to do
   // handle allocations without an explicit handle scope.
@@ -64,7 +65,7 @@ inline NoHandleAllocation::NoHandleAllocation() {
 inline NoHandleAllocation::~NoHandleAllocation() {
   // Restore state in current handle scope to re-enable handle
   // allocations.
-  ImplementationUtilities::CurrentHandleScope()->extensions = extensions_;
+  v8::ImplementationUtilities::CurrentHandleScope()->extensions = extensions_;
 }
 #endif
 
index 58ba4728ebe6eb80e65c0f0b22c4b2d374197660..6f2a0447ec45fb189e64cf7bff215d024aac0132 100644 (file)
 namespace v8 { namespace internal {
 
 
+v8::ImplementationUtilities::HandleScopeData HandleScope::current_ =
+    { -1, NULL, NULL };
+
+
+int HandleScope::NumberOfHandles() {
+  int n = HandleScopeImplementer::instance()->Blocks()->length();
+  if (n == 0) return 0;
+  return ((n - 1) * kHandleBlockSize) +
+      (current_.next - HandleScopeImplementer::instance()->Blocks()->last());
+}
+
+
+void** HandleScope::CreateHandle(void* value) {
+  void** result = current_.next;
+  if (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 (current_.extensions < 0) {
+      Utils::ReportApiFailure("v8::HandleScope::CreateHandle()",
+                              "Cannot create a handle without a HandleScope");
+      return NULL;
+    }
+    HandleScopeImplementer* impl = HandleScopeImplementer::instance();
+    // If there's more room in the last block, we use that. This is used
+    // for fast creation of scopes after scope barriers.
+    if (!impl->Blocks()->is_empty()) {
+      void** limit = &impl->Blocks()->last()[kHandleBlockSize];
+      if (current_.limit != limit) {
+        current_.limit = limit;
+      }
+    }
+
+    // If we still haven't found a slot for the handle, we extend the
+    // current handle scope by allocating a new handle block.
+    if (result == current_.limit) {
+      // If there's a spare block, use it for growing the current scope.
+      result = impl->GetSpareOrNewBlock();
+      // Add the extension to the global list of blocks, but count the
+      // extension as part of the current scope.
+      impl->Blocks()->Add(result);
+      current_.extensions++;
+      current_.limit = &result[kHandleBlockSize];
+    }
+  }
+
+  // Update the current next field, set the value in the created
+  // handle, and return the result.
+  ASSERT(result < current_.limit);
+  current_.next = result + 1;
+  *result = value;
+  return result;
+}
+
+
+void HandleScope::DeleteExtensions() {
+  ASSERT(current_.extensions != 0);
+  HandleScopeImplementer::instance()->DeleteExtensions(current_.extensions);
+}
+
+
+void HandleScope::ZapRange(void** start, void** end) {
+  if (start == NULL) return;
+  for (void** p = start; p < end; p++) {
+    *p = reinterpret_cast<void*>(v8::internal::kHandleZapValue);
+  }
+}
+
+
 Handle<FixedArray> AddKeysFromJSArray(Handle<FixedArray> content,
                                       Handle<JSArray> array) {
   CALL_HEAP_FUNCTION(content->AddKeysFromJSArray(*array), FixedArray);
index ec0614b5e04c16e34ebefe3d725887da5e84d842..130af02154cd5945a73e3e5ae82183e58f6337c9 100644 (file)
 #ifndef V8_HANDLES_H_
 #define V8_HANDLES_H_
 
+#include "apiutils.h"
+
 namespace v8 { namespace internal {
 
 // ----------------------------------------------------------------------------
 // A Handle provides a reference to an object that survives relocation by
 // the garbage collector.
-// Handles are only valid withing a HandleScope.
+// Handles are only valid within a HandleScope.
 // When a handle is created for an object a cell is allocated in the heap.
 
 template<class T>
@@ -90,6 +92,75 @@ class Handle {
 };
 
 
+// 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
+// deleted or another handle scope is created.  If there is already a
+// handle scope and a new one is created, all allocations will take
+// place in the new handle scope until it is deleted.  After that,
+// new handles will again be allocated in the original handle scope.
+//
+// After the handle scope of a local handle has been deleted the
+// 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 {
+ public:
+  HandleScope() : previous_(current_) {
+    current_.extensions = 0;
+  }
+
+  ~HandleScope() {
+    Leave(&previous_);
+  }
+
+  // Counts the number of allocated handles.
+  static int NumberOfHandles();
+
+  // Creates a new handle with the given value.
+  static void** CreateHandle(void* value);
+
+ 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);
+
+  static v8::ImplementationUtilities::HandleScopeData current_;
+  const v8::ImplementationUtilities::HandleScopeData previous_;
+
+  // Pushes a fresh handle scope to be used when allocating new handles.
+  static void Enter(
+      v8::ImplementationUtilities::HandleScopeData* previous) {
+    *previous = current_;
+    current_.extensions = 0;
+  }
+
+  // Re-establishes the previous scope state. Should be called only
+  // once, and only for the current scope.
+  static void Leave(
+      const v8::ImplementationUtilities::HandleScopeData* previous) {
+    if (current_.extensions > 0) {
+      DeleteExtensions();
+    }
+    current_ = *previous;
+#ifdef DEBUG
+    ZapRange(current_.next, current_.limit);
+#endif
+  }
+
+  // Deallocates any extensions used by the current scope.
+  static void DeleteExtensions();
+
+  // Zaps the handles in the half-open interval [start, end).
+  static void ZapRange(void** start, void** end);
+
+  friend class v8::HandleScope;
+  friend class v8::ImplementationUtilities;
+};
+
+
 // ----------------------------------------------------------------------------
 // Handle operations.
 // They might invoke garbage collection. The result is an handle to
index e6a50842fef075f83bc61ac6eefa11ba9bd8a2d7..ca0ce2a542e960112a2e12df2fac80c559b24d13 100644 (file)
@@ -66,7 +66,7 @@ Handle<Object> MessageHandler::MakeMessageObject(
     Vector< Handle<Object> > args,
     Handle<String> stack_trace) {
   // Build error message object
-  HandleScope scope;
+  v8::HandleScope scope;  // Instantiate a closeable HandleScope for EscapeFrom.
   Handle<Object> type_str = Factory::LookupAsciiSymbol(type);
   Handle<Object> array = Factory::NewJSArray(args.length());
   for (int i = 0; i < args.length(); i++)
index 0a6c7c15239715669950c483bd9da2a427f6912f..46be3d31d18a623e9ca799e4d482a174dbf6c040 100644 (file)
@@ -38,9 +38,17 @@ namespace v8 {
 static internal::Thread::LocalStorageKey thread_state_key =
     internal::Thread::CreateThreadLocalKey();
 
+
+// Track whether this V8 instance has ever called v8::Locker. This allows the
+// API code to verify that the lock is always held when V8 is being entered.
+bool Locker::active_ = false;
+
+
 // Constructor for the Locker object.  Once the Locker is constructed the
 // current thread will be guaranteed to have the big V8 lock.
 Locker::Locker() : has_lock_(false), top_level_(true) {
+  // Record that the Locker has been used at least once.
+  active_ = true;
   // Get the big lock if necessary.
   if (!internal::ThreadManager::IsLockedByCurrentThread()) {
     internal::ThreadManager::Lock();
index 8adfd0e237e4f8575ddf37addc73d19d33b54439..685a86ca113d65e6bde049a620ff970bb22d381a 100644 (file)
 
 /* Begin PBXFileReference section */
                8900116B0E71CA2300F91F35 /* libraries.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = libraries.cc; sourceTree = "<group>"; };
+               893986D40F29020C007D5254 /* apiutils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = apiutils.h; sourceTree = "<group>"; };
                8944AD0E0F1D4D3A0028D560 /* regexp-stack.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "regexp-stack.cc"; sourceTree = "<group>"; };
                8944AD0F0F1D4D3A0028D560 /* regexp-stack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "regexp-stack.h"; sourceTree = "<group>"; };
                89471C7F0EB23EE400B6874B /* flag-definitions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "flag-definitions.h"; sourceTree = "<group>"; };
                                897FF0F90E719B8F00D62E90 /* allocation.h */,
                                897FF0FA0E719B8F00D62E90 /* api.cc */,
                                897FF0FB0E719B8F00D62E90 /* api.h */,
+                               893986D40F29020C007D5254 /* apiutils.h */,
                                897FF0FC0E719B8F00D62E90 /* arguments.h */,
                                897FF0FD0E719B8F00D62E90 /* assembler-arm-inl.h */,
                                897FF0FE0E719B8F00D62E90 /* assembler-arm.cc */,