Commit 0da86e12 authored by yurys@chromium.org's avatar yurys@chromium.org

Fix an issue with debugger 'step in' when calling function has local...

Fix an issue with debugger 'step in' when calling function has local variables.Corresponding Chromium bug:http://code.google.com/p/chromium/issues/detail?id=15824
Review URL: http://codereview.chromium.org/149326

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2426 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 875dbe65
...@@ -1260,6 +1260,7 @@ void Debug::SetBreak(StackFrame::Id break_frame_id, int break_id) { ...@@ -1260,6 +1260,7 @@ void Debug::SetBreak(StackFrame::Id break_frame_id, int break_id) {
// Handle stepping into a function. // Handle stepping into a function.
void Debug::HandleStepIn(Handle<JSFunction> function, void Debug::HandleStepIn(Handle<JSFunction> function,
Handle<Object> holder,
Address fp, Address fp,
bool is_constructor) { bool is_constructor) {
// If the frame pointer is not supplied by the caller find it. // If the frame pointer is not supplied by the caller find it.
...@@ -1285,21 +1286,12 @@ void Debug::HandleStepIn(Handle<JSFunction> function, ...@@ -1285,21 +1286,12 @@ void Debug::HandleStepIn(Handle<JSFunction> function,
Builtins::builtin(Builtins::FunctionCall)) { Builtins::builtin(Builtins::FunctionCall)) {
// Handle function.apply and function.call separately to flood the // Handle function.apply and function.call separately to flood the
// function to be called and not the code for Builtins::FunctionApply or // function to be called and not the code for Builtins::FunctionApply or
// Builtins::FunctionCall. At the point of the call IC to call either // Builtins::FunctionCall. The receiver of call/apply is the target
// Builtins::FunctionApply or Builtins::FunctionCall the expression // function.
// stack has the following content: if (!holder.is_null() && holder->IsJSFunction()) {
// symbol "apply" or "call" Handle<SharedFunctionInfo> shared_info(
// function apply or call was called on JSFunction::cast(*holder)->shared());
// receiver for apply or call (first parameter to apply or call) Debug::FloodWithOneShot(shared_info);
// ... further arguments to apply or call.
JavaScriptFrameIterator it;
ASSERT(it.frame()->fp() == fp);
ASSERT(it.frame()->GetExpression(1)->IsJSFunction());
if (it.frame()->GetExpression(1)->IsJSFunction()) {
Handle<JSFunction>
actual_function(JSFunction::cast(it.frame()->GetExpression(1)));
Handle<SharedFunctionInfo> actual_shared(actual_function->shared());
Debug::FloodWithOneShot(actual_shared);
} }
} else { } else {
Debug::FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared())); Debug::FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared()));
......
...@@ -270,6 +270,7 @@ class Debug { ...@@ -270,6 +270,7 @@ class Debug {
static bool StepInActive() { return thread_local_.step_into_fp_ != 0; } static bool StepInActive() { return thread_local_.step_into_fp_ != 0; }
static void HandleStepIn(Handle<JSFunction> function, static void HandleStepIn(Handle<JSFunction> function,
Handle<Object> holder,
Address fp, Address fp,
bool is_constructor); bool is_constructor);
static Address step_in_fp() { return thread_local_.step_into_fp_; } static Address step_in_fp() { return thread_local_.step_into_fp_; }
......
...@@ -397,7 +397,7 @@ Object* CallIC::LoadFunction(State state, ...@@ -397,7 +397,7 @@ Object* CallIC::LoadFunction(State state,
// cause GC. // cause GC.
HandleScope scope; HandleScope scope;
Handle<JSFunction> function(JSFunction::cast(result)); Handle<JSFunction> function(JSFunction::cast(result));
Debug::HandleStepIn(function, fp(), false); Debug::HandleStepIn(function, object, fp(), false);
return *function; return *function;
} }
#endif #endif
......
...@@ -4316,7 +4316,7 @@ static Object* Runtime_NewObject(Arguments args) { ...@@ -4316,7 +4316,7 @@ static Object* Runtime_NewObject(Arguments args) {
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
// Handle stepping into constructors if step into is active. // Handle stepping into constructors if step into is active.
if (Debug::StepInActive()) { if (Debug::StepInActive()) {
Debug::HandleStepIn(function, 0, true); Debug::HandleStepIn(function, Handle<Object>::null(), 0, true);
} }
#endif #endif
......
// Copyright 2008 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --expose-debug-as debug
// Get the Debug object exposed from the debug context global object.
Debug = debug.Debug
var exception = null;
var state = 0;
// Simple debug event handler which first time will cause 'step in' action
// to get into g.call and than check that execution is pauesed inside
// function 'g'.
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
if (state == 0) {
// Step into f2.call:
exec_state.prepareStep(Debug.StepAction.StepIn, 2);
state = 2;
} else if (state == 2) {
assertEquals('g', event_data.func().name());
assertEquals(' return t + 1; // expected line',
event_data.sourceLineText());
state = 3;
}
}
} catch(e) {
exception = e;
}
};
// Add the debug event listener.
Debug.setListener(listener);
// Sample functions.
function g(t) {
return t + 1; // expected line
}
// Test step into function call from a function without local variables.
function call1() {
debugger;
g.call(null, 3);
}
// Test step into function call from a function with some local variables.
function call2() {
var aLocalVar = 'test';
var anotherLocalVar = g(aLocalVar) + 's';
var yetAnotherLocal = 10;
debugger;
g.call(null, 3);
}
// Test step into function call which is a part of an expression.
function call3() {
var alias = g;
debugger;
var r = 10 + alias.call(null, 3);
var aLocalVar = 'test';
var anotherLocalVar = g(aLocalVar) + 's';
var yetAnotherLocal = 10;
}
// Test step into function call from a function with some local variables.
function call4() {
var alias = g;
debugger;
alias.call(null, 3);
var aLocalVar = 'test';
var anotherLocalVar = g(aLocalVar) + 's';
var yetAnotherLocal = 10;
}
// Test step into function apply from a function without local variables.
function apply1() {
debugger;
g.apply(null, [3]);
}
// Test step into function apply from a function with some local variables.
function apply2() {
var aLocalVar = 'test';
var anotherLocalVar = g(aLocalVar) + 's';
var yetAnotherLocal = 10;
debugger;
g.apply(null, [3, 4]);
}
// Test step into function apply which is a part of an expression.
function apply3() {
var alias = g;
debugger;
var r = 10 + alias.apply(null, [3, 'unused arg']);
var aLocalVar = 'test';
var anotherLocalVar = g(aLocalVar) + 's';
var yetAnotherLocal = 10;
}
// Test step into function apply from a function with some local variables.
function apply4() {
var alias = g;
debugger;
alias.apply(null, [3]);
var aLocalVar = 'test';
var anotherLocalVar = g(aLocalVar) + 's';
var yetAnotherLocal = 10;
}
var testFunctions =
[call1, call2, call3, call4, apply1, apply2, apply3, apply4];
for (var i = 0; i < testFunctions.length; i++) {
state = 0;
testFunctions[i]();
assertNull(exception);
assertEquals(3, state);
}
// Get rid of the debug event listener.
Debug.setListener(null);
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment