Index: src/top.cc |
diff --git a/src/top.cc b/src/top.cc |
index e32eb6bc8b2677b64db262582b9c48c112d4033b..6b85af268c8cf5e07a78b17bbf365e15b29af726 100644 |
--- a/src/top.cc |
+++ b/src/top.cc |
@@ -924,38 +924,62 @@ void Top::DoThrow(MaybeObject* exception, |
} |
+void Top::PropagatePendingExceptionToExteranlTryCatch() { |
+ ASSERT(has_pending_exception()); |
+ |
+ if (!thread_local_.external_caught_exception_) return; |
+ |
+ if (thread_local_.pending_exception_ == Failure::OutOfMemoryException()) { |
+ // Do not propagate OOM exception: we should kill VM asap. |
+ } else if (thread_local_.pending_exception_ == |
+ Heap::termination_exception()) { |
+ thread_local_.TryCatchHandler()->can_continue_ = false; |
Vitaly Repeshko
2011/01/28 14:03:33
try_catch_handler() is a nicer alias for thread_lo
antonm
2011/01/28 14:43:18
Done.
|
+ thread_local_.TryCatchHandler()->exception_ = Heap::null_value(); |
+ } else { |
+ // At this point all non-object (failure) exceptions have |
+ // been dealt with so this shouldn't fail. |
+ Object* pending_exception_object = pending_exception()->ToObjectUnchecked(); |
+ Handle<Object> exception(pending_exception_object); |
Vitaly Repeshko
2011/01/28 14:03:33
Unused? If it is intended to be used, shouldn't we
antonm
2011/01/28 14:43:18
Thanks a lot, indeed unused.
|
+ thread_local_.TryCatchHandler()->can_continue_ = true; |
+ thread_local_.TryCatchHandler()->exception_ = |
+ thread_local_.pending_exception_; |
+ if (!thread_local_.pending_message_obj_->IsTheHole()) { |
+ try_catch_handler()->message_ = thread_local_.pending_message_obj_; |
+ } |
+ } |
+} |
+ |
+ |
void Top::ReportPendingMessages() { |
Vitaly Repeshko
2011/01/28 14:03:33
It reports only a single message, doesn't it? Drop
antonm
2011/01/28 14:43:18
I don't know. Let's investigate it later.
|
ASSERT(has_pending_exception()); |
setup_external_caught(); |
Vitaly Repeshko
2011/01/28 14:03:33
This looks slightly backwards: one function sets a
antonm
2011/01/28 14:43:18
I don't want to rework the things too much. I agr
|
+ PropagatePendingExceptionToExteranlTryCatch(); |
+ |
+ bool external_caught = thread_local_.external_caught_exception_; |
// 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_; |
- 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(); |
- } |
+ // Do nothing: if needed, the exception has been already propagated to |
+ // v8::TryCatch. |
} else { |
- // At this point all non-object (failure) exceptions have |
- // been dealt with so this shouldn't fail. |
- Object* pending_exception_object = pending_exception()->ToObjectUnchecked(); |
- 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_; |
- if (!thread_local_.pending_message_obj_->IsTheHole()) { |
- try_catch_handler()->message_ = thread_local_.pending_message_obj_; |
- } |
- } |
if (thread_local_.has_pending_message_) { |
Vitaly Repeshko
2011/01/28 14:03:33
Join with "else" above?
antonm
2011/01/28 14:43:18
I'd like to keep identical structure of failure an
|
+ HandleScope scope; |
+ |
+ // At this point all non-object (failure) exceptions have |
+ // been dealt with so this shouldn't fail. |
+ Object* pending_exception_obj = pending_exception()->ToObjectUnchecked(); |
+ // Message reporting executes arbitrary embedder's code and hence |
+ // we need to save this state. |
+ // TODO(antonm): consider saving the whole thread_local_. |
Vitaly Repeshko
2011/01/28 14:03:33
I don't think we should save the whole thread loca
antonm
2011/01/28 14:43:18
Yep, that's why I left it as todo (there is this f
|
+ Handle<Object> exception(pending_exception_obj); |
+ thread_local_.external_caught_exception_ = false; |
+ v8::TryCatch* former_catcher = thread_local_.catcher_; |
+ |
Mads Ager (chromium)
2011/01/28 11:39:18
Clear pending exception here instead of in ReportM
antonm
2011/01/28 13:37:25
See above.
Vitaly Repeshko
2011/01/28 14:03:33
I agree. This logic should be all moved here.
antonm
2011/01/28 14:43:18
See patch 2.
|
thread_local_.has_pending_message_ = false; |
if (thread_local_.pending_message_ != NULL) { |
MessageHandler::ReportMessage(thread_local_.pending_message_); |
@@ -971,9 +995,12 @@ void Top::ReportPendingMessages() { |
MessageHandler::ReportMessage(NULL, message_obj); |
} |
} |
+ |
+ // Restore previously saved state. |
+ thread_local_.catcher_ = former_catcher; |
+ thread_local_.external_caught_exception_ = external_caught; |
+ set_pending_exception(*exception); |
} |
- thread_local_.external_caught_exception_ = external_caught; |
- set_pending_exception(*exception); |
} |
clear_pending_message(); |
} |
@@ -985,6 +1012,9 @@ void Top::TraceException(bool flag) { |
bool Top::OptionalRescheduleException(bool is_bottom_call) { |
+ setup_external_caught(); |
+ PropagatePendingExceptionToExteranlTryCatch(); |
+ |
// Allways reschedule out of memory exceptions. |
if (!is_out_of_memory()) { |
bool is_termination_exception = |