Revision: 23101
Author:   [email protected]
Date:     Wed Aug 13 11:14:35 2014 UTC
Log:      Move Promise tracking from debug to isolate.

This prepares for tracking promise rejections when debugger is off.

[email protected]

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

Modified:
 /branches/bleeding_edge/src/debug.cc
 /branches/bleeding_edge/src/debug.h
 /branches/bleeding_edge/src/isolate.cc
 /branches/bleeding_edge/src/isolate.h
 /branches/bleeding_edge/src/runtime.cc
 /branches/bleeding_edge/src/v8threads.cc

=======================================
--- /branches/bleeding_edge/src/debug.cc        Mon Aug 11 07:59:10 2014 UTC
+++ /branches/bleeding_edge/src/debug.cc        Wed Aug 13 11:14:35 2014 UTC
@@ -568,7 +568,6 @@
   // TODO(isolates): frames_are_dropped_?
   thread_local_.current_debug_scope_ = NULL;
   thread_local_.restarter_frame_function_pointer_ = NULL;
-  thread_local_.promise_on_stack_ = NULL;
 }


@@ -855,9 +854,6 @@
   ClearAllBreakPoints();
   ClearStepping();

-  // Match unmatched PopPromise calls.
-  while (thread_local_.promise_on_stack_) PopPromise();
-
   // Return debugger is not loaded.
   if (!is_loaded()) return;

@@ -1270,57 +1266,6 @@
     return break_on_exception_;
   }
 }
-
-
-PromiseOnStack::PromiseOnStack(Isolate* isolate, PromiseOnStack* prev,
-                               Handle<JSObject> promise)
-    : isolate_(isolate), prev_(prev) {
-  handler_ = StackHandler::FromAddress(
-      Isolate::handler(isolate->thread_local_top()));
-  promise_ =
-      Handle<JSObject>::cast(isolate->global_handles()->Create(*promise));
-}
-
-
-PromiseOnStack::~PromiseOnStack() {
-  isolate_->global_handles()->Destroy(
-      Handle<Object>::cast(promise_).location());
-}
-
-
-void Debug::PushPromise(Handle<JSObject> promise) {
-  PromiseOnStack* prev = thread_local_.promise_on_stack_;
- thread_local_.promise_on_stack_ = new PromiseOnStack(isolate_, prev, promise);
-}
-
-
-void Debug::PopPromise() {
-  if (thread_local_.promise_on_stack_ == NULL) return;
-  PromiseOnStack* prev = thread_local_.promise_on_stack_->prev();
-  delete thread_local_.promise_on_stack_;
-  thread_local_.promise_on_stack_ = prev;
-}
-
-
-Handle<Object> Debug::GetPromiseOnStackOnThrow() {
-  Handle<Object> undefined = isolate_->factory()->undefined_value();
-  if (thread_local_.promise_on_stack_ == NULL) return undefined;
-  StackHandler* promise_try = thread_local_.promise_on_stack_->handler();
-  // Find the top-most try-catch handler.
-  StackHandler* handler = StackHandler::FromAddress(
-      Isolate::handler(isolate_->thread_local_top()));
-  do {
-    if (handler == promise_try) {
- // Mark the pushed try-catch handler to prevent a later duplicate event
-      // triggered with the following reject.
-      return thread_local_.promise_on_stack_->promise();
-    }
-    handler = handler->next();
- // Throwing inside a Promise can be intercepted by an inner try-catch, so
-    // we stop at the first try-catch handler.
-  } while (handler != NULL && !handler->is_catch());
-  return undefined;
-}


 bool Debug::PromiseHasRejectHandler(Handle<JSObject> promise) {
@@ -2567,7 +2512,7 @@
 void Debug::OnThrow(Handle<Object> exception, bool uncaught) {
   if (in_debug_scope() || ignore_events()) return;
   HandleScope scope(isolate_);
-  OnException(exception, uncaught, GetPromiseOnStackOnThrow());
+  OnException(exception, uncaught, isolate_->GetPromiseOnStackOnThrow());
 }


=======================================
--- /branches/bleeding_edge/src/debug.h Wed Aug  6 09:41:52 2014 UTC
+++ /branches/bleeding_edge/src/debug.h Wed Aug 13 11:14:35 2014 UTC
@@ -333,22 +333,6 @@
 };


