| Index: src/top.cc | 
| diff --git a/src/top.cc b/src/top.cc | 
| index 3364c0d511c92b1b2c50fba0c9873a8ea571c3a3..83d7de3afee6a43904ed7182cb7d75b8883bdad7 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,63 @@ 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 v8::TryCatch | 
| +    // 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 (see catcher_ check above). | 
| +  // | 
| +  // Note, that finally clause would rethrow an exception unless it's | 
| +  // aborted by jumps in control flow like return, break, etc. and we'll | 
| +  // have another chances to set proper v8::TryCatch. | 
| +  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; | 
| + | 
| +    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 +995,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_; | 
| } | 
|  |