Index: src/execution.cc |
diff --git a/src/execution.cc b/src/execution.cc |
index c0e9a64fbb000fe94d8a3a0be97c20277ab935e6..634c83ae189e5a2e5cdc8be4abbb0c91f85dcb07 100644 |
--- a/src/execution.cc |
+++ b/src/execution.cc |
@@ -540,6 +540,48 @@ void StackGuard::Continue(InterruptFlag after_what) { |
} |
+void StackGuard::RequestInterrupt(InterruptCallback callback, void* data) { |
+ ExecutionAccess access(isolate_); |
+ thread_local_.interrupt_flags_ |= API_INTERRUPT; |
+ thread_local_.interrupt_callback_ = callback; |
+ thread_local_.interrupt_callback_data_ = data; |
+ set_interrupt_limits(access); |
+} |
+ |
+ |
+void StackGuard::ClearInterrupt() { |
+ thread_local_.interrupt_callback_ = 0; |
+ thread_local_.interrupt_callback_data_ = 0; |
+ Continue(API_INTERRUPT); |
+} |
+ |
+ |
+bool StackGuard::IsAPIInterrupt() { |
+ ExecutionAccess access(isolate_); |
+ return thread_local_.interrupt_flags_ & API_INTERRUPT; |
+} |
+ |
+ |
+void StackGuard::InvokeInterruptCallback() { |
+ InterruptCallback callback = 0; |
+ void* data = 0; |
+ |
+ { |
+ ExecutionAccess access(isolate_); |
+ callback = thread_local_.interrupt_callback_; |
+ data = thread_local_.interrupt_callback_data_; |
+ thread_local_.interrupt_callback_ = NULL; |
+ thread_local_.interrupt_callback_data_ = NULL; |
+ } |
+ |
+ if (callback != NULL) { |
+ VMState<EXTERNAL> state(isolate_); |
+ HandleScope handle_scope(isolate_); |
+ callback(reinterpret_cast<v8::Isolate*>(isolate_), data); |
+ } |
+} |
+ |
+ |
char* StackGuard::ArchiveStackGuard(char* to) { |
ExecutionAccess access(isolate_); |
OS::MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); |
@@ -581,6 +623,7 @@ void StackGuard::ThreadLocal::Clear() { |
nesting_ = 0; |
postpone_interrupts_nesting_ = 0; |
interrupt_flags_ = 0; |
+ interrupt_callback_ = 0; |
} |
@@ -601,6 +644,7 @@ bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) { |
nesting_ = 0; |
postpone_interrupts_nesting_ = 0; |
interrupt_flags_ = 0; |
+ interrupt_callback_ = 0; |
return should_set_stack_limits; |
} |
@@ -936,6 +980,11 @@ MaybeObject* Execution::HandleStackGuardInterrupt(Isolate* isolate) { |
return isolate->heap()->undefined_value(); |
} |
+ if (stack_guard->IsAPIInterrupt()) { |
+ stack_guard->InvokeInterruptCallback(); |
+ stack_guard->Continue(API_INTERRUPT); |
+ } |
+ |
if (stack_guard->IsGCRequest()) { |
isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
"StackGuard GC request"); |