Index: runtime/vm/isolate.cc |
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc |
index 2ba8ae05af06d7e83f8c6aad08e010064a5e0476..09010a010987b423d16e55f31c66eb14cba05e92 100644 |
--- a/runtime/vm/isolate.cc |
+++ b/runtime/vm/isolate.cc |
@@ -774,6 +774,8 @@ Isolate::Isolate(const Dart_IsolateFlags& api_flags) |
simulator_(NULL), |
mutex_(new Mutex()), |
saved_stack_limit_(0), |
+ deferred_interrupts_mask_(0), |
+ deferred_interrupts_(0), |
stack_overflow_flags_(0), |
stack_overflow_count_(0), |
message_handler_(NULL), |
@@ -1029,16 +1031,6 @@ void Isolate::ClearStackLimit() { |
} |
-void Isolate::ScheduleInterrupts(uword interrupt_bits) { |
- MutexLocker ml(mutex_); |
- ASSERT((interrupt_bits & ~kInterruptsMask) == 0); // Must fit in mask. |
- if (stack_limit_ == saved_stack_limit_) { |
- stack_limit_ = (~static_cast<uword>(0)) & ~kInterruptsMask; |
- } |
- stack_limit_ |= interrupt_bits; |
-} |
- |
- |
void Isolate::DoneLoading() { |
GrowableObjectArray& libs = GrowableObjectArray::Handle(current_zone(), |
object_store()->libraries()); |
@@ -1439,6 +1431,27 @@ void Isolate::Run() { |
} |
+void Isolate::ScheduleInterrupts(uword interrupt_bits) { |
+ MutexLocker ml(mutex_); |
+ ASSERT((interrupt_bits & ~kInterruptsMask) == 0); // Must fit in mask. |
+ |
+ // Check to see if any of the requested interrupts should be deferred. |
+ uword defer_bits = interrupt_bits & deferred_interrupts_mask_; |
+ if (defer_bits != 0) { |
+ deferred_interrupts_ |= defer_bits; |
+ interrupt_bits &= ~deferred_interrupts_mask_; |
+ if (interrupt_bits == 0) { |
+ return; |
+ } |
+ } |
+ |
+ if (stack_limit_ == saved_stack_limit_) { |
+ stack_limit_ = (~static_cast<uword>(0)) & ~kInterruptsMask; |
+ } |
+ stack_limit_ |= interrupt_bits; |
+} |
+ |
+ |
uword Isolate::GetAndClearInterrupts() { |
MutexLocker ml(mutex_); |
if (stack_limit_ == saved_stack_limit_) { |
@@ -1450,6 +1463,40 @@ uword Isolate::GetAndClearInterrupts() { |
} |
+void Isolate::DeferMessageInterrupts() { |
+ MutexLocker ml(mutex_); |
+ ASSERT(deferred_interrupts_mask_ == 0); |
+ deferred_interrupts_mask_ = kMessageInterrupt; |
+ |
+ if (stack_limit_ != saved_stack_limit_) { |
+ // Defer any interrupts which are currently pending. |
+ deferred_interrupts_ = stack_limit_ & deferred_interrupts_mask_; |
+ |
+ // Clear deferrable interrupts, if present. |
+ stack_limit_ &= ~deferred_interrupts_mask_; |
+ |
+ if ((stack_limit_ & kInterruptsMask) == 0) { |
+ // No other pending interrupts. Restore normal stack limit. |
+ stack_limit_ = saved_stack_limit_; |
+ } |
+ } |
+} |
+ |
+ |
+void Isolate::RestoreMessageInterrupts() { |
+ MutexLocker ml(mutex_); |
+ ASSERT(deferred_interrupts_mask_ == kMessageInterrupt); |
+ deferred_interrupts_mask_ = 0; |
+ if (deferred_interrupts_ != 0) { |
+ if (stack_limit_ == saved_stack_limit_) { |
+ stack_limit_ = (~static_cast<uword>(0)) & ~kInterruptsMask; |
+ } |
+ stack_limit_ |= deferred_interrupts_; |
+ deferred_interrupts_ = 0; |
+ } |
+} |
+ |
+ |
RawError* Isolate::HandleInterrupts() { |
uword interrupt_bits = GetAndClearInterrupts(); |
if ((interrupt_bits & kVMInterrupt) != 0) { |