Index: src/isolate.cc |
diff --git a/src/isolate.cc b/src/isolate.cc |
index 2e94828aaad41b10f2d4cf1e3d907f3a2a54525d..5518f008e91a25470c452d660ea1054276210a49 100644 |
--- a/src/isolate.cc |
+++ b/src/isolate.cc |
@@ -80,6 +80,10 @@ int ThreadId::GetCurrentThreadId() { |
ThreadLocalTop::ThreadLocalTop() { |
InitializeInternal(); |
+ // This flag may be set using v8::V8::IgnoreOutOfMemoryException() |
+ // before an isolate is initialized. The initialize methods below do |
+ // not touch it to preserve its value. |
+ ignore_out_of_memory_ = false; |
} |
@@ -1269,8 +1273,14 @@ void Isolate::ReportPendingMessages() { |
ASSERT(has_pending_exception()); |
PropagatePendingExceptionToExternalTryCatch(); |
+ // If the pending exception is OutOfMemoryException set out_of_memory in |
+ // the native context. Note: We have to mark the native context here |
+ // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to |
+ // set it. |
HandleScope scope(this); |
- if (thread_local_top_.pending_exception_ == |
+ if (thread_local_top_.pending_exception_->IsOutOfMemory()) { |
+ context()->mark_out_of_memory(); |
+ } else if (thread_local_top_.pending_exception_ == |
heap()->termination_exception()) { |
// Do nothing: if needed, the exception has been already propagated to |
// v8::TryCatch. |
@@ -1301,7 +1311,8 @@ void Isolate::ReportPendingMessages() { |
MessageLocation Isolate::GetMessageLocation() { |
ASSERT(has_pending_exception()); |
- if (thread_local_top_.pending_exception_ != heap()->termination_exception() && |
+ if (!thread_local_top_.pending_exception_->IsOutOfMemory() && |
+ thread_local_top_.pending_exception_ != heap()->termination_exception() && |
thread_local_top_.has_pending_message_ && |
!thread_local_top_.pending_message_obj_->IsTheHole() && |
!thread_local_top_.pending_message_obj_->IsTheHole()) { |
@@ -1320,36 +1331,39 @@ bool Isolate::OptionalRescheduleException(bool is_bottom_call) { |
ASSERT(has_pending_exception()); |
PropagatePendingExceptionToExternalTryCatch(); |
- bool is_termination_exception = |
- pending_exception() == heap_.termination_exception(); |
+ // Always reschedule out of memory exceptions. |
+ if (!is_out_of_memory()) { |
+ bool is_termination_exception = |
+ pending_exception() == heap_.termination_exception(); |
- // Do not reschedule the exception if this is the bottom call. |
- bool clear_exception = is_bottom_call; |
+ // Do not reschedule the exception if this is the bottom call. |
+ bool clear_exception = is_bottom_call; |
- if (is_termination_exception) { |
- if (is_bottom_call) { |
+ if (is_termination_exception) { |
+ if (is_bottom_call) { |
+ thread_local_top()->external_caught_exception_ = false; |
+ clear_pending_exception(); |
+ return false; |
+ } |
+ } else if (thread_local_top()->external_caught_exception_) { |
+ // If the exception is externally caught, clear it if there are no |
+ // JavaScript frames on the way to the C++ frame that has the |
+ // external handler. |
+ ASSERT(thread_local_top()->try_catch_handler_address() != NULL); |
+ Address external_handler_address = |
+ thread_local_top()->try_catch_handler_address(); |
+ JavaScriptFrameIterator it(this); |
+ if (it.done() || (it.frame()->sp() > external_handler_address)) { |
+ clear_exception = true; |
+ } |
+ } |
+ |
+ // Clear the exception if needed. |
+ if (clear_exception) { |
thread_local_top()->external_caught_exception_ = false; |
clear_pending_exception(); |
return false; |
} |
- } else if (thread_local_top()->external_caught_exception_) { |
- // If the exception is externally caught, clear it if there are no |
- // JavaScript frames on the way to the C++ frame that has the |
- // external handler. |
- ASSERT(thread_local_top()->try_catch_handler_address() != NULL); |
- Address external_handler_address = |
- thread_local_top()->try_catch_handler_address(); |
- JavaScriptFrameIterator it(this); |
- if (it.done() || (it.frame()->sp() > external_handler_address)) { |
- clear_exception = true; |
- } |
- } |
- |
- // Clear the exception if needed. |
- if (clear_exception) { |
- thread_local_top()->external_caught_exception_ = false; |
- clear_pending_exception(); |
- return false; |
} |
// Reschedule the exception. |
@@ -1369,6 +1383,23 @@ void Isolate::SetCaptureStackTraceForUncaughtExceptions( |
} |
+bool Isolate::is_out_of_memory() { |
+ if (has_pending_exception()) { |
+ MaybeObject* e = pending_exception(); |
+ if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { |
+ return true; |
+ } |
+ } |
+ if (has_scheduled_exception()) { |
+ MaybeObject* e = scheduled_exception(); |
+ if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { |
+ return true; |
+ } |
+ } |
+ return false; |
+} |
+ |
+ |
Handle<Context> Isolate::native_context() { |
return Handle<Context>(context()->global_object()->native_context()); |
} |
@@ -1820,7 +1851,9 @@ void Isolate::PropagatePendingExceptionToExternalTryCatch() { |
if (!external_caught) return; |
- if (thread_local_top_.pending_exception_ == |
+ if (thread_local_top_.pending_exception_->IsOutOfMemory()) { |
+ // Do not propagate OOM exception: we should kill VM asap. |
+ } else if (thread_local_top_.pending_exception_ == |
heap()->termination_exception()) { |
try_catch_handler()->can_continue_ = false; |
try_catch_handler()->has_terminated_ = true; |