Chromium Code Reviews| Index: src/execution.cc |
| diff --git a/src/execution.cc b/src/execution.cc |
| index b74ef4d62ea6b0b14558fce3810308af42e4bf8a..ee6cb970cb8bd6d852f3e34a681e82d9f3efb686 100644 |
| --- a/src/execution.cc |
| +++ b/src/execution.cc |
| @@ -366,190 +366,37 @@ void StackGuard::DisableInterrupts() { |
| } |
| -bool StackGuard::ShouldPostponeInterrupts() { |
| +bool StackGuard::CheckInterrupt(int flagbit) { |
| ExecutionAccess access(isolate_); |
| - return should_postpone_interrupts(access); |
| + return thread_local_.interrupt_flags_ & flagbit; |
| } |
| -bool StackGuard::IsInterrupted() { |
| +void StackGuard::RequestInterrupt(int flagbit) { |
| ExecutionAccess access(isolate_); |
| - return (thread_local_.interrupt_flags_ & INTERRUPT) != 0; |
| -} |
| - |
| - |
| -void StackGuard::Interrupt() { |
| - ExecutionAccess access(isolate_); |
| - thread_local_.interrupt_flags_ |= INTERRUPT; |
| - set_interrupt_limits(access); |
| -} |
| - |
| - |
| -bool StackGuard::IsPreempted() { |
| - ExecutionAccess access(isolate_); |
| - return thread_local_.interrupt_flags_ & PREEMPT; |
| -} |
| - |
| - |
| -void StackGuard::Preempt() { |
| - ExecutionAccess access(isolate_); |
| - thread_local_.interrupt_flags_ |= PREEMPT; |
| + thread_local_.interrupt_flags_ |= flagbit; |
| set_interrupt_limits(access); |
| } |
| -bool StackGuard::IsTerminateExecution() { |
| +void StackGuard::ClearInterrupt(int flagbit) { |
| ExecutionAccess access(isolate_); |
| - return (thread_local_.interrupt_flags_ & TERMINATE) != 0; |
| -} |
| - |
| - |
| -void StackGuard::CancelTerminateExecution() { |
| - ExecutionAccess access(isolate_); |
| - Continue(TERMINATE); |
| - isolate_->CancelTerminateExecution(); |
| -} |
| - |
| - |
| -void StackGuard::TerminateExecution() { |
| - ExecutionAccess access(isolate_); |
| - thread_local_.interrupt_flags_ |= TERMINATE; |
| - set_interrupt_limits(access); |
| -} |
| - |
| - |
| -bool StackGuard::IsGCRequest() { |
| - ExecutionAccess access(isolate_); |
| - return (thread_local_.interrupt_flags_ & GC_REQUEST) != 0; |
| -} |
| - |
| - |
| -void StackGuard::RequestGC() { |
| - ExecutionAccess access(isolate_); |
| - thread_local_.interrupt_flags_ |= GC_REQUEST; |
| - if (thread_local_.postpone_interrupts_nesting_ == 0) { |
| - thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit; |
| - isolate_->heap()->SetStackLimits(); |
| - } |
| -} |
| - |
| - |
| -bool StackGuard::IsInstallCodeRequest() { |
| - ExecutionAccess access(isolate_); |
| - return (thread_local_.interrupt_flags_ & INSTALL_CODE) != 0; |
| -} |
| - |
| - |
| -void StackGuard::RequestInstallCode() { |
| - ExecutionAccess access(isolate_); |
| - thread_local_.interrupt_flags_ |= INSTALL_CODE; |
| - if (thread_local_.postpone_interrupts_nesting_ == 0) { |
| - thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit; |
| - isolate_->heap()->SetStackLimits(); |
| - } |
| -} |
| - |
| - |
| -bool StackGuard::IsFullDeopt() { |
| - ExecutionAccess access(isolate_); |
| - return (thread_local_.interrupt_flags_ & FULL_DEOPT) != 0; |
| -} |
| - |
| - |
| -void StackGuard::FullDeopt() { |
| - ExecutionAccess access(isolate_); |
| - thread_local_.interrupt_flags_ |= FULL_DEOPT; |
| - set_interrupt_limits(access); |
| -} |
| - |
| - |
| -bool StackGuard::IsDeoptMarkedAllocationSites() { |
| - ExecutionAccess access(isolate_); |
| - return (thread_local_.interrupt_flags_ & DEOPT_MARKED_ALLOCATION_SITES) != 0; |
| -} |
| - |
| - |
| -void StackGuard::DeoptMarkedAllocationSites() { |
| - ExecutionAccess access(isolate_); |
| - thread_local_.interrupt_flags_ |= DEOPT_MARKED_ALLOCATION_SITES; |
| - set_interrupt_limits(access); |
| -} |
| - |
| - |
| -bool StackGuard::IsDebugBreak() { |
| - ExecutionAccess access(isolate_); |
| - return thread_local_.interrupt_flags_ & DEBUGBREAK; |
| -} |
| - |
| - |
| -void StackGuard::DebugBreak() { |
| - ExecutionAccess access(isolate_); |
| - thread_local_.interrupt_flags_ |= DEBUGBREAK; |
| - set_interrupt_limits(access); |
| -} |
| - |
| - |
| -bool StackGuard::IsDebugCommand() { |
| - ExecutionAccess access(isolate_); |
| - return thread_local_.interrupt_flags_ & DEBUGCOMMAND; |
| -} |
| - |
| - |
| -void StackGuard::DebugCommand() { |
| - ExecutionAccess access(isolate_); |
| - thread_local_.interrupt_flags_ |= DEBUGCOMMAND; |
| - set_interrupt_limits(access); |
| -} |
| - |
| - |
| -void StackGuard::Continue(InterruptFlag after_what) { |
| - ExecutionAccess access(isolate_); |
| - thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what); |
| + thread_local_.interrupt_flags_ &= ~flagbit; |
| if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) { |
| reset_limits(access); |
| } |
| } |
| -void StackGuard::RequestInterrupt(InterruptCallback callback, void* data) { |
| - ExecutionAccess access(isolate_); |
| - thread_local_.interrupt_flags_ |= API_INTERRUPT; |
| - thread_local_.interrupt_callback_ = callback; |
| - thread_local_.interrupt_callback_data_ = data; |
| - set_interrupt_limits(access); |
| -} |
| - |
| - |
| -void StackGuard::ClearInterrupt() { |
| - thread_local_.interrupt_callback_ = 0; |
| - thread_local_.interrupt_callback_data_ = 0; |
| - Continue(API_INTERRUPT); |
| -} |
| - |
| - |
| -bool StackGuard::IsAPIInterrupt() { |
| - ExecutionAccess access(isolate_); |
| - return thread_local_.interrupt_flags_ & API_INTERRUPT; |
| -} |
| - |
| - |
| -void StackGuard::InvokeInterruptCallback() { |
| - InterruptCallback callback = 0; |
| - void* data = 0; |
| - |
| - { |
| - ExecutionAccess access(isolate_); |
| - callback = thread_local_.interrupt_callback_; |
| - data = thread_local_.interrupt_callback_data_; |
| - thread_local_.interrupt_callback_ = NULL; |
| - thread_local_.interrupt_callback_data_ = NULL; |
| - } |
| - |
| - if (callback != NULL) { |
| - VMState<EXTERNAL> state(isolate_); |
| - HandleScope handle_scope(isolate_); |
| - callback(reinterpret_cast<v8::Isolate*>(isolate_), data); |
| +bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag, |
| + const ExecutionAccess& lock) { |
| + int flagbit = 1 << flag; |
| + bool result = (thread_local_.interrupt_flags_ & flagbit); |
| + thread_local_.interrupt_flags_ &= ~flagbit; |
| + if (!should_postpone_interrupts(lock) && !has_pending_interrupts(lock)) { |
| + reset_limits(lock); |
| } |
| + return result; |
| } |
| @@ -594,8 +441,6 @@ void StackGuard::ThreadLocal::Clear() { |
| nesting_ = 0; |
| postpone_interrupts_nesting_ = 0; |
| interrupt_flags_ = 0; |
| - interrupt_callback_ = NULL; |
| - interrupt_callback_data_ = NULL; |
| } |
| @@ -616,8 +461,6 @@ bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) { |
| nesting_ = 0; |
| postpone_interrupts_nesting_ = 0; |
| interrupt_flags_ = 0; |
| - interrupt_callback_ = NULL; |
| - interrupt_callback_data_ = NULL; |
| return should_set_stack_limits; |
| } |
| @@ -834,93 +677,52 @@ Handle<String> Execution::GetStackTraceLine(Handle<Object> recv, |
| } |
| -static Object* RuntimePreempt(Isolate* isolate) { |
| - // Clear the preempt request flag. |
| - isolate->stack_guard()->Continue(PREEMPT); |
| - |
| - if (isolate->debug()->InDebugger()) { |
| - // If currently in the debugger don't do any actual preemption but record |
| - // that preemption occoured while in the debugger. |
| - isolate->debug()->PreemptionWhileInDebugger(); |
| - } else { |
| - // Perform preemption. |
| - v8::Unlocker unlocker(reinterpret_cast<v8::Isolate*>(isolate)); |
| - Thread::YieldCPU(); |
| - } |
| - |
| - return isolate->heap()->undefined_value(); |
| -} |
| - |
| - |
| -Object* Execution::DebugBreakHelper(Isolate* isolate) { |
| +void Execution::DebugBreakHelper(Isolate* isolate) { |
| // Just continue if breaks are disabled. |
| - if (isolate->debug()->disable_break()) { |
| - return isolate->heap()->undefined_value(); |
| - } |
| + if (isolate->debug()->disable_break()) return; |
| // Ignore debug break during bootstrapping. |
| - if (isolate->bootstrapper()->IsActive()) { |
| - return isolate->heap()->undefined_value(); |
| - } |
| + if (isolate->bootstrapper()->IsActive()) return; |
| // Ignore debug break if debugger is not active. |
| - if (!isolate->debugger()->IsDebuggerActive()) { |
| - return isolate->heap()->undefined_value(); |
| - } |
| + if (!isolate->debugger()->IsDebuggerActive()) return; |
| StackLimitCheck check(isolate); |
| - if (check.HasOverflowed()) { |
| - return isolate->heap()->undefined_value(); |
| - } |
| + if (check.HasOverflowed()) return; |
| - { |
| - JavaScriptFrameIterator it(isolate); |
| + { JavaScriptFrameIterator it(isolate); |
| ASSERT(!it.done()); |
| Object* fun = it.frame()->function(); |
| if (fun && fun->IsJSFunction()) { |
| // Don't stop in builtin functions. |
| - if (JSFunction::cast(fun)->IsBuiltin()) { |
| - return isolate->heap()->undefined_value(); |
| - } |
| + if (JSFunction::cast(fun)->IsBuiltin()) return; |
| GlobalObject* global = JSFunction::cast(fun)->context()->global_object(); |
| // Don't stop in debugger functions. |
| - if (isolate->debug()->IsDebugGlobal(global)) { |
| - return isolate->heap()->undefined_value(); |
| - } |
| + if (isolate->debug()->IsDebugGlobal(global)) return; |
| } |
| } |
| // Collect the break state before clearing the flags. |
| - bool debug_command_only = |
| - isolate->stack_guard()->IsDebugCommand() && |
| - !isolate->stack_guard()->IsDebugBreak(); |
| - |
| - // Clear the debug break request flag. |
| - isolate->stack_guard()->Continue(DEBUGBREAK); |
| + bool debug_command_only = isolate->stack_guard()->CheckDebugCommand() && |
| + !isolate->stack_guard()->CheckDebugBreak(); |
| - ProcessDebugMessages(isolate, debug_command_only); |
| + isolate->stack_guard()->ClearDebugBreak(); |
| - // Return to continue execution. |
| - return isolate->heap()->undefined_value(); |
| + Execution::ProcessDebugMessages(isolate, debug_command_only); |
| } |
| void Execution::ProcessDebugMessages(Isolate* isolate, |
| bool debug_command_only) { |
| - // Clear the debug command request flag. |
| - isolate->stack_guard()->Continue(DEBUGCOMMAND); |
| + isolate->stack_guard()->ClearDebugCommand(); |
| StackLimitCheck check(isolate); |
| - if (check.HasOverflowed()) { |
| - return; |
| - } |
| + if (check.HasOverflowed()) return; |
| HandleScope scope(isolate); |
| // Enter the debugger. Just continue if we fail to enter the debugger. |
| EnterDebugger debugger(isolate); |
| - if (debugger.FailedToEnter()) { |
| - return; |
| - } |
| + if (debugger.FailedToEnter()) return; |
| // Notify the debug event listeners. Indicate auto continue if the break was |
| // a debug command break. |
| @@ -929,52 +731,45 @@ void Execution::ProcessDebugMessages(Isolate* isolate, |
| } |
| -Object* Execution::HandleStackGuardInterrupt(Isolate* isolate) { |
| - StackGuard* stack_guard = isolate->stack_guard(); |
| - if (stack_guard->ShouldPostponeInterrupts()) { |
| - return isolate->heap()->undefined_value(); |
| +Object* StackGuard::HandleInterrupts() { |
| + ExecutionAccess access(isolate_); |
|
yurys
2014/05/29 08:42:07
Scope of this lock seems too coarse. Do we really
|
| + if (should_postpone_interrupts(access)) { |
| + return isolate_->heap()->undefined_value(); |
| } |
| - if (stack_guard->IsAPIInterrupt()) { |
| - stack_guard->InvokeInterruptCallback(); |
| - stack_guard->Continue(API_INTERRUPT); |
| + if (CheckAndClearInterrupt(API_INTERRUPT, access)) { |
| + isolate_->InvokeApiInterruptCallback(); |
| } |
| - if (stack_guard->IsGCRequest()) { |
| - isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
| - "StackGuard GC request"); |
| - stack_guard->Continue(GC_REQUEST); |
| + if (CheckAndClearInterrupt(GC_REQUEST, access)) { |
| + isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, "GC interrupt"); |
| } |
| - isolate->counters()->stack_interrupts()->Increment(); |
| - isolate->counters()->runtime_profiler_ticks()->Increment(); |
| - if (stack_guard->IsDebugBreak() || stack_guard->IsDebugCommand()) { |
| - DebugBreakHelper(isolate); |
| - } |
| - if (stack_guard->IsPreempted()) RuntimePreempt(isolate); |
| - if (stack_guard->IsTerminateExecution()) { |
| - stack_guard->Continue(TERMINATE); |
| - return isolate->TerminateExecution(); |
| + if (CheckDebugBreak() || CheckDebugCommand()) { |
| + Execution::DebugBreakHelper(isolate_); |
| } |
| - if (stack_guard->IsInterrupted()) { |
| - stack_guard->Continue(INTERRUPT); |
| - return isolate->StackOverflow(); |
| + |
| + if (CheckAndClearInterrupt(TERMINATE_EXECUTION, access)) { |
| + return isolate_->TerminateExecution(); |
| } |
| - if (stack_guard->IsFullDeopt()) { |
| - stack_guard->Continue(FULL_DEOPT); |
| - Deoptimizer::DeoptimizeAll(isolate); |
| + |
| + if (CheckAndClearInterrupt(FULL_DEOPT, access)) { |
| + Deoptimizer::DeoptimizeAll(isolate_); |
| } |
| - if (stack_guard->IsDeoptMarkedAllocationSites()) { |
| - stack_guard->Continue(DEOPT_MARKED_ALLOCATION_SITES); |
| - isolate->heap()->DeoptMarkedAllocationSites(); |
| + |
| + if (CheckAndClearInterrupt(DEOPT_MARKED_ALLOCATION_SITES, access)) { |
| + isolate_->heap()->DeoptMarkedAllocationSites(); |
| } |
| - if (stack_guard->IsInstallCodeRequest()) { |
| - ASSERT(isolate->concurrent_recompilation_enabled()); |
| - stack_guard->Continue(INSTALL_CODE); |
| - isolate->optimizing_compiler_thread()->InstallOptimizedFunctions(); |
| + |
| + if (CheckAndClearInterrupt(INSTALL_CODE, access)) { |
| + ASSERT(isolate_->concurrent_recompilation_enabled()); |
| + isolate_->optimizing_compiler_thread()->InstallOptimizedFunctions(); |
| } |
| - isolate->runtime_profiler()->OptimizeNow(); |
| - return isolate->heap()->undefined_value(); |
| + |
| + isolate_->counters()->stack_interrupts()->Increment(); |
| + isolate_->counters()->runtime_profiler_ticks()->Increment(); |
| + isolate_->runtime_profiler()->OptimizeNow(); |
| + return isolate_->heap()->undefined_value(); |
| } |
| } } // namespace v8::internal |