Index: src/execution.cc |
diff --git a/src/execution.cc b/src/execution.cc |
index 04ec9059f34d0311f5219148fdd4470a07ae9214..88e9b6d4631fb5f80a0adc3d560ddea850d7a1fe 100644 |
--- a/src/execution.cc |
+++ b/src/execution.cc |
@@ -222,9 +222,7 @@ StackGuard::StackGuard() { |
// lower addresses. |
ExecutionAccess access; |
if (thread_local_.nesting_++ == 0) { |
- // Initial StackGuard is being set. We will set the stack limits based on |
- // the current stack pointer allowing the stack to grow kLimitSize from |
- // here. |
+ // Initial StackGuard is being set. |
// Ensure that either the stack limits are unset (kIllegalLimit) or that |
// they indicate a pending interruption. The interrupt limit will be |
@@ -237,17 +235,26 @@ StackGuard::StackGuard() { |
(thread_local_.climit_ == kInterruptLimit && |
thread_local_.interrupt_flags_ != 0)); |
- uintptr_t limit = GENERATED_CODE_STACK_LIMIT(kLimitSize); |
- thread_local_.initial_jslimit_ = thread_local_.jslimit_ = limit; |
- Heap::SetStackLimit(limit); |
- // NOTE: The check for overflow is not safe as there is no guarantee that |
- // the running thread has its stack in all memory up to address 0x00000000. |
- thread_local_.initial_climit_ = thread_local_.climit_ = |
- reinterpret_cast<uintptr_t>(this) >= kLimitSize ? |
- reinterpret_cast<uintptr_t>(this) - kLimitSize : 0; |
- |
- if (thread_local_.interrupt_flags_ != 0) { |
- set_limits(kInterruptLimit, access); |
+ if (thread_local_.initial_jslimit_ == kIllegalLimit || |
+ thread_local_.initial_climit_ == kIllegalLimit) { |
+ ASSERT(thread_local_.initial_jslimit_ == kIllegalLimit && |
+ thread_local_.initial_climit_ == kIllegalLimit); |
+ |
+ // We will set the stack limits based on the current stack |
+ // pointer allowing the stack to grow kLimitSize from here. |
+ |
+ // Compute default limit, checking for underflow. |
+ uintptr_t limit = |
+ reinterpret_cast<uintptr_t>(this) >= kLimitSize ? |
+ reinterpret_cast<uintptr_t>(this) - kLimitSize : 0; |
+ |
+ thread_local_.initial_jslimit_ = GENERATED_CODE_STACK_LIMIT(limit); |
+ thread_local_.initial_climit_ = limit; |
+ } |
+ |
+ if (thread_local_.interrupt_flags_ == 0) { |
+ set_limits(thread_local_.initial_jslimit_, thread_local_.initial_climit_, |
+ access); |
} |
} |
// Ensure that proper limits have been set. |
@@ -260,8 +267,9 @@ StackGuard::StackGuard() { |
StackGuard::~StackGuard() { |
ExecutionAccess access; |
- if (--thread_local_.nesting_ == 0) { |
- set_limits(kIllegalLimit, access); |
+ if (--thread_local_.nesting_ == 0 && |
+ thread_local_.interrupt_flags_ == 0) { |
+ set_illegal_limit(access); |
} |
} |
@@ -276,24 +284,24 @@ bool StackGuard::IsStackOverflow() { |
void StackGuard::EnableInterrupts() { |
ExecutionAccess access; |
if (IsSet(access)) { |
- set_limits(kInterruptLimit, access); |
+ set_interrupt_limit(access); |
} |
} |
void StackGuard::SetStackLimit(uintptr_t limit) { |
ExecutionAccess access; |
- // If the current limits are special (eg due to a pending interrupt) then |
- // leave them alone. |
- if (thread_local_.jslimit_ == thread_local_.initial_jslimit_) { |
- thread_local_.jslimit_ = limit; |
- Heap::SetStackLimit(limit); |
- } |
- if (thread_local_.climit_ == thread_local_.initial_climit_) { |
- thread_local_.climit_ = limit; |
- } |
+ thread_local_.initial_jslimit_ = GENERATED_CODE_STACK_LIMIT(limit); |
thread_local_.initial_climit_ = limit; |
- thread_local_.initial_jslimit_ = limit; |
+ |
+ // If a StackGuard is active (nesting_ > 0) and not interrupted set |
+ // the limit directly. Otherwise the limit will be established by |
+ // the first StackGuard. |
+ if (thread_local_.nesting_ > 0 && |
+ thread_local_.interrupt_flags_ == 0) { |
+ set_limits(thread_local_.initial_jslimit_, thread_local_.initial_climit_, |
+ access); |
+ } |
} |
@@ -317,7 +325,7 @@ bool StackGuard::IsInterrupted() { |
void StackGuard::Interrupt() { |
ExecutionAccess access; |
thread_local_.interrupt_flags_ |= INTERRUPT; |
- set_limits(kInterruptLimit, access); |
+ set_interrupt_limit(access); |
} |
@@ -330,7 +338,7 @@ bool StackGuard::IsPreempted() { |
void StackGuard::Preempt() { |
ExecutionAccess access; |
thread_local_.interrupt_flags_ |= PREEMPT; |
- set_limits(kInterruptLimit, access); |
+ set_interrupt_limit(access); |
} |
@@ -343,7 +351,7 @@ bool StackGuard::IsTerminateExecution() { |
void StackGuard::TerminateExecution() { |
ExecutionAccess access; |
thread_local_.interrupt_flags_ |= TERMINATE; |
- set_limits(kInterruptLimit, access); |
+ set_interrupt_limit(access); |
} |
@@ -357,7 +365,7 @@ bool StackGuard::IsDebugBreak() { |
void StackGuard::DebugBreak() { |
ExecutionAccess access; |
thread_local_.interrupt_flags_ |= DEBUGBREAK; |
- set_limits(kInterruptLimit, access); |
+ set_interrupt_limit(access); |
} |
@@ -371,7 +379,7 @@ void StackGuard::DebugCommand() { |
if (FLAG_debugger_auto_break) { |
ExecutionAccess access; |
thread_local_.interrupt_flags_ |= DEBUGCOMMAND; |
- set_limits(kInterruptLimit, access); |
+ set_interrupt_limit(access); |
} |
} |
#endif |
@@ -407,6 +415,13 @@ char* StackGuard::RestoreStackGuard(char* from) { |
} |
+void StackGuard::InitThread(const ExecutionAccess& lock) { |
+ // new threads should configure their own stack limits |
+ ThreadLocal blank; |
+ thread_local_ = blank; |
+} |
+ |
+ |
// --- C a l l s t o n a t i v e s --- |
#define RETURN_NATIVE_CALL(name, argc, argv, has_pending_exception) \ |