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

Unified Diff: runtime/vm/debugger.cc

Issue 15000005: Allow breakpoints on one-liner functions (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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') | tests/standalone/debugger/basic_debugger_test.dart » ('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 22797)
+++ runtime/vm/debugger.cc (working copy)
@@ -58,7 +58,7 @@
next_(NULL) {
ASSERT(!func.IsNull());
ASSERT((func.token_pos() <= token_pos_) &&
- (token_pos_ < func.end_token_pos()));
+ (token_pos_ <= func.end_token_pos()));
}
@@ -860,6 +860,14 @@
}
+static bool IsSafePoint(PcDescriptors::Kind kind) {
+ return ((kind == PcDescriptors::kIcCall) ||
+ (kind == PcDescriptors::kFuncCall) ||
+ (kind == PcDescriptors::kClosureCall) ||
+ (kind == PcDescriptors::kReturn));
+}
+
+
void Debugger::InstrumentForStepping(const Function& target_function) {
if (!target_function.HasCode()) {
Compiler::CompileFunction(target_function);
@@ -882,11 +890,7 @@
bpt->Enable();
continue;
}
- PcDescriptors::Kind kind = desc.DescriptorKind(i);
- if ((kind == PcDescriptors::kIcCall) ||
- (kind == PcDescriptors::kFuncCall) ||
- (kind == PcDescriptors::kClosureCall) ||
- (kind == PcDescriptors::kReturn)) {
+ if (IsSafePoint(desc.DescriptorKind(i))) {
bpt = new CodeBreakpoint(target_function, i);
RegisterCodeBreakpoint(bpt);
bpt->Enable();
@@ -1028,18 +1032,20 @@
}
-CodeBreakpoint* Debugger::MakeCodeBreakpoint(const Function& func,
- intptr_t first_token_pos,
- intptr_t last_token_pos) {
+// Given a function and a token position range, return the best fit
+// token position to set a breakpoint.
+// If multiple possible breakpoint positions are within the given range,
+// the one with the lowest machine code address is picked.
+// If no possible breakpoint location exists in the given range, the closest
+// token position after the range is returned.
+intptr_t Debugger::ResolveBreakpointPos(const Function& func,
+ intptr_t first_token_pos,
+ intptr_t last_token_pos) {
ASSERT(func.HasCode());
ASSERT(!func.HasOptimizedCode());
Code& code = Code::Handle(func.unoptimized_code());
ASSERT(!code.IsNull());
PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
- // We attempt to find the PC descriptor that is closest to the
- // beginning of the token range, in terms of native code address. If we
- // don't find a PC descriptor within the given range, we pick the
- // nearest one to the beginning of the range, in terms of token position.
intptr_t best_fit_index = -1;
intptr_t best_fit = INT_MAX;
uword lowest_pc = kUwordMax;
@@ -1048,14 +1054,13 @@
intptr_t desc_token_pos = desc.TokenPos(i);
ASSERT(desc_token_pos >= 0);
if (desc_token_pos < first_token_pos) {
+ // This descriptor is before the given range.
continue;
}
- PcDescriptors::Kind kind = desc.DescriptorKind(i);
- if ((kind == PcDescriptors::kIcCall) ||
- (kind == PcDescriptors::kFuncCall) ||
- (kind == PcDescriptors::kClosureCall) ||
- (kind == PcDescriptors::kReturn)) {
+ if (IsSafePoint(desc.DescriptorKind(i))) {
if ((desc_token_pos - first_token_pos) < best_fit) {
+ // So far, this descriptor has the closest token position to the
+ // beginning of the range.
best_fit = desc_token_pos - first_token_pos;
ASSERT(best_fit >= 0);
best_fit_index = i;
@@ -1063,6 +1068,8 @@
if ((first_token_pos <= desc_token_pos) &&
(desc_token_pos <= last_token_pos) &&
(desc.PC(i) < lowest_pc)) {
+ // This descriptor is within the token position range and so
+ // far has the lowest code address.
lowest_pc = desc.PC(i);
lowest_pc_index = i;
}
@@ -1076,26 +1083,31 @@
best_fit_index = lowest_pc_index;
}
if (best_fit_index >= 0) {
- CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(best_fit_index));
- // We should only ever have one code breakpoint at the same address.
- if (bpt != NULL) {
- return bpt;
- }
+ return desc.TokenPos(best_fit_index);
+ }
+ return -1;
+}
- bpt = new CodeBreakpoint(func, best_fit_index);
- if (FLAG_verbose_debug) {
- OS::Print("Setting breakpoint in function '%s' "
- "(%s:%"Pd") (Token %"Pd") (PC %#"Px")\n",
- String::Handle(func.name()).ToCString(),
- String::Handle(bpt->SourceUrl()).ToCString(),
- bpt->LineNumber(),
- bpt->token_pos(),
- bpt->pc());
+
+void Debugger::MakeCodeBreakpointsAt(const Function& func,
+ intptr_t token_pos,
+ SourceBreakpoint* bpt) {
+ ASSERT(!func.HasOptimizedCode());
+ Code& code = Code::Handle(func.unoptimized_code());
+ ASSERT(!code.IsNull());
+ PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
+ for (int i = 0; i < desc.Length(); i++) {
+ intptr_t desc_token_pos = desc.TokenPos(i);
+ if ((desc_token_pos == token_pos) && IsSafePoint(desc.DescriptorKind(i))) {
+ CodeBreakpoint* code_bpt = GetCodeBreakpoint(desc.PC(i));
+ if (code_bpt == NULL) {
+ // No code breakpoint for this code exists; create one.
+ code_bpt = new CodeBreakpoint(func, i);
+ RegisterCodeBreakpoint(code_bpt);
+ }
+ code_bpt->set_src_bpt(bpt);
}
- RegisterCodeBreakpoint(bpt);
- return bpt;
}
- return NULL;
}
@@ -1107,70 +1119,67 @@
// The given token position is not within the target function.
return NULL;
}
- DeoptimizeWorld();
- ASSERT(!target_function.HasOptimizedCode());
-
- CodeBreakpoint* cbpt = NULL;
- SourceBreakpoint* source_bpt = NULL;
+ intptr_t breakpoint_pos = -1;
+ Function& closure = Function::Handle(isolate_);
+ if (target_function.HasImplicitClosureFunction()) {
+ // There is a closurized version of this function.
+ closure = target_function.ImplicitClosureFunction();
+ }
+ // Determine actual breakpoint location if the function or an
+ // implicit closure of the function has been compiled already.
if (target_function.HasCode()) {
- cbpt = MakeCodeBreakpoint(target_function, first_token_pos, last_token_pos);
- if (cbpt != NULL) {
- if (cbpt->src_bpt() != NULL) {
- // There is already a source breakpoint for the location.
- ASSERT(cbpt->src_bpt() ==
- GetSourceBreakpoint(target_function, cbpt->token_pos()));
- return cbpt->src_bpt();
- }
- // No source breakpoint exists yet that is associated with the code
- // breakpoint we found. (This is an internal breakpoint.) Adjust
- // the breakpoint location to the actual position where breakpoint
- // got set.
- first_token_pos = cbpt->token_pos();
- }
+ DeoptimizeWorld();
+ ASSERT(!target_function.HasOptimizedCode());
+ breakpoint_pos =
+ ResolveBreakpointPos(target_function, first_token_pos, last_token_pos);
+ } else if (!closure.IsNull() && closure.HasCode()) {
+ DeoptimizeWorld();
+ ASSERT(!closure.HasOptimizedCode());
+ breakpoint_pos =
+ ResolveBreakpointPos(closure, first_token_pos, last_token_pos);
} else {
- source_bpt = GetSourceBreakpoint(target_function, first_token_pos);
+ // This function has not been compiled yet. Set a pending
+ // breakpoint to be resolved later.
+ SourceBreakpoint* source_bpt =
+ GetSourceBreakpoint(target_function, first_token_pos);
if (source_bpt != NULL) {
- // A source breakpoint for this uncompiled location already
- // exists.
+ // A pending source breakpoint for this uncompiled location
+ // already exists.
+ if (FLAG_verbose_debug) {
+ OS::Print("Pending breakpoint for uncompiled function"
+ " '%s' at line %"Pd" already exists\n",
+ target_function.ToFullyQualifiedCString(),
+ source_bpt->LineNumber());
+ }
return source_bpt;
}
- }
- source_bpt = new SourceBreakpoint(nextId(), target_function, first_token_pos);
- RegisterSourceBreakpoint(source_bpt);
- if (FLAG_verbose_debug && !target_function.HasCode()) {
- OS::Print("Registering breakpoint for "
- "uncompiled function '%s' at line %"Pd"\n",
- target_function.ToFullyQualifiedCString(),
- source_bpt->LineNumber());
- }
-
- if (cbpt != NULL) {
- ASSERT(cbpt->src_bpt() == NULL);
- cbpt->set_src_bpt(source_bpt);
- SignalBpResolved(source_bpt);
- } else {
+ source_bpt =
+ new SourceBreakpoint(nextId(), target_function, first_token_pos);
+ RegisterSourceBreakpoint(source_bpt);
if (FLAG_verbose_debug) {
- OS::Print("Failed to set breakpoint at '%s' line %"Pd"\n",
- String::Handle(source_bpt->SourceUrl()).ToCString(),
+ OS::Print("Registering pending breakpoint for "
+ "uncompiled function '%s' at line %"Pd"\n",
+ target_function.ToFullyQualifiedCString(),
source_bpt->LineNumber());
}
+ source_bpt->Enable();
+ return source_bpt;
}
-
- if (target_function.HasImplicitClosureFunction()) {
- // There is a closurized version of this function. If the closure
- // is already compiled, we need to set a code breakpoint in its
- // code.
- const Function& closure =
- Function::Handle(target_function.ImplicitClosureFunction());
- if (closure.HasCode()) {
- ASSERT(!closure.HasOptimizedCode());
- CodeBreakpoint* closure_bpt =
- MakeCodeBreakpoint(closure, first_token_pos, last_token_pos);
- if ((closure_bpt != NULL) && (closure_bpt->src_bpt() == NULL)) {
- closure_bpt->set_src_bpt(source_bpt);
- }
- }
+ ASSERT(breakpoint_pos != -1);
+ SourceBreakpoint* source_bpt =
+ GetSourceBreakpoint(target_function, breakpoint_pos);
+ if (source_bpt != NULL) {
+ // A source breakpoint for this location already exists.
+ return source_bpt;
}
+ source_bpt = new SourceBreakpoint(nextId(), target_function, breakpoint_pos);
+ RegisterSourceBreakpoint(source_bpt);
+ if (target_function.HasCode()) {
+ MakeCodeBreakpointsAt(target_function, breakpoint_pos, source_bpt);
+ }
+ if (!closure.IsNull() && closure.HasCode()) {
+ MakeCodeBreakpointsAt(closure, breakpoint_pos, source_bpt);
+ }
source_bpt->Enable();
return source_bpt;
}
@@ -1209,8 +1218,8 @@
SourceBreakpoint* Debugger::SetBreakpointAtLine(const String& script_url,
intptr_t line_number) {
- Library& lib = Library::Handle();
- Script& script = Script::Handle();
+ Library& lib = Library::Handle(isolate_);
+ Script& script = Script::Handle(isolate_);
const GrowableObjectArray& libs =
GrowableObjectArray::Handle(isolate_->object_store()->libraries());
for (int i = 0; i < libs.Length(); i++) {
@@ -1237,8 +1246,15 @@
}
return NULL;
}
- const Function& func =
- Function::Handle(lib.LookupFunctionInScript(script, first_token_idx));
+
+ Function& func = Function::Handle(isolate_);
+ while (first_token_idx <= last_token_idx) {
+ func = lib.LookupFunctionInScript(script, first_token_idx);
+ if (!func.IsNull()) {
+ break;
+ }
+ first_token_idx++;
+ }
if (func.IsNull()) {
if (FLAG_verbose_debug) {
OS::Print("No executable code at line %"Pd" in '%s'\n",
@@ -1684,13 +1700,11 @@
OS::Print("Enable pending breakpoint for function '%s'\n",
String::Handle(lookup_function.name()).ToCString());
}
- // Set breakpoint in newly compiled code of function func.
- CodeBreakpoint* cbpt =
- MakeCodeBreakpoint(func, bpt->token_pos(), func.end_token_pos());
- if (cbpt != NULL) {
- cbpt->set_src_bpt(bpt);
- SignalBpResolved(bpt);
- }
+ intptr_t bp_pos =
+ ResolveBreakpointPos(func, bpt->token_pos(), func.end_token_pos());
+ bpt->set_token_pos(bp_pos);
+ MakeCodeBreakpointsAt(func, bp_pos, bpt);
+ SignalBpResolved(bpt);
}
bpt->Enable(); // Enables the code breakpoint as well.
}
« no previous file with comments | « runtime/vm/debugger.h ('k') | tests/standalone/debugger/basic_debugger_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698