Index: src/execution.cc |
diff --git a/src/execution.cc b/src/execution.cc |
index 2766e76b8caa5454923542d8861a6a581977f946..5cb55311bc04f72006b0ea4da71ddb34d91a4b20 100644 |
--- a/src/execution.cc |
+++ b/src/execution.cc |
@@ -20,8 +20,6 @@ StackGuard::StackGuard() |
void StackGuard::set_interrupt_limits(const ExecutionAccess& lock) { |
ASSERT(isolate_ != NULL); |
- // Ignore attempts to interrupt when interrupts are postponed. |
- if (should_postpone_interrupts(lock)) return; |
thread_local_.jslimit_ = kInterruptLimit; |
thread_local_.climit_ = kInterruptLimit; |
isolate_->heap()->SetStackLimits(); |
@@ -337,36 +335,62 @@ void StackGuard::DisableInterrupts() { |
} |
-bool StackGuard::CheckInterrupt(int flagbit) { |
+void StackGuard::PushPostponeInterruptsScope(PostponeInterruptsScope* scope) { |
ExecutionAccess access(isolate_); |
- return thread_local_.interrupt_flags_ & flagbit; |
+ scope->prev_ = thread_local_.postpone_interrupts_; |
+ thread_local_.postpone_interrupts_ = scope; |
} |
-void StackGuard::RequestInterrupt(int flagbit) { |
+void StackGuard::PopPostponeInterruptsScope() { |
ExecutionAccess access(isolate_); |
- thread_local_.interrupt_flags_ |= flagbit; |
+ PostponeInterruptsScope* top = thread_local_.postpone_interrupts_; |
+ thread_local_.interrupt_flags_ |= top->intercepted_flags_; |
+ thread_local_.postpone_interrupts_ = top->prev_; |
+ if (has_pending_interrupts(access)) set_interrupt_limits(access); |
+} |
+ |
+ |
+bool StackGuard::CheckInterrupt(InterruptFlag flag) { |
+ ExecutionAccess access(isolate_); |
+ return thread_local_.interrupt_flags_ & flag; |
+} |
+ |
+ |
+void StackGuard::RequestInterrupt(InterruptFlag flag) { |
+ ExecutionAccess access(isolate_); |
+ // Check the chain of PostponeInterruptsScopes for interception. |
+ if (thread_local_.postpone_interrupts_ && |
+ thread_local_.postpone_interrupts_->Intercept(flag)) { |
+ return; |
+ } |
+ |
+ // Not intercepted. Set as active interrupt flag. |
+ thread_local_.interrupt_flags_ |= flag; |
set_interrupt_limits(access); |
} |
-void StackGuard::ClearInterrupt(int flagbit) { |
+void StackGuard::ClearInterrupt(InterruptFlag flag) { |
ExecutionAccess access(isolate_); |
- thread_local_.interrupt_flags_ &= ~flagbit; |
- if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) { |
- reset_limits(access); |
+ // Clear the interrupt flag from the chain of PostponeInterruptsScopes. |
+ for (PostponeInterruptsScope* current = thread_local_.postpone_interrupts_; |
+ current != NULL; |
+ current = current->prev_) { |
+ current->intercepted_flags_ &= ~flag; |
} |
+ |
+ // Clear the interrupt flag from the active interrupt flags. |
+ thread_local_.interrupt_flags_ &= ~flag; |
+ if (!has_pending_interrupts(access)) reset_limits(access); |
} |
bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag) { |
ExecutionAccess access(isolate_); |
- int flagbit = 1 << flag; |
- bool result = (thread_local_.interrupt_flags_ & flagbit); |
- thread_local_.interrupt_flags_ &= ~flagbit; |
- if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) { |
- reset_limits(access); |
- } |
+ bool result = (thread_local_.interrupt_flags_ & flag); |
+ thread_local_.interrupt_flags_ &= ~flag; |
+ if (!has_pending_interrupts(access)) reset_limits(access); |
return result; |
} |
@@ -408,8 +432,7 @@ void StackGuard::ThreadLocal::Clear() { |
jslimit_ = kIllegalLimit; |
real_climit_ = kIllegalLimit; |
climit_ = kIllegalLimit; |
- nesting_ = 0; |
- postpone_interrupts_nesting_ = 0; |
+ postpone_interrupts_ = NULL; |
interrupt_flags_ = 0; |
} |
@@ -428,8 +451,7 @@ bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) { |
climit_ = limit; |
should_set_stack_limits = true; |
} |
- nesting_ = 0; |
- postpone_interrupts_nesting_ = 0; |
+ postpone_interrupts_ = NULL; |
interrupt_flags_ = 0; |
return should_set_stack_limits; |
} |
@@ -648,13 +670,6 @@ Handle<String> Execution::GetStackTraceLine(Handle<Object> recv, |
Object* StackGuard::HandleInterrupts() { |
- { |
- ExecutionAccess access(isolate_); |
- if (should_postpone_interrupts(access)) { |
- return isolate_->heap()->undefined_value(); |
- } |
- } |
- |
if (CheckAndClearInterrupt(GC_REQUEST)) { |
isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, "GC interrupt"); |
} |