-class PromiseOnStack {
- public:
-  PromiseOnStack(Isolate* isolate, PromiseOnStack* prev,
-                 Handle<JSObject> getter);
-  ~PromiseOnStack();
-  StackHandler* handler() { return handler_; }
-  Handle<JSObject> promise() { return promise_; }
-  PromiseOnStack* prev() { return prev_; }
- private:
-  Isolate* isolate_;
-  StackHandler* handler_;
-  Handle<JSObject> promise_;
-  PromiseOnStack* prev_;
-};
-
-
 // This class contains the debugger support. The main purpose is to handle
 // setting break points in the code.
 //
@@ -452,11 +436,6 @@
   // Check whether this frame is just about to return.
   bool IsBreakAtReturn(JavaScriptFrame* frame);

-  // Promise handling.
-  // Push and pop a promise and the current try-catch handler.
-  void PushPromise(Handle<JSObject> promise);
-  void PopPromise();
-
   // Support for LiveEdit
   void FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
                              LiveEdit::FrameDropMode mode,
@@ -551,7 +530,6 @@
   void ClearMirrorCache();

// Returns a promise if the pushed try-catch handler matches the current one.
-  Handle<Object> GetPromiseOnStackOnThrow();
   bool PromiseHasRejectHandler(Handle<JSObject> promise);

   void CallEventCallback(v8::DebugEvent event,
@@ -658,13 +636,6 @@
// of the pointer to function being restarted. Otherwise (most of the time)
     // stores NULL. This pointer is used with 'step in' implementation.
     Object** restarter_frame_function_pointer_;
-
- // When a promise is being resolved, we may want to trigger a debug event
-    // if we catch a throw.  For this purpose we remember the try-catch
-    // handler address that would catch the exception.  We also hold onto a
- // closure that returns a promise if the exception is considered uncaught.
-    // Due to the possibility of reentry we use a linked list.
-    PromiseOnStack* promise_on_stack_;
   };

   // Storage location for registers when handling debug break calls
=======================================
--- /branches/bleeding_edge/src/isolate.cc      Wed Aug  6 16:56:52 2014 UTC
+++ /branches/bleeding_edge/src/isolate.cc      Wed Aug 13 11:14:35 2014 UTC
@@ -79,6 +79,7 @@
   save_context_ = NULL;
   catcher_ = NULL;
   top_lookup_result_ = NULL;
+  promise_on_stack_ = NULL;

   // These members are re-initialized later after deserialization
   // is complete.
@@ -98,6 +99,12 @@
 #endif
   thread_id_ = ThreadId::Current();
 }
+
+
+void ThreadLocalTop::Free() {
+  // Match unmatched PopPromise calls.
+  while (promise_on_stack_) isolate_->PopPromise();
+}


 base::Thread::LocalStorageKey Isolate::isolate_key_;
@@ -1287,6 +1294,48 @@
   clear_pending_exception();
   return true;
 }
+
+
+void Isolate::PushPromise(Handle<JSObject> promise) {
+  ThreadLocalTop* tltop = thread_local_top();
+  PromiseOnStack* prev = tltop->promise_on_stack_;
+ StackHandler* handler = StackHandler::FromAddress(Isolate::handler(tltop));
+  Handle<JSObject> global_handle =
+      Handle<JSObject>::cast(global_handles()->Create(*promise));
+ tltop->promise_on_stack_ = new PromiseOnStack(handler, global_handle, prev);
+}
+
+
+void Isolate::PopPromise() {
+  ThreadLocalTop* tltop = thread_local_top();
+  if (tltop->promise_on_stack_ == NULL) return;
+  PromiseOnStack* prev = tltop->promise_on_stack_->prev();
+  Handle<Object> global_handle = tltop->promise_on_stack_->promise();
+  delete tltop->promise_on_stack_;
+  tltop->promise_on_stack_ = prev;
+  global_handles()->Destroy(global_handle.location());
+}
+
+
+Handle<Object> Isolate::GetPromiseOnStackOnThrow() {
+  Handle<Object> undefined = factory()->undefined_value();
+  ThreadLocalTop* tltop = thread_local_top();
+  if (tltop->promise_on_stack_ == NULL) return undefined;
+  StackHandler* promise_try = tltop->promise_on_stack_->handler();
+  // Find the top-most try-catch handler.
+ StackHandler* handler = StackHandler::FromAddress(Isolate::handler(tltop));
+  do {
+    if (handler == promise_try) {
+ // Mark the pushed try-catch handler to prevent a later duplicate event
+      // triggered with the following reject.
+      return tltop->promise_on_stack_->promise();
+    }
+    handler = handler->next();
+ // Throwing inside a Promise can be intercepted by an inner try-catch, so
+    // we stop at the first try-catch handler.
+  } while (handler != NULL && !handler->is_catch());
+  return undefined;
+}


 void Isolate::SetCaptureStackTraceForUncaughtExceptions(
@@ -1552,6 +1601,8 @@

     debug()->Unload();

+    FreeThreadResources();
+
     if (concurrent_recompilation_enabled()) {
       optimizing_compiler_thread_->Stop();
       delete optimizing_compiler_thread_;
=======================================
--- /branches/bleeding_edge/src/isolate.h       Wed Aug  6 16:56:52 2014 UTC
+++ /branches/bleeding_edge/src/isolate.h       Wed Aug 13 11:14:35 2014 UTC
@@ -78,6 +78,7 @@

 class Debug;
 class Debugger;
+class PromiseOnStack;

 #if !defined(__arm__) && V8_TARGET_ARCH_ARM || \
     !defined(__aarch64__) && V8_TARGET_ARCH_ARM64 || \
@@ -240,11 +241,7 @@
         v8::TryCatch::JSStackComparableAddress(try_catch_handler()));
   }

