Commit d9399cc3 authored by yangguo's avatar yangguo Committed by Commit bot

[debugger] account for inlined functions when stepping.

- Remove obsolete BreakLocatorType.
- Perform PrepareStepOnThrow after OnException event, in case stepping
  was scheduled in the exception event.
- Use frame count instead of frame pointer for stepping. Frame pointer
  is not reliable due to possible deopts.
- Consistently check for inlined functions in inlined frames.
- Use SharedFunctionInfo in FloodWithOneshot and EnsureDebugInfo.

R=jgruber@chromium.org
BUG=v8:5901

Review-Url: https://codereview.chromium.org/2664793002
Cr-Commit-Position: refs/heads/master@{#42878}
parent 9432eb5c
This diff is collapsed.
...@@ -50,10 +50,6 @@ enum ExceptionBreakType { ...@@ -50,10 +50,6 @@ enum ExceptionBreakType {
}; };
// Type of exception break.
enum BreakLocatorType { ALL_BREAK_LOCATIONS, CALLS_AND_RETURNS };
// The different types of breakpoint position alignments. // The different types of breakpoint position alignments.
// Must match Debug.BreakPositionAlignment in debug.js // Must match Debug.BreakPositionAlignment in debug.js
enum BreakPositionAlignment { enum BreakPositionAlignment {
...@@ -122,8 +118,7 @@ class BreakLocation { ...@@ -122,8 +118,7 @@ class BreakLocation {
class BreakIterator { class BreakIterator {
public: public:
static std::unique_ptr<BreakIterator> GetIterator( static std::unique_ptr<BreakIterator> GetIterator(
Handle<DebugInfo> debug_info, Handle<AbstractCode> abstract_code, Handle<DebugInfo> debug_info, Handle<AbstractCode> abstract_code);
BreakLocatorType type = ALL_BREAK_LOCATIONS);
virtual ~BreakIterator() {} virtual ~BreakIterator() {}
...@@ -145,8 +140,7 @@ class BreakIterator { ...@@ -145,8 +140,7 @@ class BreakIterator {
virtual void SetDebugBreak() = 0; virtual void SetDebugBreak() = 0;
protected: protected:
explicit BreakIterator(Handle<DebugInfo> debug_info, explicit BreakIterator(Handle<DebugInfo> debug_info);
BreakLocatorType break_locator_type);
int BreakIndexFromPosition(int position, BreakPositionAlignment alignment); int BreakIndexFromPosition(int position, BreakPositionAlignment alignment);
...@@ -156,7 +150,6 @@ class BreakIterator { ...@@ -156,7 +150,6 @@ class BreakIterator {
int break_index_; int break_index_;
int position_; int position_;
int statement_position_; int statement_position_;
BreakLocatorType break_locator_type_;
private: private:
DisallowHeapAllocation no_gc_; DisallowHeapAllocation no_gc_;
...@@ -165,7 +158,7 @@ class BreakIterator { ...@@ -165,7 +158,7 @@ class BreakIterator {
class CodeBreakIterator : public BreakIterator { class CodeBreakIterator : public BreakIterator {
public: public:
CodeBreakIterator(Handle<DebugInfo> debug_info, BreakLocatorType type); explicit CodeBreakIterator(Handle<DebugInfo> debug_info);
~CodeBreakIterator() override {} ~CodeBreakIterator() override {}
BreakLocation GetBreakLocation() override; BreakLocation GetBreakLocation() override;
...@@ -184,7 +177,7 @@ class CodeBreakIterator : public BreakIterator { ...@@ -184,7 +177,7 @@ class CodeBreakIterator : public BreakIterator {
} }
private: private:
int GetModeMask(BreakLocatorType type); int GetModeMask();
DebugBreakType GetDebugBreakType(); DebugBreakType GetDebugBreakType();
RelocInfo::Mode rmode() { return reloc_iterator_.rinfo()->rmode(); } RelocInfo::Mode rmode() { return reloc_iterator_.rinfo()->rmode(); }
...@@ -197,8 +190,7 @@ class CodeBreakIterator : public BreakIterator { ...@@ -197,8 +190,7 @@ class CodeBreakIterator : public BreakIterator {
class BytecodeArrayBreakIterator : public BreakIterator { class BytecodeArrayBreakIterator : public BreakIterator {
public: public:
BytecodeArrayBreakIterator(Handle<DebugInfo> debug_info, explicit BytecodeArrayBreakIterator(Handle<DebugInfo> debug_info);
BreakLocatorType type);
~BytecodeArrayBreakIterator() override {} ~BytecodeArrayBreakIterator() override {}
BreakLocation GetBreakLocation() override; BreakLocation GetBreakLocation() override;
...@@ -357,11 +349,8 @@ class Debug { ...@@ -357,11 +349,8 @@ class Debug {
void SetDebugDelegate(debug::DebugDelegate* delegate); void SetDebugDelegate(debug::DebugDelegate* delegate);
// Returns whether the operation succeeded. Compilation can only be triggered // Returns whether the operation succeeded.
// if a valid closure is passed as the second argument, otherwise the shared bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared);
// function needs to be compiled already.
bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
Handle<JSFunction> function);
void CreateDebugInfo(Handle<SharedFunctionInfo> shared); void CreateDebugInfo(Handle<SharedFunctionInfo> shared);
static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared); static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared);
...@@ -466,6 +455,9 @@ class Debug { ...@@ -466,6 +455,9 @@ class Debug {
thread_local_.break_id_ = ++thread_local_.break_count_; thread_local_.break_id_ = ++thread_local_.break_count_;
} }
// Return the number of virtual frames below debugger entry.
int CurrentFrameCount();
inline bool ignore_events() const { inline bool ignore_events() const {
return is_suppressed_ || !is_active_ || isolate_->needs_side_effect_check(); return is_suppressed_ || !is_active_ || isolate_->needs_side_effect_check();
} }
...@@ -492,7 +484,6 @@ class Debug { ...@@ -492,7 +484,6 @@ class Debug {
return !event_listener_.is_null() && !event_listener_->IsForeign(); return !event_listener_.is_null() && !event_listener_->IsForeign();
} }
bool IsBlackboxed(SharedFunctionInfo* shared);
bool IsExceptionBlackboxed(bool uncaught); bool IsExceptionBlackboxed(bool uncaught);
void OnException(Handle<Object> exception, Handle<Object> promise); void OnException(Handle<Object> exception, Handle<Object> promise);
...@@ -526,8 +517,7 @@ class Debug { ...@@ -526,8 +517,7 @@ class Debug {
// Clear all code from instrumentation. // Clear all code from instrumentation.
void ClearAllBreakPoints(); void ClearAllBreakPoints();
// Instrument a function with one-shots. // Instrument a function with one-shots.
void FloodWithOneShot(Handle<JSFunction> function, void FloodWithOneShot(Handle<SharedFunctionInfo> function);
BreakLocatorType type = ALL_BREAK_LOCATIONS);
// Clear all one-shot instrumentations, but restore break points. // Clear all one-shot instrumentations, but restore break points.
void ClearOneShot(); void ClearOneShot();
...@@ -607,10 +597,10 @@ class Debug { ...@@ -607,10 +597,10 @@ class Debug {
int last_statement_position_; int last_statement_position_;
// Frame pointer from last step next or step frame action. // Frame pointer from last step next or step frame action.
Address last_fp_; int last_frame_count_;
// Frame pointer of the target frame we want to arrive at. // Frame pointer of the target frame we want to arrive at.
Address target_fp_; int target_frame_count_;
// Value of the accumulator at the point of entering the debugger. // Value of the accumulator at the point of entering the debugger.
Object* return_value_; Object* return_value_;
......
...@@ -954,6 +954,16 @@ void JavaScriptFrame::GetFunctions(List<SharedFunctionInfo*>* functions) const { ...@@ -954,6 +954,16 @@ void JavaScriptFrame::GetFunctions(List<SharedFunctionInfo*>* functions) const {
functions->Add(function()->shared()); functions->Add(function()->shared());
} }
void JavaScriptFrame::GetFunctions(
List<Handle<SharedFunctionInfo>>* functions) const {
DCHECK(functions->length() == 0);
List<SharedFunctionInfo*> raw_functions;
GetFunctions(&raw_functions);
for (const auto& raw_function : raw_functions) {
functions->Add(Handle<SharedFunctionInfo>(raw_function));
}
}
void JavaScriptFrame::Summarize(List<FrameSummary>* functions, void JavaScriptFrame::Summarize(List<FrameSummary>* functions,
FrameSummary::Mode mode) const { FrameSummary::Mode mode) const {
DCHECK(functions->length() == 0); DCHECK(functions->length() == 0);
......
...@@ -1029,6 +1029,8 @@ class JavaScriptFrame : public StandardFrame { ...@@ -1029,6 +1029,8 @@ class JavaScriptFrame : public StandardFrame {
// Return a list with {SharedFunctionInfo} objects of this frame. // Return a list with {SharedFunctionInfo} objects of this frame.
virtual void GetFunctions(List<SharedFunctionInfo*>* functions) const; virtual void GetFunctions(List<SharedFunctionInfo*>* functions) const;
void GetFunctions(List<Handle<SharedFunctionInfo>>* functions) const;
// Lookup exception handler for current {pc}, returns -1 if none found. Also // Lookup exception handler for current {pc}, returns -1 if none found. Also
// returns data associated with the handler site specific to the frame type: // returns data associated with the handler site specific to the frame type:
// - OptimizedFrame : Data is the stack slot count of the entire frame. // - OptimizedFrame : Data is the stack slot count of the entire frame.
......
...@@ -6456,14 +6456,13 @@ TEST(BreakLocationIterator) { ...@@ -6456,14 +6456,13 @@ TEST(BreakLocationIterator) {
Handle<i::SharedFunctionInfo> shared(function->shared()); Handle<i::SharedFunctionInfo> shared(function->shared());
EnableDebugger(isolate); EnableDebugger(isolate);
CHECK(i_isolate->debug()->EnsureDebugInfo(shared, function)); CHECK(i_isolate->debug()->EnsureDebugInfo(shared));
Handle<i::DebugInfo> debug_info(shared->GetDebugInfo()); Handle<i::DebugInfo> debug_info(shared->GetDebugInfo());
Handle<i::AbstractCode> abstract_code(shared->abstract_code()); Handle<i::AbstractCode> abstract_code(shared->abstract_code());
{ {
auto iterator = i::BreakIterator::GetIterator(debug_info, abstract_code, auto iterator = i::BreakIterator::GetIterator(debug_info, abstract_code);
i::ALL_BREAK_LOCATIONS);
CHECK(iterator->GetBreakLocation().IsDebuggerStatement()); CHECK(iterator->GetBreakLocation().IsDebuggerStatement());
CHECK_EQ(17, iterator->GetBreakLocation().position()); CHECK_EQ(17, iterator->GetBreakLocation().position());
iterator->Next(); iterator->Next();
...@@ -6482,18 +6481,6 @@ TEST(BreakLocationIterator) { ...@@ -6482,18 +6481,6 @@ TEST(BreakLocationIterator) {
CHECK(iterator->Done()); CHECK(iterator->Done());
} }
{
auto iterator = i::BreakIterator::GetIterator(debug_info, abstract_code,
i::CALLS_AND_RETURNS);
CHECK(iterator->GetBreakLocation().IsCall());
CHECK_EQ(32, iterator->GetBreakLocation().position());
iterator->Next();
CHECK(iterator->GetBreakLocation().IsReturn());
CHECK_EQ(60, iterator->GetBreakLocation().position());
iterator->Next();
CHECK(iterator->Done());
}
DisableDebugger(isolate); DisableDebugger(isolate);
} }
......
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --ignition --turbo
function f() {
throw new Error();
}
function g() {
try {
f();
} catch (e) {
return 1; // Break
}
}
function h() {
return g();
}
h();
h();
var Debug = debug.Debug;
var step_count = 0;
var exception = null;
function listener(event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Exception) {
step_count++;
exec_state.prepareStep(Debug.StepAction.StepNext);
} else if (event == Debug.DebugEvent.Break) {
step_count++;
try {
assertTrue(exec_state.frame().sourceLineText().includes('Break'));
} catch (e) {
exception = e;
print(e);
}
}
}
Debug.setListener(listener);
Debug.setBreakOnException();
% OptimizeFunctionOnNextCall(h);
h();
Debug.setListener(null);
assertNull(exception);
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function f() {
debugger;
return 1;
}
function g() {
return f();
} // Break
function h() {
return g();
}
h();
h();
var Debug = debug.Debug;
var step_count = 0;
var exception = null;
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
if (step_count == 0) {
exec_state.prepareStep(Debug.StepAction.StepOut);
} else {
assertTrue(exec_state.frame().sourceLineText().includes('Break'));
}
step_count++;
} catch (e) {
exception = e;
print(e);
}
}
Debug.setListener(listener);
% OptimizeFunctionOnNextCall(h);
h();
Debug.setListener(null);
assertNull(exception);
assertEquals(2, step_count);
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