Revision: 16965
Author:   [email protected]
Date:     Thu Sep 26 13:46:37 2013 UTC
Log: Add EscapableHandleScope to api to fix problems with HandleScope::Close

[email protected]
BUG=

Review URL: https://codereview.chromium.org/24245005
http://code.google.com/p/v8/source/detail?r=16965

Modified:
 /branches/bleeding_edge/include/v8.h
 /branches/bleeding_edge/src/api.cc
 /branches/bleeding_edge/test/cctest/test-api.cc

=======================================
--- /branches/bleeding_edge/include/v8.h        Thu Sep 26 13:31:19 2013 UTC
+++ /branches/bleeding_edge/include/v8.h        Thu Sep 26 13:46:37 2013 UTC
@@ -135,6 +135,7 @@
 class ObjectOperationDescriptor;
 class RawOperationDescriptor;
 class CallHandlerHelper;
+class EscapableHandleScope;

 namespace internal {
 class Arguments;
@@ -401,6 +402,7 @@
   friend class Context;
   template<class F> friend class internal::CustomArguments;
   friend class HandleScope;
+  friend class EscapableHandleScope;

   V8_INLINE static Local<T> New(Isolate* isolate, T* that);
 };
@@ -773,10 +775,7 @@

   ~HandleScope();

-  /**
-   * Closes the handle scope and returns the value as a handle in the
-   * previous scope, which is the new current scope after the call.
-   */
+  // TODO(dcarney): deprecated - use EscapableHandleScope::Escape.
   template <class T> Local<T> Close(Handle<T> value);

   /**
@@ -794,6 +793,9 @@
   static internal::Object** CreateHandle(internal::HeapObject* value);

  private:
+  V8_INLINE HandleScope() {}
+  void Initialize(Isolate* isolate);
+
   // Make it hard to create heap-allocated or illegal handle scopes by
   // disallowing certain operations.
   HandleScope(const HandleScope&);
@@ -814,19 +816,47 @@
     }
   };

-  void Initialize(Isolate* isolate);
   void Leave();

   internal::Isolate* isolate_;
   internal::Object** prev_next_;
   internal::Object** prev_limit_;

+  // TODO(dcarney): remove this field
// 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_;
   internal::Object** RawClose(internal::Object** value);

   friend class ImplementationUtilities;
+  friend class EscapableHandleScope;
+};
+
+
+/**
+ * A HandleScope which first allocates a handle in the current scope
+ * which will be later filled with the escape value.
+ */
+class V8_EXPORT EscapableHandleScope : public HandleScope {
+ public:
+  EscapableHandleScope(Isolate* isolate);
+  V8_INLINE ~EscapableHandleScope() {}
+
+  /**
+   * Pushes the value into the previous scope and returns a handle to it.
+   * Cannot be called twice.
+   */
+  template <class T>
+  V8_INLINE Local<T> Escape(Local<T> value) {
+    internal::Object** slot =
+        Escape(reinterpret_cast<internal::Object**>(*value));
+    return Local<T>(reinterpret_cast<T*>(slot));
+  }
+
+ private:
+  internal::Object** Escape(internal::Object** escape_value);
+
+  internal::Object** escape_slot_;
 };


=======================================
--- /branches/bleeding_edge/src/api.cc  Thu Sep 26 09:40:13 2013 UTC
+++ /branches/bleeding_edge/src/api.cc  Thu Sep 26 13:46:37 2013 UTC
@@ -699,6 +699,26 @@
   return reinterpret_cast<i::Object**>(
       i::HandleScope::CreateHandle(value->GetIsolate(), value));
 }
+
+
+EscapableHandleScope::EscapableHandleScope(Isolate* v8_isolate) {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
+  escape_slot_ = CreateHandle(isolate, isolate->heap()->the_hole_value());
+  Initialize(v8_isolate);
+}
+
+
+i::Object** EscapableHandleScope::Escape(i::Object** escape_value) {
+  ApiCheck(*escape_slot_ == isolate_->heap()->the_hole_value(),
+           "EscapeableHandleScope::Escape",
+           "Escape value set twice");
+  if (escape_value == NULL) {
+    *escape_slot_ = isolate_->heap()->undefined_value();
+    return NULL;
+  }
+  *escape_slot_ = *escape_value;
+  return escape_slot_;
+}


 void Context::Enter() {
=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc Thu Sep 26 08:21:48 2013 UTC +++ /branches/bleeding_edge/test/cctest/test-api.cc Thu Sep 26 13:46:37 2013 UTC
@@ -20593,3 +20593,24 @@
   CHECK_EQ(v8::Integer::New(17, isolate), result2);
 }

+
+TEST(EscapeableHandleScope) {
+  HandleScope outer_scope(CcTest::isolate());
+  LocalContext context;
+  const int runs = 10;
+  Local<String> values[runs];
+  for (int i = 0; i < runs; i++) {
+    v8::EscapableHandleScope inner_scope(CcTest::isolate());
+    Local<String> value;
+    if (i != 0) value = v8_str("escape value");
+    values[i] = inner_scope.Escape(value);
+  }
+  for (int i = 0; i < runs; i++) {
+    Local<String> expected;
+    if (i != 0) {
+      CHECK_EQ(v8_str("escape value"), values[i]);
+    } else {
+      CHECK(values[i].IsEmpty());
+    }
+  }
+}

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to