-  void Free() {
-    DCHECK(!has_pending_message_);
-    DCHECK(!external_caught_exception_);
-    DCHECK(try_catch_handler_ == NULL);
-  }
+  void Free();

   Isolate* isolate_;
// The context where the current execution method is created and for variable
@@ -270,6 +267,11 @@
   Address c_entry_fp_;  // the frame pointer of the top c entry frame
   Address handler_;   // try-blocks are chained through the stack

+  // Throwing an exception may cause a Promise rejection.  For this purpose
+  // we keep track of a stack of nested promises and the corresponding
+  // try-catch handlers.
+  PromiseOnStack* promise_on_stack_;
+
 #ifdef USE_SIMULATOR
   Simulator* simulator_;
 #endif
@@ -676,6 +678,11 @@
   // JavaScript code.  If an exception is scheduled true is returned.
   bool OptionalRescheduleException(bool is_bottom_call);

+  // Push and pop a promise and the current try-catch handler.
+  void PushPromise(Handle<JSObject> promise);
+  void PopPromise();
+  Handle<Object> GetPromiseOnStackOnThrow();
+
   class ExceptionScope {
    public:
     explicit ExceptionScope(Isolate* isolate) :
@@ -1349,6 +1356,22 @@
 #undef THREAD_LOCAL_TOP_ACCESSOR


+class PromiseOnStack {
+ public:
+  PromiseOnStack(StackHandler* handler, Handle<JSObject> promise,
+                 PromiseOnStack* prev)
+      : handler_(handler), promise_(promise), prev_(prev) {}
+  StackHandler* handler() { return handler_; }
+  Handle<JSObject> promise() { return promise_; }
+  PromiseOnStack* prev() { return prev_; }
+
+ private:
+  StackHandler* handler_;
+  Handle<JSObject> promise_;
+  PromiseOnStack* prev_;
+};
+
+
 // If the GCC version is 4.1.x or 4.2.x an additional field is added to the
 // class as a work around for a bug in the generated code found with these
 // versions of GCC. See V8 issue 122 for details.
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Tue Aug 12 15:28:20 2014 UTC
+++ /branches/bleeding_edge/src/runtime.cc      Wed Aug 13 11:14:35 2014 UTC
@@ -5495,7 +5495,7 @@
   DCHECK(args.length() == 1);
   HandleScope scope(isolate);
   CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
-  isolate->debug()->PushPromise(promise);
+  isolate->PushPromise(promise);
   return isolate->heap()->undefined_value();
 }

@@ -5503,7 +5503,7 @@
 RUNTIME_FUNCTION(Runtime_DebugPopPromise) {
   DCHECK(args.length() == 0);
   SealHandleScope shs(isolate);
-  isolate->debug()->PopPromise();
+  isolate->PopPromise();
   return isolate->heap()->undefined_value();
 }

=======================================
--- /branches/bleeding_edge/src/v8threads.cc    Mon Aug  4 11:34:54 2014 UTC
+++ /branches/bleeding_edge/src/v8threads.cc    Wed Aug 13 11:14:35 2014 UTC
@@ -307,6 +307,9 @@


 void ThreadManager::FreeThreadResources() {
+  DCHECK(!isolate_->has_pending_exception());
+  DCHECK(!isolate_->external_caught_exception());
+  DCHECK(isolate_->try_catch_handler() == NULL);
   isolate_->handle_scope_implementer()->FreeThreadResources();
   isolate_->FreeThreadResources();
   isolate_->debug()->FreeThreadResources();

--
--
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/d/optout.

Reply via email to