| Index: src/execution.cc
|
| ===================================================================
|
| --- src/execution.cc (revision 3427)
|
| +++ src/execution.cc (working copy)
|
| @@ -38,7 +38,20 @@
|
| namespace v8 {
|
| namespace internal {
|
|
|
| +class StackGuardPrivateData {
|
| + public:
|
| + Thread::LocalStorageKey stack_limit_key;
|
|
|
| + StackGuardPrivateData()
|
| + :stack_limit_key(internal::Thread::CreateThreadLocalKey()) {
|
| + }
|
| +};
|
| +
|
| +StackGuardData::StackGuardData()
|
| + :thread_local_(0),
|
| + stack_guard_private_data_(NULL) {
|
| +}
|
| +
|
| static Handle<Object> Invoke(bool construct,
|
| Handle<JSFunction> func,
|
| Handle<Object> receiver,
|
| @@ -204,13 +217,14 @@
|
|
|
|
|
| // Static state for stack guards.
|
| -StackGuard::ThreadLocal StackGuard::thread_local_;
|
|
|
|
|
| bool StackGuard::IsStackOverflow() {
|
| ExecutionAccess access;
|
| - return (thread_local_.jslimit_ != kInterruptLimit &&
|
| - thread_local_.climit_ != kInterruptLimit);
|
| + StackGuardData::ThreadLocal& thread_local = v8_context()->
|
| + stack_guard_data_.thread_local_;
|
| + return (thread_local.jslimit_ != kInterruptLimit &&
|
| + thread_local.climit_ != kInterruptLimit);
|
| }
|
|
|
|
|
| @@ -224,17 +238,19 @@
|
|
|
| void StackGuard::SetStackLimit(uintptr_t limit) {
|
| ExecutionAccess access;
|
| + StackGuardData::ThreadLocal& thread_local = v8_context()->
|
| + stack_guard_data_.thread_local_;
|
| // 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_.real_jslimit_) {
|
| - thread_local_.jslimit_ = jslimit;
|
| + if (thread_local.jslimit_ == thread_local.real_jslimit_) {
|
| + thread_local.jslimit_ = jslimit;
|
| }
|
| - if (thread_local_.climit_ == thread_local_.real_climit_) {
|
| - thread_local_.climit_ = limit;
|
| + if (thread_local.climit_ == thread_local.real_climit_) {
|
| + thread_local.climit_ = limit;
|
| }
|
| - thread_local_.real_climit_ = limit;
|
| - thread_local_.real_jslimit_ = jslimit;
|
| + thread_local.real_climit_ = limit;
|
| + thread_local.real_jslimit_ = jslimit;
|
| }
|
|
|
|
|
| @@ -245,45 +261,48 @@
|
|
|
|
|
| bool StackGuard::IsSet(const ExecutionAccess& lock) {
|
| - return thread_local_.interrupt_flags_ != 0;
|
| + return v8_context()->stack_guard_data_.thread_local_.interrupt_flags_ != 0;
|
| }
|
|
|
|
|
| bool StackGuard::IsInterrupted() {
|
| ExecutionAccess access;
|
| - return thread_local_.interrupt_flags_ & INTERRUPT;
|
| + return v8_context()->
|
| + stack_guard_data_.thread_local_.interrupt_flags_ & INTERRUPT;
|
| }
|
|
|
|
|
| void StackGuard::Interrupt() {
|
| ExecutionAccess access;
|
| - thread_local_.interrupt_flags_ |= INTERRUPT;
|
| + v8_context()->stack_guard_data_.thread_local_.interrupt_flags_ |= INTERRUPT;
|
| set_limits(kInterruptLimit, access);
|
| }
|
|
|
|
|
| bool StackGuard::IsPreempted() {
|
| ExecutionAccess access;
|
| - return thread_local_.interrupt_flags_ & PREEMPT;
|
| + return v8_context()->
|
| + stack_guard_data_.thread_local_.interrupt_flags_ & PREEMPT;
|
| }
|
|
|
|
|
| void StackGuard::Preempt() {
|
| ExecutionAccess access;
|
| - thread_local_.interrupt_flags_ |= PREEMPT;
|
| + v8_context()->stack_guard_data_.thread_local_.interrupt_flags_ |= PREEMPT;
|
| set_limits(kInterruptLimit, access);
|
| }
|
|
|
|
|
| bool StackGuard::IsTerminateExecution() {
|
| ExecutionAccess access;
|
| - return thread_local_.interrupt_flags_ & TERMINATE;
|
| + return v8_context()->
|
| + stack_guard_data_.thread_local_.interrupt_flags_ & TERMINATE;
|
| }
|
|
|
|
|
| void StackGuard::TerminateExecution() {
|
| ExecutionAccess access;
|
| - thread_local_.interrupt_flags_ |= TERMINATE;
|
| + v8_context()->stack_guard_data_.thread_local_.interrupt_flags_ |= TERMINATE;
|
| set_limits(kInterruptLimit, access);
|
| }
|
|
|
| @@ -291,27 +310,30 @@
|
| #ifdef ENABLE_DEBUGGER_SUPPORT
|
| bool StackGuard::IsDebugBreak() {
|
| ExecutionAccess access;
|
| - return thread_local_.interrupt_flags_ & DEBUGBREAK;
|
| + return v8_context()->
|
| + stack_guard_data_.thread_local_.interrupt_flags_ & DEBUGBREAK;
|
| }
|
|
|
|
|
| void StackGuard::DebugBreak() {
|
| ExecutionAccess access;
|
| - thread_local_.interrupt_flags_ |= DEBUGBREAK;
|
| + v8_context()->stack_guard_data_.thread_local_.interrupt_flags_ |= DEBUGBREAK;
|
| set_limits(kInterruptLimit, access);
|
| }
|
|
|
|
|
| bool StackGuard::IsDebugCommand() {
|
| ExecutionAccess access;
|
| - return thread_local_.interrupt_flags_ & DEBUGCOMMAND;
|
| + return v8_context()->
|
| + stack_guard_data_.thread_local_.interrupt_flags_ & DEBUGCOMMAND;
|
| }
|
|
|
|
|
| void StackGuard::DebugCommand() {
|
| if (FLAG_debugger_auto_break) {
|
| ExecutionAccess access;
|
| - thread_local_.interrupt_flags_ |= DEBUGCOMMAND;
|
| + v8_context()->
|
| + stack_guard_data_.thread_local_.interrupt_flags_ |= DEBUGCOMMAND;
|
| set_limits(kInterruptLimit, access);
|
| }
|
| }
|
| @@ -319,51 +341,69 @@
|
|
|
| void StackGuard::Continue(InterruptFlag after_what) {
|
| ExecutionAccess access;
|
| - thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what);
|
| - if (thread_local_.interrupt_flags_ == 0) {
|
| + StackGuardData::ThreadLocal& thread_local = v8_context()->
|
| + stack_guard_data_.thread_local_;
|
| + thread_local.interrupt_flags_ &= ~static_cast<int>(after_what);
|
| + if (thread_local.interrupt_flags_ == 0) {
|
| reset_limits(access);
|
| }
|
| }
|
|
|
|
|
| int StackGuard::ArchiveSpacePerThread() {
|
| - return sizeof(ThreadLocal);
|
| + return sizeof(StackGuardData::ThreadLocal);
|
| }
|
|
|
|
|
| char* StackGuard::ArchiveStackGuard(char* to) {
|
| ExecutionAccess access;
|
| - memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
|
| - ThreadLocal blank;
|
| - thread_local_ = blank;
|
| - return to + sizeof(ThreadLocal);
|
| + StackGuardData::ThreadLocal& thread_local = v8_context()->
|
| + stack_guard_data_.thread_local_;
|
| + memcpy(
|
| + to,
|
| + reinterpret_cast<char*>(&thread_local),
|
| + sizeof(StackGuardData::ThreadLocal));
|
| + StackGuardData::ThreadLocal blank;
|
| + thread_local = blank;
|
| + return to + sizeof(StackGuardData::ThreadLocal);
|
| }
|
|
|
|
|
| char* StackGuard::RestoreStackGuard(char* from) {
|
| ExecutionAccess access;
|
| - memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
|
| + memcpy(
|
| + reinterpret_cast<char*>(&v8_context()->stack_guard_data_.thread_local_),
|
| + from,
|
| + sizeof(StackGuardData::ThreadLocal));
|
| Heap::SetStackLimits();
|
| - return from + sizeof(ThreadLocal);
|
| + return from + sizeof(StackGuardData::ThreadLocal);
|
| }
|
|
|
|
|
| -static internal::Thread::LocalStorageKey stack_limit_key =
|
| - internal::Thread::CreateThreadLocalKey();
|
| +void StackGuard::PostConstruct() {
|
| + V8Context* const v8context = v8_context();
|
| + v8context->stack_guard_data_.thread_local_.Clear();
|
| + v8context->stack_guard_data_.stack_guard_private_data_ =
|
| + new StackGuardPrivateData();
|
| +}
|
|
|
| +void StackGuard::PreDestroy() {
|
| + delete v8_context()->stack_guard_data_.stack_guard_private_data_;
|
| +}
|
|
|
| void StackGuard::FreeThreadResources() {
|
| + StackGuardData& stack_guard_data = v8_context()->stack_guard_data_;
|
| Thread::SetThreadLocal(
|
| - stack_limit_key,
|
| - reinterpret_cast<void*>(thread_local_.real_climit_));
|
| + stack_guard_data.stack_guard_private_data_->stack_limit_key,
|
| + reinterpret_cast<void*>(stack_guard_data.thread_local_.real_climit_));
|
| }
|
|
|
|
|
| -void StackGuard::ThreadLocal::Clear() {
|
| - real_jslimit_ = kIllegalLimit;
|
| - jslimit_ = kIllegalLimit;
|
| - real_climit_ = kIllegalLimit;
|
| - climit_ = kIllegalLimit;
|
| +void StackGuardData::ThreadLocal::Clear() {
|
| + real_jslimit_ = StackGuard::kIllegalLimit;
|
| + jslimit_ = StackGuard::kIllegalLimit;
|
| + real_climit_ = StackGuard::kIllegalLimit;
|
| + climit_ = StackGuard::kIllegalLimit;
|
| nesting_ = 0;
|
| postpone_interrupts_nesting_ = 0;
|
| interrupt_flags_ = 0;
|
| @@ -371,12 +411,13 @@
|
| }
|
|
|
|
|
| -void StackGuard::ThreadLocal::Initialize() {
|
| - if (real_climit_ == kIllegalLimit) {
|
| +void StackGuardData::ThreadLocal::Initialize() {
|
| + if (real_climit_ == StackGuard::kIllegalLimit) {
|
| // Takes the address of the limit variable in order to find out where
|
| // the top of stack is right now.
|
| - uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize;
|
| - ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize);
|
| + uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) -
|
| + StackGuard::kLimitSize;
|
| + ASSERT(reinterpret_cast<uintptr_t>(&limit) > StackGuard::kLimitSize);
|
| real_jslimit_ = SimulatorStack::JsLimitFromCLimit(limit);
|
| jslimit_ = SimulatorStack::JsLimitFromCLimit(limit);
|
| real_climit_ = limit;
|
| @@ -390,13 +431,15 @@
|
|
|
|
|
| void StackGuard::ClearThread(const ExecutionAccess& lock) {
|
| - thread_local_.Clear();
|
| + v8_context()->stack_guard_data_.thread_local_.Clear();
|
| }
|
|
|
|
|
| void StackGuard::InitThread(const ExecutionAccess& lock) {
|
| - thread_local_.Initialize();
|
| - void* stored_limit = Thread::GetThreadLocal(stack_limit_key);
|
| + StackGuardData& stack_guard_data = v8_context()->stack_guard_data_;
|
| + stack_guard_data.thread_local_.Initialize();
|
| + void* stored_limit = Thread::GetThreadLocal(
|
| + stack_guard_data.stack_guard_private_data_->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));
|
|
|