Index: src/execution.cc |
=================================================================== |
--- src/execution.cc (revision 2982) |
+++ src/execution.cc (working copy) |
@@ -61,9 +61,6 @@ |
// Entering JavaScript. |
VMState state(JS); |
- // Guard the stack against too much recursion. |
- StackGuard guard; |
- |
// Placeholder for return value. |
Object* value = reinterpret_cast<Object*>(kZapValue); |
@@ -217,55 +214,6 @@ |
StackGuard::ThreadLocal StackGuard::thread_local_; |
-StackGuard::StackGuard() { |
- // NOTE: Overall the StackGuard code assumes that the stack grows towards |
- // 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. |
- |
- // Ensure that either the stack limits are unset (kIllegalLimit) or that |
- // they indicate a pending interruption. The interrupt limit will be |
- // temporarily reset through the code below and reestablished if the |
- // interrupt flags indicate that an interrupt is pending. |
- ASSERT(thread_local_.jslimit_ == kIllegalLimit || |
- (thread_local_.jslimit_ == kInterruptLimit && |
- thread_local_.interrupt_flags_ != 0)); |
- ASSERT(thread_local_.climit_ == kIllegalLimit || |
- (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); |
- } |
- } |
- // Ensure that proper limits have been set. |
- ASSERT(thread_local_.jslimit_ != kIllegalLimit && |
- thread_local_.climit_ != kIllegalLimit); |
- ASSERT(thread_local_.initial_jslimit_ != kIllegalLimit && |
- thread_local_.initial_climit_ != kIllegalLimit); |
-} |
- |
- |
-StackGuard::~StackGuard() { |
- ExecutionAccess access; |
- if (--thread_local_.nesting_ == 0) { |
- set_limits(kIllegalLimit, access); |
- } |
-} |
- |
- |
bool StackGuard::IsStackOverflow() { |
ExecutionAccess access; |
return (thread_local_.jslimit_ != kInterruptLimit && |
@@ -285,15 +233,16 @@ |
ExecutionAccess access; |
// If the current limits are special (eg due to a pending interrupt) then |
// leave them alone. |
+ uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(limit); |
if (thread_local_.jslimit_ == thread_local_.initial_jslimit_) { |
- thread_local_.jslimit_ = limit; |
- Heap::SetStackLimit(limit); |
+ thread_local_.jslimit_ = jslimit; |
+ Heap::SetStackLimit(jslimit); |
} |
if (thread_local_.climit_ == thread_local_.initial_climit_) { |
thread_local_.climit_ = limit; |
} |
thread_local_.initial_climit_ = limit; |
- thread_local_.initial_jslimit_ = limit; |
+ thread_local_.initial_jslimit_ = jslimit; |
} |
@@ -407,10 +356,61 @@ |
} |
+static internal::Thread::LocalStorageKey stack_limit_key = |
+ internal::Thread::CreateThreadLocalKey(); |
+ |
+ |
void StackGuard::FreeThreadResources() { |
+ Thread::SetThreadLocal( |
+ stack_limit_key, |
+ reinterpret_cast<void*>(thread_local_.initial_climit_)); |
} |
+void StackGuard::ThreadLocal::Clear() { |
+ initial_jslimit_ = kIllegalLimit; |
+ jslimit_ = kIllegalLimit; |
+ initial_climit_ = kIllegalLimit; |
+ climit_ = kIllegalLimit; |
+ nesting_ = 0; |
+ postpone_interrupts_nesting_ = 0; |
+ interrupt_flags_ = 0; |
+ Heap::SetStackLimit(kIllegalLimit); |
+} |
+ |
+ |
+void StackGuard::ThreadLocal::Initialize() { |
+ if (initial_climit_ == kIllegalLimit) { |
+ // Takes the address of the limit variable in order to find out where |
+ // the top of stack is right now. |
+ intptr_t limit = reinterpret_cast<intptr_t>(&limit) - kLimitSize; |
+ initial_jslimit_ = SimulatorStack::JsLimitFromCLimit(limit); |
+ jslimit_ = SimulatorStack::JsLimitFromCLimit(limit); |
+ initial_climit_ = limit; |
+ climit_ = limit; |
+ Heap::SetStackLimit(SimulatorStack::JsLimitFromCLimit(limit)); |
+ } |
+ nesting_ = 0; |
+ postpone_interrupts_nesting_ = 0; |
+ interrupt_flags_ = 0; |
+} |
+ |
+ |
+void StackGuard::ClearThread(const ExecutionAccess& lock) { |
+ thread_local_.Clear(); |
+} |
+ |
+ |
+void StackGuard::InitThread(const ExecutionAccess& lock) { |
+ thread_local_.Initialize(); |
+ void* stored_limit = Thread::GetThreadLocal(stack_limit_key); |
+ // You should hold the ExecutionAccess lock when you call this. |
+ if (stored_limit != NULL) { |
+ StackGuard::SetStackLimit(reinterpret_cast<intptr_t>(stored_limit)); |
+ } |
+} |
+ |
+ |
// --- C a l l s t o n a t i v e s --- |
#define RETURN_NATIVE_CALL(name, argc, argv, has_pending_exception) \ |