diff --git a/deps/v8/build/common.gypi b/deps/v8/build/common.gypi index 1609197876..7f084b8c1d 100644 --- a/deps/v8/build/common.gypi +++ b/deps/v8/build/common.gypi @@ -239,6 +239,7 @@ 'WIN32', ], 'msvs_configuration_attributes': { + 'OutputDirectory': '<(DEPTH)\\build\\$(ConfigurationName)', 'IntermediateDirectory': '$(OutDir)\\obj\\$(ProjectName)', 'CharacterSet': '1', }, @@ -270,7 +271,7 @@ 'target_conditions': [ ['_toolset=="host"', { 'variables': { - 'm32flag': ' /dev/null 2>&1) && echo "-m32" || true)', + 'm32flag': ' /dev/null 2>&1) && echo -n "-m32" || true)', }, 'cflags': [ '<(m32flag)' ], 'ldflags': [ '<(m32flag)' ], @@ -280,7 +281,7 @@ }], ['_toolset=="target"', { 'variables': { - 'm32flag': ' /dev/null 2>&1) && echo "-m32" || true)', + 'm32flag': ' /dev/null 2>&1) && echo -n "-m32" || true)', }, 'cflags': [ '<(m32flag)' ], 'ldflags': [ '<(m32flag)' ], @@ -323,7 +324,7 @@ }, 'conditions': [ ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd"', { - 'cflags': [ '-Wno-unused-parameter', + 'cflags': [ '-Wall', '<(werror)', '-W', '-Wno-unused-parameter', '-Wnon-virtual-dtor', '-Woverloaded-virtual' ], }], ], @@ -332,6 +333,10 @@ 'conditions': [ ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd" \ or OS=="android"', { + 'cflags!': [ + '-O2', + '-Os', + ], 'cflags': [ '-fdata-sections', '-ffunction-sections', diff --git a/deps/v8/src/debug.cc b/deps/v8/src/debug.cc index 543ce9f24d..ed70c6a8d9 100644 --- a/deps/v8/src/debug.cc +++ b/deps/v8/src/debug.cc @@ -892,16 +892,6 @@ void Debug::Iterate(ObjectVisitor* v) { } -void Debug::PutValuesOnStackAndDie(int start, - Address c_entry_fp, - Address last_fp, - Address larger_fp, - int count, - int end) { - OS::Abort(); -} - - Object* Debug::Break(Arguments args) { Heap* heap = isolate_->heap(); HandleScope scope(isolate_); @@ -999,41 +989,17 @@ Object* Debug::Break(Arguments args) { it.Advance(); } - // Catch the cases that would lead to crashes and capture - // - C entry FP at which to start stack crawl. - // - FP of the frame at which we plan to stop stepping out (last FP). - // - current FP that's larger than last FP. - // - Counter for the number of steps to step out. - if (it.done()) { - // We crawled the entire stack, never reaching last_fp_. - PutValuesOnStackAndDie(0xBEEEEEEE, - frame->fp(), - thread_local_.last_fp_, - NULL, - count, - 0xFEEEEEEE); - } else if (it.frame()->fp() != thread_local_.last_fp_) { - // We crawled over last_fp_, without getting a match. - PutValuesOnStackAndDie(0xBEEEEEEE, - frame->fp(), - thread_local_.last_fp_, - it.frame()->fp(), - count, - 0xFEEEEEEE); + // Check that we indeed found the frame we are looking for. + CHECK(!it.done() && (it.frame()->fp() == thread_local_.last_fp_)); + if (step_count > 1) { + // Save old count and action to continue stepping after + // StepOut + thread_local_.queued_step_count_ = step_count - 1; } - // If we found original frame - if (it.frame()->fp() == thread_local_.last_fp_) { - if (step_count > 1) { - // Save old count and action to continue stepping after - // StepOut - thread_local_.queued_step_count_ = step_count - 1; - } - - // Set up for StepOut to reach target frame - step_action = StepOut; - step_count = count; - } + // Set up for StepOut to reach target frame + step_action = StepOut; + step_count = count; } // Clear all current stepping setup. diff --git a/deps/v8/src/debug.h b/deps/v8/src/debug.h index d9c966c37f..2adbd24338 100644 --- a/deps/v8/src/debug.h +++ b/deps/v8/src/debug.h @@ -232,12 +232,6 @@ class Debug { void PreemptionWhileInDebugger(); void Iterate(ObjectVisitor* v); - NO_INLINE(void PutValuesOnStackAndDie(int start, - Address c_entry_fp, - Address last_fp, - Address larger_fp, - int count, - int end)); Object* Break(Arguments args); void SetBreakPoint(Handle shared, Handle break_point_object, diff --git a/deps/v8/src/execution.cc b/deps/v8/src/execution.cc index 5618975673..40ed7de414 100644 --- a/deps/v8/src/execution.cc +++ b/deps/v8/src/execution.cc @@ -132,6 +132,12 @@ static Handle Invoke(bool is_construct, V8::FatalProcessOutOfMemory("JS", true); } } +#ifdef ENABLE_DEBUGGER_SUPPORT + // Reset stepping state when script exits with uncaught exception. + if (isolate->debugger()->IsDebuggerActive()) { + isolate->debug()->ClearStepping(); + } +#endif // ENABLE_DEBUGGER_SUPPORT return Handle(); } else { isolate->clear_pending_message(); diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc index 199371fe46..de3a55e5d1 100644 --- a/deps/v8/src/runtime.cc +++ b/deps/v8/src/runtime.cc @@ -4842,21 +4842,28 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) { // Check whether debugger and is about to step into the callback that is passed // to a built-in function such as Array.forEach. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugCallbackSupportsStepping) { - if (!isolate->IsDebuggerActive()) return isolate->heap()->false_value(); +#ifdef ENABLE_DEBUGGER_SUPPORT + if (!isolate->IsDebuggerActive() || !isolate->debug()->StepInActive()) { + return isolate->heap()->false_value(); + } CONVERT_ARG_CHECKED(Object, callback, 0); // We do not step into the callback if it's a builtin or not even a function. if (!callback->IsJSFunction() || JSFunction::cast(callback)->IsBuiltin()) { return isolate->heap()->false_value(); } return isolate->heap()->true_value(); +#else + return isolate->heap()->false_value(); +#endif // ENABLE_DEBUGGER_SUPPORT } // Set one shot breakpoints for the callback function that is passed to a // built-in function such as Array.forEach to enable stepping into the callback. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrepareStepInIfStepping) { +#ifdef ENABLE_DEBUGGER_SUPPORT Debug* debug = isolate->debug(); - if (!debug->IsStepping()) return NULL; + if (!debug->IsStepping()) return isolate->heap()->undefined_value(); CONVERT_ARG_CHECKED(Object, callback, 0); HandleScope scope(isolate); Handle shared_info(JSFunction::cast(callback)->shared()); @@ -4865,7 +4872,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrepareStepInIfStepping) { // again, we need to clear the step out at this point. debug->ClearStepOut(); debug->FloodWithOneShot(shared_info); - return NULL; +#endif // ENABLE_DEBUGGER_SUPPORT + return isolate->heap()->undefined_value(); } diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc index bd350fe202..2243106e76 100644 --- a/deps/v8/src/version.cc +++ b/deps/v8/src/version.cc @@ -35,7 +35,7 @@ #define MAJOR_VERSION 3 #define MINOR_VERSION 11 #define BUILD_NUMBER 10 -#define PATCH_LEVEL 14 +#define PATCH_LEVEL 15 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) #define IS_CANDIDATE_VERSION 0 diff --git a/deps/v8/test/cctest/test-debug.cc b/deps/v8/test/cctest/test-debug.cc index e40f406c3c..166b762913 100644 --- a/deps/v8/test/cctest/test-debug.cc +++ b/deps/v8/test/cctest/test-debug.cc @@ -7350,4 +7350,47 @@ TEST(DebugBreakInline) { } +static void DebugEventStepNext(v8::DebugEvent event, + v8::Handle exec_state, + v8::Handle event_data, + v8::Handle data) { + if (event == v8::Break) { + PrepareStep(StepNext); + } +} + + +static void RunScriptInANewCFrame(const char* source) { + v8::TryCatch try_catch; + CompileRun(source); + CHECK(try_catch.HasCaught()); +} + + +TEST(Regress131642) { + // Bug description: + // When doing StepNext through the first script, the debugger is not reset + // after exiting through exception. A flawed implementation enabling the + // debugger to step into Array.prototype.forEach breaks inside the callback + // for forEach in the second script under the assumption that we are in a + // recursive call. In an attempt to step out, we crawl the stack using the + // recorded frame pointer from the first script and fail when not finding it + // on the stack. + v8::HandleScope scope; + DebugLocalContext env; + v8::Debug::SetDebugEventListener(DebugEventStepNext); + + // We step through the first script. It exits through an exception. We run + // this inside a new frame to record a different FP than the second script + // would expect. + const char* script_1 = "debugger; throw new Error();"; + RunScriptInANewCFrame(script_1); + + // The second script uses forEach. + const char* script_2 = "[0].forEach(function() { });"; + CompileRun(script_2); + + v8::Debug::SetDebugEventListener(NULL); +} + #endif // ENABLE_DEBUGGER_SUPPORT