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

Unified Diff: runtime/vm/debugger.cc

Issue 1699153002: Add step OverAwait to service protocol (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 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/service.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/debugger.cc
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 82511db787418fe52421c7147296fead76518912..06e788026781b828c52f60a0e7291ebd62a41adf 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -218,6 +218,9 @@ void Breakpoint::PrintJSON(JSONStream* stream) {
jsobj.AddFixedServiceId("breakpoints/%" Pd "", id());
jsobj.AddProperty("breakpointNumber", id());
+ if (is_synthetic_async()) {
+ jsobj.AddProperty("isSyntheticAsyncContinuation", is_synthetic_async());
+ }
jsobj.AddProperty("resolved", bpt_location_->IsResolved());
if (bpt_location_->IsResolved()) {
jsobj.AddLocation(bpt_location_);
@@ -430,7 +433,8 @@ Breakpoint* BreakpointLocation::AddSingleShot(Debugger* dbg) {
Breakpoint* BreakpointLocation::AddPerClosure(Debugger* dbg,
- const Instance& closure) {
+ const Instance& closure,
+ bool for_over_await) {
Breakpoint* bpt = breakpoints();
while (bpt != NULL) {
if (bpt->IsPerClosure() && bpt->closure() == closure.raw()) break;
@@ -439,6 +443,7 @@ Breakpoint* BreakpointLocation::AddPerClosure(Debugger* dbg,
if (bpt == NULL) {
bpt = new Breakpoint(dbg->nextId(), this);
bpt->SetIsPerClosure(closure);
+ bpt->set_is_synthetic_async(for_over_await);
AddBreakpoint(bpt, dbg);
}
return bpt;
@@ -1268,6 +1273,7 @@ Debugger::Debugger()
stack_trace_(NULL),
stepping_fp_(0),
skip_next_step_(false),
+ synthetic_async_breakpoint_(NULL),
exc_pause_info_(kNoPauseOnExceptions) {
}
@@ -1280,6 +1286,7 @@ Debugger::~Debugger() {
ASSERT(code_breakpoints_ == NULL);
ASSERT(stack_trace_ == NULL);
ASSERT(obj_cache_ == NULL);
+ ASSERT(synthetic_async_breakpoint_ == NULL);
}
@@ -1326,6 +1333,25 @@ static RawFunction* ResolveLibraryFunction(
}
+bool Debugger::SetupStepOverAsyncSuspension() {
+ ActivationFrame* top_frame = TopDartFrame();
+ if (!IsAtAsyncJump(top_frame)) {
+ // Not at an async operation.
+ return false;
+ }
+ Object& closure = Object::Handle(top_frame->GetAsyncOperation());
+ ASSERT(!closure.IsNull());
+ ASSERT(closure.IsInstance());
+ ASSERT(Instance::Cast(closure).IsClosure());
+ Breakpoint* bpt = SetBreakpointAtActivation(Instance::Cast(closure), true);
+ if (bpt == NULL) {
+ // Unable to set the breakpoint.
+ return false;
+ }
+ return true;
+}
+
+
void Debugger::SetSingleStep() {
resume_action_ = kSingleStep;
}
@@ -2155,7 +2181,8 @@ Breakpoint* Debugger::SetBreakpointAtEntry(const Function& target_function,
}
-Breakpoint* Debugger::SetBreakpointAtActivation(const Instance& closure) {
+Breakpoint* Debugger::SetBreakpointAtActivation(
+ const Instance& closure, bool for_over_await) {
if (!closure.IsClosure()) {
return NULL;
}
@@ -2165,7 +2192,7 @@ Breakpoint* Debugger::SetBreakpointAtActivation(const Instance& closure) {
func.token_pos(),
func.end_token_pos(),
-1, -1 /* no line/col */);
- return bpt_location->AddPerClosure(this, closure);
+ return bpt_location->AddPerClosure(this, closure, for_over_await);
}
@@ -2617,24 +2644,28 @@ void Debugger::SignalPausedEvent(ActivationFrame* top_frame,
DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointReached);
event.set_top_frame(top_frame);
event.set_breakpoint(bpt);
+ event.set_at_async_jump(IsAtAsyncJump(top_frame));
+ Pause(&event);
+}
+
+
+bool Debugger::IsAtAsyncJump(ActivationFrame* top_frame) {
Object& closure_or_null = Object::Handle(top_frame->GetAsyncOperation());
if (!closure_or_null.IsNull()) {
ASSERT(closure_or_null.IsInstance());
ASSERT(Instance::Cast(closure_or_null).IsClosure());
- event.set_async_continuation(&closure_or_null);
const Script& script = Script::Handle(top_frame->SourceScript());
const TokenStream& tokens = TokenStream::Handle(script.tokens());
TokenStream::Iterator iter(tokens, top_frame->TokenPos());
if ((iter.CurrentTokenKind() == Token::kIDENT) &&
((iter.CurrentLiteral() == Symbols::Await().raw()) ||
(iter.CurrentLiteral() == Symbols::YieldKw().raw()))) {
- event.set_at_async_jump(true);
+ return true;
}
}
- Pause(&event);
+ return false;
}
-
RawError* Debugger::DebuggerStepCallback() {
ASSERT(isolate_->single_step());
// Don't pause recursively.
@@ -2691,7 +2722,14 @@ RawError* Debugger::DebuggerStepCallback() {
ASSERT(stack_trace_ == NULL);
stack_trace_ = CollectStackTrace();
- SignalPausedEvent(frame, NULL);
+ // If this step callback is part of stepping over an await statement,
+ // we saved the synthetic async breakpoint in SignalBpReached. We report
+ // that we are paused at that breakpoint and then delete it after continuing.
+ SignalPausedEvent(frame, synthetic_async_breakpoint_);
+ if (synthetic_async_breakpoint_ != NULL) {
+ RemoveBreakpoint(synthetic_async_breakpoint_->id());
+ synthetic_async_breakpoint_ = NULL;
+ }
HandleSteppingRequest(stack_trace_);
stack_trace_ = NULL;
@@ -2764,6 +2802,36 @@ RawError* Debugger::SignalBpReached() {
return Error::null();
}
+ if (bpt_hit->is_synthetic_async()) {
+ DebuggerStackTrace* stack_trace = CollectStackTrace();
+ ASSERT(stack_trace->Length() > 0);
+ ASSERT(stack_trace_ == NULL);
+ stack_trace_ = stack_trace;
+
+ // Hit a synthetic async breakpoint.
+ if (FLAG_verbose_debug) {
+ OS::Print(">>> hit synthetic breakpoint at %s:%" Pd " "
+ "(token %s) (address %#" Px ")\n",
+ String::Handle(cbpt->SourceUrl()).ToCString(),
+ cbpt->LineNumber(),
+ cbpt->token_pos().ToCString(),
+ top_frame->pc());
+ }
+
+ ASSERT(synthetic_async_breakpoint_ == NULL);
+ synthetic_async_breakpoint_ = bpt_hit;
+ bpt_hit = NULL;
+
+ // We are at the entry of an async function.
+ // We issue a step over to resume at the point after the await statement.
+ SetStepOver();
+ // When we single step from a user breakpoint, our next stepping
+ // point will be at the exact same pc. Skip it.
+ HandleSteppingRequest(stack_trace_, true /* skip next step */);
+ stack_trace_ = NULL;
+ return Error::null();
+ }
+
if (FLAG_verbose_debug) {
OS::Print(">>> hit %s breakpoint at %s:%" Pd " "
"(token %s) (address %#" Px ")\n",
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/service.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698