Revision: 21208
Author: [email protected]
Date: Fri May 9 09:13:12 2014 UTC
Log: Clean up stack guard interrupts.
[email protected]
Review URL: https://codereview.chromium.org/264233005
http://code.google.com/p/v8/source/detail?r=21208
Modified:
/branches/bleeding_edge/src/api.cc
/branches/bleeding_edge/src/arm/regexp-macro-assembler-arm.cc
/branches/bleeding_edge/src/arm64/regexp-macro-assembler-arm64.cc
/branches/bleeding_edge/src/debug.cc
/branches/bleeding_edge/src/debug.h
/branches/bleeding_edge/src/execution.cc
/branches/bleeding_edge/src/execution.h
/branches/bleeding_edge/src/heap.cc
/branches/bleeding_edge/src/ia32/regexp-macro-assembler-ia32.cc
/branches/bleeding_edge/src/incremental-marking.cc
/branches/bleeding_edge/src/isolate.cc
/branches/bleeding_edge/src/isolate.h
/branches/bleeding_edge/src/mips/regexp-macro-assembler-mips.cc
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/v8threads.cc
/branches/bleeding_edge/src/x64/regexp-macro-assembler-x64.cc
/branches/bleeding_edge/test/cctest/test-debug.cc
=======================================
--- /branches/bleeding_edge/src/api.cc Fri May 9 08:40:18 2014 UTC
+++ /branches/bleeding_edge/src/api.cc Fri May 9 09:13:12 2014 UTC
@@ -6464,7 +6464,8 @@
void V8::TerminateExecution(Isolate* isolate) {
-
reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->TerminateExecution();
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ i_isolate->stack_guard()->RequestTerminateExecution();
}
@@ -6477,18 +6478,24 @@
void V8::CancelTerminateExecution(Isolate* isolate) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
- i_isolate->stack_guard()->CancelTerminateExecution();
+ i_isolate->stack_guard()->ClearTerminateExecution();
+ i_isolate->CancelTerminateExecution();
}
void Isolate::RequestInterrupt(InterruptCallback callback, void* data) {
- reinterpret_cast<i::Isolate*>(this)->stack_guard()->RequestInterrupt(
- callback, data);
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(this);
+ i_isolate->set_api_interrupt_callback(callback);
+ i_isolate->set_api_interrupt_callback_data(data);
+ i_isolate->stack_guard()->RequestApiInterrupt();
}
void Isolate::ClearInterrupt() {
- reinterpret_cast<i::Isolate*>(this)->stack_guard()->ClearInterrupt();
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(this);
+ i_isolate->stack_guard()->ClearApiInterrupt();
+ i_isolate->set_api_interrupt_callback(NULL);
+ i_isolate->set_api_interrupt_callback_data(NULL);
}
@@ -6810,13 +6817,13 @@
void Debug::DebugBreak(Isolate* isolate) {
- reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->DebugBreak();
+
reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->RequestDebugBreak();
}
void Debug::CancelDebugBreak(Isolate* isolate) {
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
- internal_isolate->stack_guard()->Continue(i::DEBUGBREAK);
+ internal_isolate->stack_guard()->ClearDebugBreak();
}
=======================================
--- /branches/bleeding_edge/src/arm/regexp-macro-assembler-arm.cc Tue Apr
29 06:42:26 2014 UTC
+++ /branches/bleeding_edge/src/arm/regexp-macro-assembler-arm.cc Fri May
9 09:13:12 2014 UTC
@@ -1071,7 +1071,7 @@
ASSERT(*return_address <=
re_code->instruction_start() + re_code->instruction_size());
- Object* result = Execution::HandleStackGuardInterrupt(isolate);
+ Object* result = isolate->stack_guard()->HandleInterrupts();
if (*code_handle != re_code) { // Return address no longer valid
int delta = code_handle->address() - re_code->address();
=======================================
--- /branches/bleeding_edge/src/arm64/regexp-macro-assembler-arm64.cc Wed
May 7 06:40:50 2014 UTC
+++ /branches/bleeding_edge/src/arm64/regexp-macro-assembler-arm64.cc Fri
May 9 09:13:12 2014 UTC
@@ -1315,7 +1315,7 @@
ASSERT(*return_address <=
re_code->instruction_start() + re_code->instruction_size());
- Object* result = Execution::HandleStackGuardInterrupt(isolate);
+ Object* result = isolate->stack_guard()->HandleInterrupts();
if (*code_handle != re_code) { // Return address no longer valid
int delta = code_handle->address() - re_code->address();
=======================================
--- /branches/bleeding_edge/src/debug.cc Fri May 9 08:42:17 2014 UTC
+++ /branches/bleeding_edge/src/debug.cc Fri May 9 09:13:12 2014 UTC
@@ -526,7 +526,7 @@
thread_local_.after_break_target_ = 0;
// TODO(isolates): frames_are_dropped_?
thread_local_.debugger_entry_ = NULL;
- thread_local_.pending_interrupts_ = 0;
+ thread_local_.has_pending_interrupt_ = false;
thread_local_.restarter_frame_function_pointer_ = NULL;
}
@@ -858,13 +858,6 @@
GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location()));
debug_context_ = Handle<Context>();
}
-
-
-// Set the flag indicating that preemption happened during debugging.
-void Debug::PreemptionWhileInDebugger() {
- ASSERT(InDebugger());
- Debug::set_interrupts_pending(PREEMPT);
-}
Object* Debug::Break(Arguments args) {
@@ -2961,7 +2954,7 @@
// Clear any pending debug break if this is a real break.
if (!auto_continue) {
- isolate_->debug()->clear_interrupt_pending(DEBUGBREAK);
+ isolate_->debug()->set_has_pending_interrupt(false);
}
// Create the execution state.
@@ -3107,7 +3100,7 @@
// added. It should be enough to clear the flag only once while we are
in the
// debugger.
ASSERT(isolate_->debug()->InDebugger());
- isolate_->stack_guard()->Continue(DEBUGCOMMAND);
+ isolate_->stack_guard()->ClearDebugCommand();
// Notify the debugger that a debug event has occurred unless auto
continue is
// active in which case no event is send.
@@ -3355,7 +3348,7 @@
// Set the debug command break flag to have the command processed.
if (!isolate_->debug()->InDebugger()) {
- isolate_->stack_guard()->DebugCommand();
+ isolate_->stack_guard()->RequestDebugCommand();
}
MessageDispatchHelperThread* dispatch_thread;
@@ -3383,7 +3376,7 @@
// Set the debug command break flag to have the command processed.
if (!isolate_->debug()->InDebugger()) {
- isolate_->stack_guard()->DebugCommand();
+ isolate_->stack_guard()->RequestDebugCommand();
}
}
@@ -3486,9 +3479,6 @@
has_js_frames_(!it_.done()),
save_(isolate_) {
Debug* debug = isolate_->debug();
- ASSERT(prev_ != NULL || !debug->is_interrupt_pending(PREEMPT));
- ASSERT(prev_ != NULL || !debug->is_interrupt_pending(DEBUGBREAK));
-
// Link recursive debugger entry.
debug->set_debugger_entry(this);
@@ -3529,30 +3519,24 @@
if (!isolate_->has_pending_exception()) {
// Try to avoid any pending debug break breaking in the clear mirror
// cache JavaScript code.
- if (isolate_->stack_guard()->IsDebugBreak()) {
- debug->set_interrupts_pending(DEBUGBREAK);
- isolate_->stack_guard()->Continue(DEBUGBREAK);
+ if (isolate_->stack_guard()->CheckDebugBreak()) {
+ debug->set_has_pending_interrupt(true);
+ isolate_->stack_guard()->ClearDebugBreak();
}
debug->ClearMirrorCache();
}
- // Request preemption and debug break when leaving the last debugger
entry
- // if any of these where recorded while debugging.
- if (debug->is_interrupt_pending(PREEMPT)) {
- // This re-scheduling of preemption is to avoid starvation in some
- // debugging scenarios.
- debug->clear_interrupt_pending(PREEMPT);
- isolate_->stack_guard()->Preempt();
- }
- if (debug->is_interrupt_pending(DEBUGBREAK)) {
- debug->clear_interrupt_pending(DEBUGBREAK);
- isolate_->stack_guard()->DebugBreak();
+ // Request debug break when leaving the last debugger entry
+ // if one was recorded while debugging.
+ if (debug->has_pending_interrupt()) {
+ debug->set_has_pending_interrupt(false);
+ isolate_->stack_guard()->RequestDebugBreak();
}
// If there are commands in the queue when leaving the debugger request
// that these commands are processed.
if (isolate_->debugger()->HasCommands()) {
- isolate_->stack_guard()->DebugCommand();
+ isolate_->stack_guard()->RequestDebugCommand();
}
// If leaving the debugger with the debugger no longer active unload
it.
=======================================
--- /branches/bleeding_edge/src/debug.h Thu May 8 18:00:26 2014 UTC
+++ /branches/bleeding_edge/src/debug.h Fri May 9 09:13:12 2014 UTC
@@ -216,7 +216,6 @@
void Unload();
bool IsLoaded() { return !debug_context_.is_null(); }
bool InDebugger() { return thread_local_.debugger_entry_ != NULL; }
- void PreemptionWhileInDebugger();
Object* Break(Arguments args);
bool SetBreakPoint(Handle<JSFunction> function,
@@ -317,18 +316,13 @@
}
// Check whether any of the specified interrupts are pending.
- bool is_interrupt_pending(InterruptFlag what) {
- return (thread_local_.pending_interrupts_ & what) != 0;
+ bool has_pending_interrupt() {
+ return thread_local_.has_pending_interrupt_;
}
// Set specified interrupts as pending.
- void set_interrupts_pending(InterruptFlag what) {
- thread_local_.pending_interrupts_ |= what;
- }
-
- // Clear specified interrupts from pending.
- void clear_interrupt_pending(InterruptFlag what) {
- thread_local_.pending_interrupts_ &= ~static_cast<int>(what);
+ void set_has_pending_interrupt(bool value) {
+ thread_local_.has_pending_interrupt_ = value;
}
// Getter and setter for the disable break state.
@@ -585,7 +579,7 @@
EnterDebugger* debugger_entry_;
// Pending interrupts scheduled while debugging.
- int pending_interrupts_;
+ bool has_pending_interrupt_;
// When restarter frame is on stack, stores the address
// of the pointer to function being restarted. Otherwise (most of the
time)
=======================================
--- /branches/bleeding_edge/src/execution.cc Fri May 2 08:00:47 2014 UTC
+++ /branches/bleeding_edge/src/execution.cc Fri May 9 09:13:12 2014 UTC
@@ -366,190 +366,37 @@
}
-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;
+ thread_local_.interrupt_flags_ |= flagbit;
set_interrupt_limits(access);
}
-bool StackGuard::IsPreempted() {
+void StackGuard::ClearInterrupt(int flagbit) {
ExecutionAccess access(isolate_);
- return thread_local_.interrupt_flags_ & PREEMPT;
-}
-
-
-void StackGuard::Preempt() {
- ExecutionAccess access(isolate_);
- thread_local_.interrupt_flags_ |= PREEMPT;
- set_interrupt_limits(access);
-}
-
-
-bool StackGuard::IsTerminateExecution() {
- 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 @@
nesting_ = 0;
postpone_interrupts_nesting_ = 0;
interrupt_flags_ = 0;
- interrupt_callback_ = NULL;
- interrupt_callback_data_ = NULL;
}
@@ -616,8 +461,6 @@
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 @@
}
-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 @@
}
-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_);
+ 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
=======================================
--- /branches/bleeding_edge/src/execution.h Fri Apr 25 11:00:37 2014 UTC
+++ /branches/bleeding_edge/src/execution.h Fri May 9 09:13:12 2014 UTC
@@ -10,21 +10,6 @@
namespace v8 {
namespace internal {
-// Flag used to set the interrupt causes.
-enum InterruptFlag {
- INTERRUPT = 1 << 0,
- DEBUGBREAK = 1 << 1,
- DEBUGCOMMAND = 1 << 2,
- PREEMPT = 1 << 3,
- TERMINATE = 1 << 4,
- GC_REQUEST = 1 << 5,
- FULL_DEOPT = 1 << 6,
- INSTALL_CODE = 1 << 7,
- API_INTERRUPT = 1 << 8,
- DEOPT_MARKED_ALLOCATION_SITES = 1 << 9
-};
-
-
class Execution V8_FINAL : public AllStatic {
public:
// Call a function, the caller supplies a receiver and an array
@@ -119,13 +104,9 @@
Handle<Object> pos,
Handle<Object> is_global);
- static Object* DebugBreakHelper(Isolate* isolate);
+ static void DebugBreakHelper(Isolate* isolate);
static void ProcessDebugMessages(Isolate* isolate, bool
debug_command_only);
- // If the stack guard is triggered, but it is not an actual
- // stack overflow, then handle the interruption accordingly.
- static Object* HandleStackGuardInterrupt(Isolate* isolate);
-
// Get a function delegate (or undefined) for the given non-function
// object. Used for support calling objects as functions.
static Handle<Object> GetFunctionDelegate(Isolate* isolate,
@@ -171,31 +152,23 @@
void ClearThread(const ExecutionAccess& lock);
bool IsStackOverflow();
- bool IsPreempted();
- void Preempt();
- bool IsInterrupted();
- void Interrupt();
- bool IsTerminateExecution();
- void TerminateExecution();
- void CancelTerminateExecution();
- bool IsDebugBreak();
- void DebugBreak();
- bool IsDebugCommand();
- void DebugCommand();
- bool IsGCRequest();
- void RequestGC();
- bool IsInstallCodeRequest();
- void RequestInstallCode();
- bool IsFullDeopt();
- void FullDeopt();
- bool IsDeoptMarkedAllocationSites();
- void DeoptMarkedAllocationSites();
- void Continue(InterruptFlag after_what);
- void RequestInterrupt(InterruptCallback callback, void* data);
- void ClearInterrupt();
- bool IsAPIInterrupt();
- void InvokeInterruptCallback();
+#define INTERRUPT_LIST(V) \
+ V(DEBUGBREAK, DebugBreak) \
+ V(DEBUGCOMMAND, DebugCommand) \
+ V(TERMINATE_EXECUTION, TerminateExecution) \
+ V(GC_REQUEST, GC) \
+ V(FULL_DEOPT, FullDeopt) \
+ V(INSTALL_CODE, InstallCode) \
+ V(API_INTERRUPT, ApiInterrupt) \
+ V(DEOPT_MARKED_ALLOCATION_SITES, DeoptMarkedAllocationSites)
+
+#define V(NAME, Name) \
+ inline bool Check##Name() { return CheckInterrupt(1 << NAME); } \
+ inline void Request##Name() { RequestInterrupt(1 << NAME); } \
+ inline void Clear##Name() { ClearInterrupt(1 << NAME); }
+ INTERRUPT_LIST(V)
+#undef V
// This provides an asynchronous read of the stack limits for the current
// thread. There are no locks protecting this, but it is assumed that
you
@@ -218,11 +191,29 @@
Address address_of_real_jslimit() {
return reinterpret_cast<Address>(&thread_local_.real_jslimit_);
}
- bool ShouldPostponeInterrupts();
+
+ // If the stack guard is triggered, but it is not an actual
+ // stack overflow, then handle the interruption accordingly.
+ Object* HandleInterrupts();
private:
StackGuard();
+// Flag used to set the interrupt causes.
+enum InterruptFlag {
+#define V(NAME, Name) NAME,
+ INTERRUPT_LIST(V)
+#undef V
+ NUMBER_OF_INTERRUPTS
+};
+
+ bool CheckInterrupt(int flagbit);
+ void RequestInterrupt(int flagbit);
+ void ClearInterrupt(int flagbit);
+ bool CheckAndClearInterrupt(InterruptFlag flag, const ExecutionAccess&
lock);
+
+ void InvokeApiInterruptCallback();
+
// You should hold the ExecutionAccess lock when calling this method.
bool has_pending_interrupts(const ExecutionAccess& lock) {
// Sanity check: We shouldn't be asking about pending interrupts
@@ -282,9 +273,6 @@
int nesting_;
int postpone_interrupts_nesting_;
int interrupt_flags_;
-
- InterruptCallback interrupt_callback_;
- void* interrupt_callback_data_;
};
// TODO(isolates): Technically this could be calculated directly from a
=======================================
--- /branches/bleeding_edge/src/heap.cc Fri May 9 09:02:40 2014 UTC
+++ /branches/bleeding_edge/src/heap.cc Fri May 9 09:13:12 2014 UTC
@@ -514,7 +514,7 @@
}
if (trigger_deoptimization) {
- isolate_->stack_guard()->DeoptMarkedAllocationSites();
+ isolate_->stack_guard()->RequestDeoptMarkedAllocationSites();
}
FlushAllocationSitesScratchpad();
@@ -1113,7 +1113,7 @@
// code which should be tenured in local pretenuring mode.
if (FLAG_pretenuring) {
if (!FLAG_allocation_site_pretenuring) {
- isolate_->stack_guard()->FullDeopt();
+ isolate_->stack_guard()->RequestFullDeopt();
}
}
} else if (new_space_high_promotion_mode_active_ &&
@@ -1130,7 +1130,7 @@
// Trigger deoptimization here to turn off global pretenuring as soon
as
// possible.
if (FLAG_pretenuring && !FLAG_allocation_site_pretenuring) {
- isolate_->stack_guard()->FullDeopt();
+ isolate_->stack_guard()->RequestFullDeopt();
}
}
@@ -1749,7 +1749,7 @@
}
cur = casted->weak_next();
}
- if (marked) isolate_->stack_guard()->DeoptMarkedAllocationSites();
+ if (marked) isolate_->stack_guard()->RequestDeoptMarkedAllocationSites();
}
=======================================
--- /branches/bleeding_edge/src/ia32/regexp-macro-assembler-ia32.cc Tue Apr
29 06:42:26 2014 UTC
+++ /branches/bleeding_edge/src/ia32/regexp-macro-assembler-ia32.cc Fri
May 9 09:13:12 2014 UTC
@@ -1103,7 +1103,7 @@
ASSERT(*return_address <=
re_code->instruction_start() + re_code->instruction_size());
- Object* result = Execution::HandleStackGuardInterrupt(isolate);
+ Object* result = isolate->stack_guard()->HandleInterrupts();
if (*code_handle != re_code) { // Return address no longer valid
int delta = code_handle->address() - re_code->address();
=======================================
--- /branches/bleeding_edge/src/incremental-marking.cc Wed Apr 30 12:25:18
2014 UTC
+++ /branches/bleeding_edge/src/incremental-marking.cc Fri May 9 09:13:12
2014 UTC
@@ -797,7 +797,7 @@
}
}
}
- heap_->isolate()->stack_guard()->Continue(GC_REQUEST);
+ heap_->isolate()->stack_guard()->ClearGC();
state_ = STOPPED;
is_compacting_ = false;
}
@@ -814,7 +814,7 @@
RecordWriteStub::STORE_BUFFER_ONLY);
DeactivateIncrementalWriteBarrier();
ASSERT(marking_deque_.IsEmpty());
- heap_->isolate()->stack_guard()->Continue(GC_REQUEST);
+ heap_->isolate()->stack_guard()->ClearGC();
}
=======================================
--- /branches/bleeding_edge/src/isolate.cc Fri May 9 08:40:18 2014 UTC
+++ /branches/bleeding_edge/src/isolate.cc Fri May 9 09:13:12 2014 UTC
@@ -833,6 +833,20 @@
clear_scheduled_exception();
}
}
+
+
+void Isolate::InvokeApiInterruptCallback() {
+ InterruptCallback callback = api_interrupt_callback_;
+ void* data = api_interrupt_callback_data_;
+ api_interrupt_callback_ = NULL;
+ api_interrupt_callback_data_ = NULL;
+
+ if (callback != NULL) {
+ VMState<EXTERNAL> state(this);
+ HandleScope handle_scope(this);
+ callback(reinterpret_cast<v8::Isolate*>(this), data);
+ }
+}
Object* Isolate::Throw(Object* exception, MessageLocation* location) {
=======================================
--- /branches/bleeding_edge/src/isolate.h Fri May 9 08:40:18 2014 UTC
+++ /branches/bleeding_edge/src/isolate.h Fri May 9 09:13:12 2014 UTC
@@ -359,6 +359,8 @@
V(int, max_available_threads,
0) \
V(uint32_t, per_isolate_assert_data,
0xFFFFFFFFu) \
V(DebuggerAgent*, debugger_agent_instance,
NULL) \
+ V(InterruptCallback, api_interrupt_callback,
NULL) \
+ V(void*, api_interrupt_callback_data,
NULL) \
ISOLATE_INIT_SIMULATOR_LIST(V)
#define THREAD_LOCAL_TOP_ACCESSOR(type, name) \
@@ -758,6 +760,8 @@
Object* TerminateExecution();
void CancelTerminateExecution();
+ void InvokeApiInterruptCallback();
+
// Administration
void Iterate(ObjectVisitor* v);
void Iterate(ObjectVisitor* v, ThreadLocalTop* t);
=======================================
--- /branches/bleeding_edge/src/mips/regexp-macro-assembler-mips.cc Tue Apr
29 06:42:26 2014 UTC
+++ /branches/bleeding_edge/src/mips/regexp-macro-assembler-mips.cc Fri
May 9 09:13:12 2014 UTC
@@ -1130,7 +1130,7 @@
ASSERT(*return_address <=
re_code->instruction_start() + re_code->instruction_size());
- Object* result = Execution::HandleStackGuardInterrupt(isolate);
+ Object* result = isolate->stack_guard()->HandleInterrupts();
if (*code_handle != re_code) { // Return address no longer valid.
int delta = code_handle->address() - re_code->address();
=======================================
--- /branches/bleeding_edge/src/runtime.cc Thu May 8 09:33:11 2014 UTC
+++ /branches/bleeding_edge/src/runtime.cc Fri May 9 09:13:12 2014 UTC
@@ -9601,7 +9601,7 @@
return isolate->StackOverflow();
}
- return Execution::HandleStackGuardInterrupt(isolate);
+ return isolate->stack_guard()->HandleInterrupts();
}
@@ -9625,7 +9625,7 @@
RUNTIME_FUNCTION(RuntimeHidden_Interrupt) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 0);
- return Execution::HandleStackGuardInterrupt(isolate);
+ return isolate->stack_guard()->HandleInterrupts();
}
@@ -10804,7 +10804,8 @@
RUNTIME_FUNCTION(Runtime_DebugBreak) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 0);
- return Execution::DebugBreakHelper(isolate);
+ Execution::DebugBreakHelper(isolate);
+ return isolate->heap()->undefined_value();
}
@@ -10841,7 +10842,7 @@
RUNTIME_FUNCTION(Runtime_Break) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 0);
- isolate->stack_guard()->DebugBreak();
+ isolate->stack_guard()->RequestDebugBreak();
return isolate->heap()->undefined_value();
}
=======================================
--- /branches/bleeding_edge/src/v8threads.cc Tue Apr 29 06:42:26 2014 UTC
+++ /branches/bleeding_edge/src/v8threads.cc Fri May 9 09:13:12 2014 UTC
@@ -145,7 +145,7 @@
from = isolate_->bootstrapper()->RestoreState(from);
per_thread->set_thread_state(NULL);
if (state->terminate_on_restore()) {
- isolate_->stack_guard()->TerminateExecution();
+ isolate_->stack_guard()->RequestTerminateExecution();
state->set_terminate_on_restore(false);
}
state->set_id(ThreadId::Invalid());
=======================================
--- /branches/bleeding_edge/src/x64/regexp-macro-assembler-x64.cc Tue Apr
29 06:42:26 2014 UTC
+++ /branches/bleeding_edge/src/x64/regexp-macro-assembler-x64.cc Fri May
9 09:13:12 2014 UTC
@@ -1210,7 +1210,7 @@
ASSERT(*return_address <=
re_code->instruction_start() + re_code->instruction_size());
- Object* result = Execution::HandleStackGuardInterrupt(isolate);
+ Object* result = isolate->stack_guard()->HandleInterrupts();
if (*code_handle != re_code) { // Return address no longer valid
intptr_t delta = code_handle->address() - re_code->address();
=======================================
--- /branches/bleeding_edge/test/cctest/test-debug.cc Mon Apr 28 12:08:17
2014 UTC
+++ /branches/bleeding_edge/test/cctest/test-debug.cc Fri May 9 09:13:12
2014 UTC
@@ -6834,18 +6834,18 @@
} else if (message.IsEvent() && message.GetEvent() == v8::AfterCompile) {
i::HandleScope scope(isolate);
- bool is_debug_break = isolate->stack_guard()->IsDebugBreak();
+ bool is_debug_break = isolate->stack_guard()->CheckDebugBreak();
// Force DebugBreak flag while serializer is working.
- isolate->stack_guard()->DebugBreak();
+ isolate->stack_guard()->RequestDebugBreak();
// Force serialization to trigger some internal JS execution.
message.GetJSON();
// Restore previous state.
if (is_debug_break) {
- isolate->stack_guard()->DebugBreak();
+ isolate->stack_guard()->RequestDebugBreak();
} else {
- isolate->stack_guard()->Continue(i::DEBUGBREAK);
+ isolate->stack_guard()->ClearDebugBreak();
}
}
}
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.