From c1eff30f1f34757c6c948de3b80617934c26ab10 Mon Sep 17 00:00:00 2001 From: "yangguo@chromium.org" Date: Wed, 21 May 2014 15:00:32 +0000 Subject: [PATCH] Move promises recorded for debugging to thread local data. R=rossberg@chromium.org Review URL: https://codereview.chromium.org/296693005 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21413 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/debug.cc | 42 +++++++++++++++++++++++++++--------------- src/debug.h | 29 ++++++++++++++++++++++------- 2 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/debug.cc b/src/debug.cc index b13a163157..6cfc5001ae 100644 --- a/src/debug.cc +++ b/src/debug.cc @@ -37,8 +37,6 @@ Debug::Debug(Isolate* isolate) disable_break_(false), break_on_exception_(false), break_on_uncaught_exception_(false), - promise_catch_handlers_(0), - promise_getters_(0), isolate_(isolate) { ThreadInit(); } @@ -511,6 +509,7 @@ void Debug::ThreadInit() { thread_local_.debugger_entry_ = NULL; thread_local_.has_pending_interrupt_ = false; thread_local_.restarter_frame_function_pointer_ = NULL; + thread_local_.promise_on_stack_ = NULL; } @@ -1249,29 +1248,42 @@ bool Debug::IsBreakOnException(ExceptionBreakType type) { } +Debug::PromiseOnStack::PromiseOnStack(Isolate* isolate, + PromiseOnStack* prev, + Handle getter) + : isolate_(isolate), prev_(prev) { + handler_ = StackHandler::FromAddress( + Isolate::handler(isolate->thread_local_top())); + getter_ = Handle::cast( + isolate->global_handles()->Create(*getter)); +} + + +Debug::PromiseOnStack::~PromiseOnStack() { + isolate_->global_handles()->Destroy(Handle::cast(getter_).location()); +} + + void Debug::PromiseHandlePrologue(Handle promise_getter) { - Handle promise_getter_global = Handle::cast( - isolate_->global_handles()->Create(*promise_getter)); - StackHandler* handler = - StackHandler::FromAddress(Isolate::handler(isolate_->thread_local_top())); - promise_getters_.Add(promise_getter_global); - promise_catch_handlers_.Add(handler); + PromiseOnStack* prev = thread_local_.promise_on_stack_; + thread_local_.promise_on_stack_ = + new PromiseOnStack(isolate_, prev, promise_getter); } void Debug::PromiseHandleEpilogue() { - if (promise_catch_handlers_.length() == 0) return; - promise_catch_handlers_.RemoveLast(); - Handle promise_getter = promise_getters_.RemoveLast(); - isolate_->global_handles()->Destroy(promise_getter.location()); + 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 Debug::GetPromiseForUncaughtException() { Handle undefined = isolate_->factory()->undefined_value(); - if (promise_getters_.length() == 0) return undefined; - Handle promise_getter = promise_getters_.last(); - StackHandler* promise_catch = promise_catch_handlers_.last(); + if (thread_local_.promise_on_stack_ == NULL) return undefined; + Handle promise_getter = thread_local_.promise_on_stack_->getter(); + StackHandler* promise_catch = thread_local_.promise_on_stack_->handler(); // Find the top-most try-catch handler. StackHandler* handler = StackHandler::FromAddress( Isolate::handler(isolate_->thread_local_top())); diff --git a/src/debug.h b/src/debug.h index 9a110475dc..7956237045 100644 --- a/src/debug.h +++ b/src/debug.h @@ -519,13 +519,21 @@ class Debug { bool break_on_exception_; bool break_on_uncaught_exception_; - // When a promise is being resolved, we may want to trigger a debug event for - // the case 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 list to form a stack. - List promise_catch_handlers_; - List > promise_getters_; + class PromiseOnStack { + public: + PromiseOnStack(Isolate* isolate, + PromiseOnStack* prev, + Handle getter); + ~PromiseOnStack(); + StackHandler* handler() { return handler_; } + Handle getter() { return getter_; } + PromiseOnStack* prev() { return prev_; } + private: + Isolate* isolate_; + StackHandler* handler_; + Handle getter_; + PromiseOnStack* prev_; + }; // Per-thread data. class ThreadLocal { @@ -578,6 +586,13 @@ class Debug { // 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