diff --git a/src/execution.cc b/src/execution.cc index 0598ad718f..03541a8f3a 100644 --- a/src/execution.cc +++ b/src/execution.cc @@ -91,12 +91,10 @@ static Handle Invoke(bool construct, value->Verify(); #endif - // Update the pending exception flag and return the value. + // Update the pending exception and external caught flag and return the value. *has_pending_exception = value->IsException(); ASSERT(*has_pending_exception == Top::has_pending_exception()); - if (*has_pending_exception) { - Top::setup_external_caught(); - } + Top::propagate_external_caught(); // If the pending exception is OutOfMemoryException set out_of_memory in // the global context. Note: We have to mark the global context here diff --git a/src/top.cc b/src/top.cc index a78ba32b57..8df808e561 100644 --- a/src/top.cc +++ b/src/top.cc @@ -101,7 +101,7 @@ void Top::InitializeThreadLocal() { clear_pending_exception(); clear_scheduled_exception(); thread_local_.save_context_ = NULL; - thread_local_.catcher_ = NULL; + thread_local_.pending_external_caught_exception_ = false; } @@ -607,7 +607,7 @@ Failure* Top::Throw(Object* exception, MessageLocation* location) { Failure* Top::ReThrow(Object* exception, MessageLocation* location) { - // Set the exception beeing re-thrown. + // Set the exception being re-thrown. set_pending_exception(exception); return Failure::Exception(); } @@ -789,9 +789,8 @@ void Top::DoThrow(Object* exception, // If the exception is caught externally, we store it in the // try/catch handler. The C code can find it later and process it if // necessary. - thread_local_.catcher_ = NULL; + thread_local_.pending_external_caught_exception_ = is_caught_externally; if (is_caught_externally) { - thread_local_.catcher_ = thread_local_.try_catch_handler_; thread_local_.try_catch_handler_->exception_ = reinterpret_cast(*exception_handle); if (!message_obj.is_null()) { diff --git a/src/top.h b/src/top.h index 866487c835..69fb7fa6c7 100644 --- a/src/top.h +++ b/src/top.h @@ -53,7 +53,9 @@ class ThreadLocalTop BASE_EMBEDDED { bool external_caught_exception_; v8::TryCatch* try_catch_handler_; SaveContext* save_context_; - v8::TryCatch* catcher_; + // Flag indicating that the try_catch_handler_ contains an exception to be + // caught. + bool pending_external_caught_exception_; // Stack. Address c_entry_fp_; // the frame pointer of the top c entry frame @@ -144,10 +146,16 @@ class Top { thread_local_.scheduled_exception_ = Heap::the_hole_value(); } - static void setup_external_caught() { - thread_local_.external_caught_exception_ = - (thread_local_.catcher_ != NULL) && - (Top::thread_local_.try_catch_handler_ == Top::thread_local_.catcher_); + // Propagate the external caught exception flag. If there is no external + // caught exception always clear the TryCatch handler as it might contain + // an exception object from a throw which was bypassed by a finally block + // doing an explicit return/break/continue. + static void propagate_external_caught() { + if (has_pending_exception()) { + thread_local_.external_caught_exception_ = + thread_local_.pending_external_caught_exception_; + } + thread_local_.pending_external_caught_exception_ = false; } // Tells whether the current context has experienced an out of memory