| 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) \
|
|
|