Index: src/isolate.cc |
diff --git a/src/isolate.cc b/src/isolate.cc |
index 215296d735cc5b8b9698cfc67d9dc0cfa3bd7208..cfd5a3d8e6c62aac9414feab62e239376efae98d 100644 |
--- a/src/isolate.cc |
+++ b/src/isolate.cc |
@@ -79,6 +79,7 @@ void ThreadLocalTop::InitializeInternal() { |
save_context_ = NULL; |
catcher_ = NULL; |
top_lookup_result_ = NULL; |
+ promise_on_stack_ = NULL; |
// These members are re-initialized later after deserialization |
// is complete. |
@@ -100,6 +101,12 @@ void ThreadLocalTop::Initialize() { |
} |
+void ThreadLocalTop::Free() { |
+ // Match unmatched PopPromise calls. |
+ while (promise_on_stack_) isolate_->PopPromise(); |
+} |
+ |
+ |
base::Thread::LocalStorageKey Isolate::isolate_key_; |
base::Thread::LocalStorageKey Isolate::thread_id_key_; |
base::Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_; |
@@ -1289,6 +1296,48 @@ bool Isolate::OptionalRescheduleException(bool is_bottom_call) { |
} |
+void Isolate::PushPromise(Handle<JSObject> promise) { |
+ ThreadLocalTop* tltop = thread_local_top(); |
+ PromiseOnStack* prev = tltop->promise_on_stack_; |
+ StackHandler* handler = StackHandler::FromAddress(Isolate::handler(tltop)); |
+ Handle<JSObject> global_handle = |
+ Handle<JSObject>::cast(global_handles()->Create(*promise)); |
+ tltop->promise_on_stack_ = new PromiseOnStack(handler, global_handle, prev); |
+} |
+ |
+ |
+void Isolate::PopPromise() { |
+ ThreadLocalTop* tltop = thread_local_top(); |
+ if (tltop->promise_on_stack_ == NULL) return; |
+ PromiseOnStack* prev = tltop->promise_on_stack_->prev(); |
+ Handle<Object> global_handle = tltop->promise_on_stack_->promise(); |
+ delete tltop->promise_on_stack_; |
+ tltop->promise_on_stack_ = prev; |
+ global_handles()->Destroy(global_handle.location()); |
+} |
+ |
+ |
+Handle<Object> Isolate::GetPromiseOnStackOnThrow() { |
+ Handle<Object> undefined = factory()->undefined_value(); |
+ ThreadLocalTop* tltop = thread_local_top(); |
+ if (tltop->promise_on_stack_ == NULL) return undefined; |
+ StackHandler* promise_try = tltop->promise_on_stack_->handler(); |
+ // Find the top-most try-catch handler. |
+ StackHandler* handler = StackHandler::FromAddress(Isolate::handler(tltop)); |
+ do { |
+ if (handler == promise_try) { |
+ // Mark the pushed try-catch handler to prevent a later duplicate event |
+ // triggered with the following reject. |
+ return tltop->promise_on_stack_->promise(); |
+ } |
+ handler = handler->next(); |
+ // Throwing inside a Promise can be intercepted by an inner try-catch, so |
+ // we stop at the first try-catch handler. |
+ } while (handler != NULL && !handler->is_catch()); |
+ return undefined; |
+} |
+ |
+ |
void Isolate::SetCaptureStackTraceForUncaughtExceptions( |
bool capture, |
int frame_limit, |
@@ -1552,6 +1601,8 @@ void Isolate::Deinit() { |
debug()->Unload(); |
+ FreeThreadResources(); |
+ |
if (concurrent_recompilation_enabled()) { |
optimizing_compiler_thread_->Stop(); |
delete optimizing_compiler_thread_; |