| Index: src/isolate.cc
|
| diff --git a/src/isolate.cc b/src/isolate.cc
|
| index 82af337d905f15b4bcda189453e8708bae85956f..500f01689f5a612be3fcd3cc27a4b4aef74fc367 100644
|
| --- a/src/isolate.cc
|
| +++ b/src/isolate.cc
|
| @@ -461,6 +461,9 @@ void Isolate::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
|
| v->VisitPointer(&pending);
|
| thread->pending_exception_ = pending; // In case GC updated it.
|
| }
|
| +
|
| + v->VisitPointer(&(thread->last_traced_exception_));
|
| + v->VisitPointer(BitCast<Object**>(&(thread->last_stack_trace_)));
|
| v->VisitPointer(&(thread->pending_message_obj_));
|
| v->VisitPointer(BitCast<Object**>(&(thread->pending_message_script_)));
|
| v->VisitPointer(BitCast<Object**>(&(thread->context_)));
|
| @@ -1053,6 +1056,11 @@ void Isolate::DoThrow(MaybeObject* exception, MessageLocation* location) {
|
| bool should_report_exception =
|
| ShouldReportException(&can_be_caught_externally, catchable_by_javascript);
|
| bool report_exception = catchable_by_javascript && should_report_exception;
|
| + bool try_catch_needs_message =
|
| + can_be_caught_externally && try_catch_handler()->capture_message_;
|
| + bool exception_rethrown =
|
| + (thread_local_top_.last_traced_exception_ == exception_object);
|
| + bool bootstrapping = bootstrapper()->IsActive();
|
|
|
| #ifdef ENABLE_DEBUGGER_SUPPORT
|
| // Notify debugger of exception.
|
| @@ -1061,34 +1069,49 @@ void Isolate::DoThrow(MaybeObject* exception, MessageLocation* location) {
|
| }
|
| #endif
|
|
|
| - // Generate the message.
|
| + // Generate message.
|
| Handle<Object> message_obj;
|
| - MessageLocation potential_computed_location;
|
| - bool try_catch_needs_message =
|
| - can_be_caught_externally &&
|
| - try_catch_handler()->capture_message_;
|
| + Handle<JSArray> stack_trace_object;
|
| + if (capture_stack_trace_for_uncaught_exceptions_ && !bootstrapping) {
|
| + if (exception_rethrown) {
|
| + // We already have the stack trace for this exception.
|
| + stack_trace_object = Handle<JSArray>(thread_local_top_.last_stack_trace_);
|
| + } else {
|
| + // Hang on to this exception and its stack trace even if it's not an
|
| + // uncaught exception just in case it is rethrown later.
|
| + stack_trace_object = CaptureCurrentStackTrace(
|
| + stack_trace_for_uncaught_exceptions_frame_limit_,
|
| + stack_trace_for_uncaught_exceptions_options_);
|
| + thread_local_top_.last_traced_exception_ = exception_object;
|
| + thread_local_top_.last_stack_trace_ = *stack_trace_object;
|
| + }
|
| + }
|
| +
|
| if (report_exception || try_catch_needs_message) {
|
| + MessageLocation potential_computed_location;
|
| if (location == NULL) {
|
| - // If no location was specified we use a computed one instead
|
| + // If no location was specified we use a computed one instead.
|
| ComputeLocation(&potential_computed_location);
|
| location = &potential_computed_location;
|
| }
|
| - if (!bootstrapper()->IsActive()) {
|
| - // It's not safe to try to make message objects or collect stack
|
| - // traces while the bootstrapper is active since the infrastructure
|
| - // may not have been properly initialized.
|
| + // It's not safe to try to make message objects or collect stack traces
|
| + // while the bootstrapper is active since the infrastructure may not have
|
| + // been properly initialized.
|
| + if (!bootstrapping) {
|
| Handle<String> stack_trace;
|
| if (FLAG_trace_exception) stack_trace = StackTraceString();
|
| - Handle<JSArray> stack_trace_object;
|
| - if (report_exception && capture_stack_trace_for_uncaught_exceptions_) {
|
| - stack_trace_object = CaptureCurrentStackTrace(
|
| - stack_trace_for_uncaught_exceptions_frame_limit_,
|
| - stack_trace_for_uncaught_exceptions_options_);
|
| - }
|
| - ASSERT(is_object); // Can't use the handle unless there's a real object.
|
| - message_obj = MessageHandler::MakeMessageObject("uncaught_exception",
|
| - location, HandleVector<Object>(&exception_handle, 1), stack_trace,
|
| + message_obj = MessageHandler::MakeMessageObject(
|
| + "uncaught_exception",
|
| + location,
|
| + HandleVector<Object>(&exception_handle, 1),
|
| + stack_trace,
|
| stack_trace_object);
|
| + thread_local_top()->pending_message_obj_ = *message_obj;
|
| + if (location != NULL) {
|
| + thread_local_top()->pending_message_script_ = *location->script();
|
| + thread_local_top()->pending_message_start_pos_ = location->start_pos();
|
| + thread_local_top()->pending_message_end_pos_ = location->end_pos();
|
| + }
|
| } else if (location != NULL && !location->script().is_null()) {
|
| // We are bootstrapping and caught an error where the location is set
|
| // and we have a script for the location.
|
| @@ -1104,14 +1127,6 @@ void Isolate::DoThrow(MaybeObject* exception, MessageLocation* location) {
|
|
|
| // Save the message for reporting if the the exception remains uncaught.
|
| thread_local_top()->has_pending_message_ = report_exception;
|
| - if (!message_obj.is_null()) {
|
| - thread_local_top()->pending_message_obj_ = *message_obj;
|
| - if (location != NULL) {
|
| - thread_local_top()->pending_message_script_ = *location->script();
|
| - thread_local_top()->pending_message_start_pos_ = location->start_pos();
|
| - thread_local_top()->pending_message_end_pos_ = location->end_pos();
|
| - }
|
| - }
|
|
|
| // Do not forget to clean catcher_ if currently thrown exception cannot
|
| // be caught. If necessary, ReThrow will update the catcher.
|
| @@ -1814,6 +1829,7 @@ bool Isolate::Init(Deserializer* des) {
|
|
|
| // Finish initialization of ThreadLocal after deserialization is done.
|
| clear_pending_exception();
|
| + clear_last_stack_trace();
|
| clear_pending_message();
|
| clear_scheduled_exception();
|
|
|
|
|