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