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

Unified Diff: runtime/vm/debugger.cc

Issue 805573003: Fix debugging of async code (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years 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/parser.cc » ('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 42362)
+++ runtime/vm/debugger.cc (working copy)
@@ -64,6 +64,7 @@
end_token_pos_(end_token_pos),
is_resolved_(false),
is_enabled_(false),
+ is_one_shot_(false),
next_(NULL),
function_(Function::null()),
line_number_(-1) {
@@ -1138,48 +1139,8 @@
}
-RawError* Debugger::SetInternalBreakpoints(const Function& target_function) {
- if (target_function.is_native()) {
- // Can't instrument native functions. Fail silently.
- return Error::null();
- }
- Isolate* isolate = Isolate::Current();
- if (!target_function.HasCode()) {
- const Error& error = Error::Handle(
- Compiler::CompileFunction(isolate, target_function));
- if (!error.IsNull()) {
- return error.raw();
- }
- }
- // Hang on to the code object before deoptimizing, in case deoptimization
- // might cause the GC to run.
- Code& code = Code::Handle(isolate, target_function.unoptimized_code());
- ASSERT(!code.IsNull());
- DeoptimizeWorld();
- ASSERT(!target_function.HasOptimizedCode());
- PcDescriptors& desc = PcDescriptors::Handle(isolate, code.pc_descriptors());
- PcDescriptors::Iterator iter(desc, kSafepointKind);
- while (iter.MoveNext()) {
- if (iter.TokenPos() != Scanner::kNoSourcePos) {
- CodeBreakpoint* bpt = GetCodeBreakpoint(iter.Pc());
- if (bpt != NULL) {
- // There is already a breakpoint for this address. Make sure
- // it is enabled.
- bpt->Enable();
- continue;
- }
- bpt = new CodeBreakpoint(code, iter.TokenPos(),
- iter.Pc(), iter.Kind());
- RegisterCodeBreakpoint(bpt);
- bpt->Enable();
- }
- }
- return Error::null();
-}
-
-
void Debugger::SignalBpResolved(SourceBreakpoint* bpt) {
- if (HasEventHandler()) {
+ if (HasEventHandler() && !bpt->IsOneShot()) {
DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointResolved);
event.set_breakpoint(bpt);
InvokeEventHandler(&event);
@@ -1418,9 +1379,23 @@
}
+static intptr_t LastTokenOnLine(const TokenStream& tokens, intptr_t pos) {
+ TokenStream::Iterator iter(tokens, pos, TokenStream::Iterator::kAllTokens);
+ ASSERT(iter.IsValid());
+ intptr_t last_pos = pos;
+ while ((iter.CurrentTokenKind() != Token::kNEWLINE) &&
+ (iter.CurrentTokenKind() != Token::kEOS)) {
+ last_pos = iter.CurrentPosition();
+ iter.Advance();
+ }
+ return last_pos;
+}
+
+
// Given a function and a token range, return the best fit
// token position to set a breakpoint. The best fit is the safe point
-// with the lowest compiled code address within the token range.
+// in the line closest to the beginning of the token range, and within
+// that line, the safe point with the lowest compiled code address.
intptr_t Debugger::ResolveBreakpointPos(const Function& func,
intptr_t requested_token_pos,
intptr_t last_token_pos) {
@@ -1437,41 +1412,45 @@
Code& code = Code::Handle(func.unoptimized_code());
ASSERT(!code.IsNull());
PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
+
+ // First pass: find the safe point which is closest to the beginning
+ // of the given token range.
intptr_t best_fit_pos = INT_MAX;
- uword lowest_pc = kUwordMax;
- intptr_t lowest_pc_token_pos = INT_MAX;
PcDescriptors::Iterator iter(desc, kSafepointKind);
while (iter.MoveNext()) {
const intptr_t desc_token_pos = iter.TokenPos();
- ASSERT(desc_token_pos >= 0);
- if (desc_token_pos != Scanner::kNoSourcePos) {
- if ((desc_token_pos < requested_token_pos) ||
- (desc_token_pos > last_token_pos)) {
- // This descriptor is outside the desired token range.
- continue;
- }
- if (desc_token_pos < best_fit_pos) {
- // So far, this descriptor has the lowest token position after
- // the first acceptable token position.
- best_fit_pos = desc_token_pos;
- }
- if (iter.Pc() < lowest_pc) {
- // This descriptor so far has the lowest code address.
+ if ((desc_token_pos != Scanner::kNoSourcePos) &&
+ (desc_token_pos < best_fit_pos) &&
+ (desc_token_pos >= requested_token_pos) &&
+ (desc_token_pos <= last_token_pos)) {
+ best_fit_pos = desc_token_pos;
+ }
+ }
+ // Second pass (if we found a safe point in the first pass):
+ // For all token positions on the same line, select the one
+ // with the lowest compiled code address. E.g., in a line with
+ // the nested function calls f(g(x)), the call g() will have a lower
+ // compiled code address but is not the lowest token position in the
+ // line.
+ if (best_fit_pos != INT_MAX) {
+ const Script& script = Script::Handle(func.script());
+ const TokenStream& tokens = TokenStream::Handle(script.tokens());
+ const intptr_t begin_pos = best_fit_pos;
+ const intptr_t end_of_line_pos = LastTokenOnLine(tokens, begin_pos);
+ uword lowest_pc = kUwordMax;
+ PcDescriptors::Iterator iter(desc, kSafepointKind);
+ while (iter.MoveNext()) {
+ const intptr_t pos = iter.TokenPos();
+ if ((pos != Scanner::kNoSourcePos) &&
+ (begin_pos <= pos) && (pos <= end_of_line_pos) &&
+ (iter.Pc() < lowest_pc)) {
lowest_pc = iter.Pc();
- lowest_pc_token_pos = desc_token_pos;
+ best_fit_pos = pos;
}
}
- }
- if (lowest_pc_token_pos != INT_MAX) {
- // We found the pc descriptor that has the lowest execution address.
- // This is the first possible breakpoint after the requested token
- // position. We use this instead of the nearest PC descriptor
- // measured in token index distance.
- return lowest_pc_token_pos;
- }
- if (best_fit_pos != INT_MAX) {
return best_fit_pos;
}
+
// We didn't find a safe point in the given token range. Try and find
// a safe point in the remaining source code of the function.
if (last_token_pos < func.end_token_pos()) {
@@ -1554,12 +1533,12 @@
if ((function.token_pos() == start_pos)
&& (function.end_token_pos() == end_pos)
&& (function.script() == script.raw())) {
- if (function.HasCode()) {
+ if (function.HasCode() && !function.IsAsyncFunction()) {
function_list->Add(function);
}
if (function.HasImplicitClosureFunction()) {
function = function.ImplicitClosureFunction();
- if (function.HasCode()) {
+ if (function.HasCode() && !function.IsAsyncFunction()) {
function_list->Add(function);
}
}
@@ -1575,12 +1554,12 @@
if ((function.token_pos() == start_pos)
&& (function.end_token_pos() == end_pos)
&& (function.script() == script.raw())) {
- if (function.HasCode()) {
+ if (function.HasCode() && !function.IsAsyncFunction()) {
function_list->Add(function);
}
if (function.HasImplicitClosureFunction()) {
function = function.ImplicitClosureFunction();
- if (function.HasCode()) {
+ if (function.HasCode() && !function.IsAsyncFunction()) {
function_list->Add(function);
}
}
@@ -1723,7 +1702,7 @@
if (FLAG_verbose_debug) {
intptr_t line_number;
script.GetTokenLocation(breakpoint_pos, &line_number, NULL);
- OS::Print("Resolved breakpoint for "
+ OS::Print("Resolved BP for "
"function '%s' at line %" Pd "\n",
func.ToFullyQualifiedCString(),
line_number);
@@ -1770,14 +1749,11 @@
RawError* Debugger::OneTimeBreakAtEntry(const Function& target_function) {
- Error& err = Error::Handle();
- err = SetInternalBreakpoints(target_function);
- if (err.IsNull() && target_function.HasImplicitClosureFunction()) {
- const Function& closure_func =
- Function::Handle(target_function.ImplicitClosureFunction());
- err = SetInternalBreakpoints(closure_func);
+ SourceBreakpoint* bpt = SetBreakpointAtEntry(target_function);
+ if (bpt != NULL) {
+ bpt->SetIsOneShot();
}
- return err.raw();
+ return Error::null();
}
@@ -2136,6 +2112,10 @@
isolate_->set_single_step(false);
ASSERT(!IsPaused());
ASSERT(obj_cache_ == NULL);
+ if ((bpt != NULL) && bpt->IsOneShot()) {
+ RemoveBreakpoint(bpt->id());
+ bpt = NULL;
+ }
DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointReached);
event.set_top_frame(top_frame);
event.set_breakpoint(bpt);
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698