Chromium Code Reviews| Index: src/top.cc |
| diff --git a/src/top.cc b/src/top.cc |
| index 3364c0d511c92b1b2c50fba0c9873a8ea571c3a3..3761767cee5160898f07b6fb28794b3bb1278471 100644 |
| --- a/src/top.cc |
| +++ b/src/top.cc |
| @@ -333,7 +333,7 @@ void Top::RegisterTryCatchHandler(v8::TryCatch* that) { |
| void Top::UnregisterTryCatchHandler(v8::TryCatch* that) { |
| - ASSERT(thread_local_.TryCatchHandler() == that); |
| + ASSERT(try_catch_handler() == that); |
| thread_local_.set_try_catch_handler_address( |
| reinterpret_cast<Address>(that->next_)); |
| thread_local_.catcher_ = NULL; |
| @@ -732,6 +732,13 @@ Failure* Top::Throw(Object* exception, MessageLocation* location) { |
| Failure* Top::ReThrow(MaybeObject* exception, MessageLocation* location) { |
| + bool can_be_caught_externally = false; |
| + ShouldReportException(&can_be_caught_externally, |
| + is_catchable_by_javascript(exception)); |
| + if (can_be_caught_externally) { |
| + thread_local_.catcher_ = try_catch_handler(); |
| + } |
| + |
| // Set the exception being re-thrown. |
| set_pending_exception(exception); |
| return Failure::Exception(); |
| @@ -807,7 +814,7 @@ void Top::ComputeLocation(MessageLocation* target) { |
| } |
| -bool Top::ShouldReportException(bool* is_caught_externally, |
| +bool Top::ShouldReportException(bool* can_be_caught_externally, |
| bool catchable_by_javascript) { |
| // Find the top-most try-catch handler. |
| StackHandler* handler = |
| @@ -823,13 +830,13 @@ bool Top::ShouldReportException(bool* is_caught_externally, |
| // The exception has been externally caught if and only if there is |
| // an external handler which is on top of the top-most try-catch |
| // handler. |
| - *is_caught_externally = external_handler_address != NULL && |
| + *can_be_caught_externally = external_handler_address != NULL && |
| (handler == NULL || handler->address() > external_handler_address || |
| !catchable_by_javascript); |
| - if (*is_caught_externally) { |
| + if (*can_be_caught_externally) { |
| // Only report the exception if the external handler is verbose. |
| - return thread_local_.TryCatchHandler()->is_verbose_; |
| + return try_catch_handler()->is_verbose_; |
| } else { |
| // Report the exception if it isn't caught by JavaScript code. |
| return handler == NULL; |
| @@ -848,14 +855,12 @@ void Top::DoThrow(MaybeObject* exception, |
| Handle<Object> exception_handle(exception_object); |
| // Determine reporting and whether the exception is caught externally. |
| - bool is_out_of_memory = exception == Failure::OutOfMemoryException(); |
| - bool is_termination_exception = exception == Heap::termination_exception(); |
| - bool catchable_by_javascript = !is_termination_exception && !is_out_of_memory; |
| + bool catchable_by_javascript = is_catchable_by_javascript(exception); |
| // Only real objects can be caught by JS. |
| ASSERT(!catchable_by_javascript || is_object); |
| - bool is_caught_externally = false; |
| + bool can_be_caught_externally = false; |
| bool should_report_exception = |
| - ShouldReportException(&is_caught_externally, catchable_by_javascript); |
| + ShouldReportException(&can_be_caught_externally, catchable_by_javascript); |
| bool report_exception = catchable_by_javascript && should_report_exception; |
| #ifdef ENABLE_DEBUGGER_SUPPORT |
| @@ -869,8 +874,8 @@ void Top::DoThrow(MaybeObject* exception, |
| Handle<Object> message_obj; |
| MessageLocation potential_computed_location; |
| bool try_catch_needs_message = |
| - is_caught_externally && |
| - thread_local_.TryCatchHandler()->capture_message_; |
| + can_be_caught_externally && |
| + try_catch_handler()->capture_message_; |
| if (report_exception || try_catch_needs_message) { |
| if (location == NULL) { |
| // If no location was specified we use a computed one instead |
| @@ -908,8 +913,8 @@ void Top::DoThrow(MaybeObject* exception, |
| } |
| } |
| - if (is_caught_externally) { |
| - thread_local_.catcher_ = thread_local_.TryCatchHandler(); |
| + if (can_be_caught_externally) { |
| + thread_local_.catcher_ = try_catch_handler(); |
| } |
| // NOTE: Notifying the debugger or generating the message |
| @@ -925,22 +930,59 @@ void Top::DoThrow(MaybeObject* exception, |
| } |
| +bool Top::IsExternallyCaught() { |
| + ASSERT(has_pending_exception()); |
| + |
| + if ((thread_local_.catcher_ == NULL) || |
| + (try_catch_handler() != thread_local_.catcher_)) { |
| + // When throwing the exception, we found no or another v8::TryCatch |
|
Mads Ager (chromium)
2011/02/16 09:17:49
no or another -> no
antonm
2011/02/16 11:40:44
Done.
|
| + // which should care about this exception. |
| + return false; |
| + } |
| + |
| + if (!is_catchable_by_javascript(pending_exception())) { |
| + return true; |
| + } |
| + |
| + // Get the address of the external handler so we can compare the address to |
| + // determine which one is closer to the top of the stack. |
| + Address external_handler_address = thread_local_.try_catch_handler_address(); |
| + ASSERT(external_handler_address != NULL); |
| + |
| + // The exception has been externally caught if and only if there is |
| + // an external handler which is on top of the top-most try-finally |
| + // handler. |
| + // There should be no try-catch blocks as they would prohibit us from |
| + // finding external catcher in the first place. |
| + StackHandler* handler = |
| + StackHandler::FromAddress(Top::handler(Top::GetCurrentThread())); |
| + while (handler != NULL && handler->address() < external_handler_address) { |
| + ASSERT(!handler->is_try_catch()); |
| + if (handler->is_try_finally()) return false; |
|
Mads Ager (chromium)
2011/02/16 09:17:49
In cases where the exception is propagated from th
antonm
2011/02/16 11:40:44
Done.
|
| + |
| + handler = handler->next(); |
| + } |
| + |
| + return true; |
| +} |
| + |
| + |
| void Top::ReportPendingMessages() { |
| ASSERT(has_pending_exception()); |
| - setup_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 |
| // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to |
| // set it. |
| - bool external_caught = thread_local_.external_caught_exception_; |
| + bool external_caught = IsExternallyCaught(); |
| + thread_local_.external_caught_exception_ = external_caught; |
| HandleScope scope; |
| if (thread_local_.pending_exception_ == Failure::OutOfMemoryException()) { |
| context()->mark_out_of_memory(); |
| } else if (thread_local_.pending_exception_ == |
| Heap::termination_exception()) { |
| if (external_caught) { |
| - thread_local_.TryCatchHandler()->can_continue_ = false; |
| - thread_local_.TryCatchHandler()->exception_ = Heap::null_value(); |
| + try_catch_handler()->can_continue_ = false; |
| + try_catch_handler()->exception_ = Heap::null_value(); |
| } |
| } else { |
| // At this point all non-object (failure) exceptions have |
| @@ -949,9 +991,8 @@ void Top::ReportPendingMessages() { |
| Handle<Object> exception(pending_exception_object); |
| thread_local_.external_caught_exception_ = false; |
| if (external_caught) { |
| - thread_local_.TryCatchHandler()->can_continue_ = true; |
| - thread_local_.TryCatchHandler()->exception_ = |
| - thread_local_.pending_exception_; |
| + try_catch_handler()->can_continue_ = true; |
| + try_catch_handler()->exception_ = thread_local_.pending_exception_; |
| if (!thread_local_.pending_message_obj_->IsTheHole()) { |
| try_catch_handler()->message_ = thread_local_.pending_message_obj_; |
| } |