Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Unified Diff: runtime/vm/debugger.cc

Issue 10442088: Bigger stepping granularity in debugging (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/debugger.cc
===================================================================
--- runtime/vm/debugger.cc (revision 8117)
+++ runtime/vm/debugger.cc (working copy)
@@ -475,6 +475,7 @@
src_breakpoints_(NULL),
code_breakpoints_(NULL),
resume_action_(kContinue),
+ last_bpt_line_(-1),
ignore_breakpoints_(false) {
}
@@ -966,6 +967,19 @@
}
+bool Debugger::IsDebuggable(const Function& func) {
+ RawFunction::Kind fkind = func.kind();
+ if ((fkind == RawFunction::kImplicitGetter) ||
+ (fkind == RawFunction::kImplicitSetter) ||
+ (fkind == RawFunction::kConstImplicitGetter)) {
+ return false;
+ }
+ const Class& cls = Class::Handle(func.owner());
+ const Library& lib = Library::Handle(cls.library());
+ return lib.IsDebuggable();
+}
+
+
void Debugger::BreakpointCallback() {
ASSERT(initialized_);
@@ -985,6 +999,15 @@
frame->pc());
}
+ if (!bpt->IsInternal()) {
+ // This is a user-defined breakpoint, so we call the breakpoint callback
+ // even if it is on the same line as the previous breakpoint.
+ last_bpt_line_ = -1;
+ }
+
+ bool notify_frontend =
+ (last_bpt_line_ < 0) || (last_bpt_line_ != bpt->LineNumber());
+
DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
while (frame != NULL) {
ASSERT(frame->IsValid());
@@ -995,38 +1018,47 @@
frame = iterator.NextFrame();
}
- resume_action_ = kContinue;
- if (bp_handler_ != NULL) {
- SourceBreakpoint* src_bpt = bpt->src_bpt();
- ASSERT(stack_trace_ == NULL);
- ASSERT(obj_cache_ == NULL);
- obj_cache_ = new RemoteObjectCache(64);
- stack_trace_ = stack_trace;
- (*bp_handler_)(src_bpt, stack_trace);
- stack_trace_ = NULL;
- obj_cache_ = NULL; // Remote object cache is zone allocated.
+ if (notify_frontend) {
+ resume_action_ = kContinue;
+ if (bp_handler_ != NULL) {
+ SourceBreakpoint* src_bpt = bpt->src_bpt();
+ ASSERT(stack_trace_ == NULL);
+ ASSERT(obj_cache_ == NULL);
+ obj_cache_ = new RemoteObjectCache(64);
+ stack_trace_ = stack_trace;
+ (*bp_handler_)(src_bpt, stack_trace);
+ stack_trace_ = NULL;
+ obj_cache_ = NULL; // Remote object cache is zone allocated.
+ last_bpt_line_ = bpt->LineNumber();
+ }
}
+ Function& currently_instrumented_func = Function::Handle();
+ if (bpt->IsInternal()) {
+ currently_instrumented_func = bpt->function();
+ }
+ Function& func_to_instrument = Function::Handle();
if (resume_action_ == kContinue) {
- RemoveInternalBreakpoints();
+ // Nothing to do here, any potential instrumentation will be removed
+ // below.
} else if (resume_action_ == kStepOver) {
- Function& func = Function::Handle(bpt->function());
+ func_to_instrument = bpt->function();
siva 2012/05/31 19:11:15 This will be an issue if we have resursive calls r
hausner 2012/05/31 20:04:14 We don't have recursive calls. Breakpoints are ign
siva 2012/05/31 20:26:56 I didn't mean recursive calls to the breakpoint ha
if (bpt->breakpoint_kind_ == PcDescriptors::kReturn) {
// If we are at the function return, do a StepOut action.
if (stack_trace->Length() > 1) {
- ActivationFrame* caller = stack_trace->ActivationFrameAt(1);
- func = caller->DartFunction().raw();
+ ActivationFrame* caller_frame = stack_trace->ActivationFrameAt(1);
+ func_to_instrument = caller_frame->DartFunction().raw();
}
}
- RemoveInternalBreakpoints(); // *bpt is now invalid.
- InstrumentForStepping(func);
} else if (resume_action_ == kStepInto) {
+ // If the call target is not debuggable, we treat StepInto like
+ // a StepOver, that is we instrument the current function.
if (bpt->breakpoint_kind_ == PcDescriptors::kIcCall) {
+ func_to_instrument = bpt->function();
int num_args, num_named_args;
uword target;
CodePatcher::GetInstanceCallAt(bpt->pc_, NULL,
&num_args, &num_named_args, &target);
- RemoveInternalBreakpoints(); // *bpt is now invalid.
ActivationFrame* top_frame = stack_trace->ActivationFrameAt(0);
Instance& receiver = Instance::Handle(
top_frame->GetInstanceCallReceiver(num_args));
@@ -1034,32 +1066,42 @@
ResolveCompileInstanceCallTarget(isolate_, receiver));
if (!code.IsNull()) {
Function& callee = Function::Handle(code.function());
- InstrumentForStepping(callee);
+ if (IsDebuggable(callee)) {
+ func_to_instrument = callee.raw();
+ }
}
} else if (bpt->breakpoint_kind_ == PcDescriptors::kFuncCall) {
+ func_to_instrument = bpt->function();
Function& callee = Function::Handle();
uword target;
CodePatcher::GetStaticCallAt(bpt->pc_, &callee, &target);
- RemoveInternalBreakpoints(); // *bpt is now invalid.
- InstrumentForStepping(callee);
+ if (IsDebuggable(callee)) {
+ func_to_instrument = callee.raw();
+ }
} else {
ASSERT(bpt->breakpoint_kind_ == PcDescriptors::kReturn);
- RemoveInternalBreakpoints(); // *bpt is now invalid.
// Treat like stepping out to caller.
if (stack_trace->Length() > 1) {
- ActivationFrame* caller = stack_trace->ActivationFrameAt(1);
- InstrumentForStepping(caller->DartFunction());
+ ActivationFrame* caller_frame = stack_trace->ActivationFrameAt(1);
+ func_to_instrument = caller_frame->DartFunction().raw();
}
}
} else {
ASSERT(resume_action_ == kStepOut);
- RemoveInternalBreakpoints(); // *bpt is now invalid.
// Set stepping breakpoints in the caller.
if (stack_trace->Length() > 1) {
- ActivationFrame* caller = stack_trace->ActivationFrameAt(1);
- InstrumentForStepping(caller->DartFunction());
+ ActivationFrame* caller_frame = stack_trace->ActivationFrameAt(1);
+ func_to_instrument = caller_frame->DartFunction().raw();
siva 2012/05/31 19:11:15 How does this work if we have recursive calls i.e
hausner 2012/05/31 20:04:14 Recursive functions are not properly treated yet.
siva 2012/05/31 20:26:56 Actually we won't step out to the previous activat
hausner 2012/05/31 20:32:28 Ah, you are right. I will put this on my todo list
}
}
+
+ if (func_to_instrument.raw() != currently_instrumented_func.raw()) {
+ last_bpt_line_ = -1;
+ RemoveInternalBreakpoints(); // *bpt is now invalid.
+ if (!func_to_instrument.IsNull()) {
+ InstrumentForStepping(func_to_instrument);
+ }
+ }
}
@@ -1146,8 +1188,8 @@
} else {
prev_bpt->set_next(curr_bpt->next());
}
- // Remove the code breakpoints associated with the source breakpoint.
- RemoveCodeBreakpoints(curr_bpt);
+ // Remove references from code breakpoints to this source breakpoint.
+ UnlinkCodeBreakpoints(curr_bpt);
delete curr_bpt;
return;
}
@@ -1158,13 +1200,28 @@
}
-// Remove and delete the code breakpoints that are associated with given
-// source breakpoint bpt. If bpt is null, remove the internal breakpoints.
-void Debugger::RemoveCodeBreakpoints(SourceBreakpoint* src_bpt) {
+// Turn code breakpoints associated with the given source breakpoint into
+// internal breakpoints. They will later be deleted when control
+// returns from the user-defined breakpoint callback.
siva 2012/05/31 19:11:15 Can you add a comment stating that breakpoints can
hausner 2012/05/31 20:04:14 Done.
+void Debugger::UnlinkCodeBreakpoints(SourceBreakpoint* src_bpt) {
+ ASSERT(src_bpt != NULL);
+ CodeBreakpoint* curr_bpt = code_breakpoints_;
+ while (curr_bpt != NULL) {
+ if (curr_bpt->src_bpt() == src_bpt) {
+ curr_bpt->set_src_bpt(NULL);
siva 2012/05/31 19:11:15 can you break out from here instead of looping til
hausner 2012/05/31 20:04:14 There can be multiple code breakpoints pointing to
+ }
+ curr_bpt = curr_bpt->next();
+ }
+}
+
+
+// Remove and delete internal breakpoints, i.e. breakpoints that
+// are not associated with a source breakpoint.
+void Debugger::RemoveInternalBreakpoints() {
CodeBreakpoint* prev_bpt = NULL;
CodeBreakpoint* curr_bpt = code_breakpoints_;
while (curr_bpt != NULL) {
- if (curr_bpt->src_bpt() == src_bpt) {
+ if (curr_bpt->src_bpt() == NULL) {
if (prev_bpt == NULL) {
code_breakpoints_ = code_breakpoints_->next();
} else {
@@ -1182,13 +1239,6 @@
}
-// Remove and delete all breakpoints that are not associated with a
-// user-defined source breakpoint.
-void Debugger::RemoveInternalBreakpoints() {
- RemoveCodeBreakpoints(NULL);
-}
-
-
SourceBreakpoint* Debugger::GetSourceBreakpoint(const Function& func,
intptr_t token_index) {
SourceBreakpoint* bpt = src_breakpoints_;
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698