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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/service.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/debugger.h" 5 #include "vm/debugger.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 8
9 #include "vm/code_generator.h" 9 #include "vm/code_generator.h"
10 #include "vm/code_patcher.h" 10 #include "vm/code_patcher.h"
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 } 211 }
212 } 212 }
213 213
214 214
215 void Breakpoint::PrintJSON(JSONStream* stream) { 215 void Breakpoint::PrintJSON(JSONStream* stream) {
216 JSONObject jsobj(stream); 216 JSONObject jsobj(stream);
217 jsobj.AddProperty("type", "Breakpoint"); 217 jsobj.AddProperty("type", "Breakpoint");
218 218
219 jsobj.AddFixedServiceId("breakpoints/%" Pd "", id()); 219 jsobj.AddFixedServiceId("breakpoints/%" Pd "", id());
220 jsobj.AddProperty("breakpointNumber", id()); 220 jsobj.AddProperty("breakpointNumber", id());
221 if (is_synthetic_async()) {
222 jsobj.AddProperty("isSyntheticAsyncContinuation", is_synthetic_async());
223 }
221 jsobj.AddProperty("resolved", bpt_location_->IsResolved()); 224 jsobj.AddProperty("resolved", bpt_location_->IsResolved());
222 if (bpt_location_->IsResolved()) { 225 if (bpt_location_->IsResolved()) {
223 jsobj.AddLocation(bpt_location_); 226 jsobj.AddLocation(bpt_location_);
224 } else { 227 } else {
225 jsobj.AddUnresolvedLocation(bpt_location_); 228 jsobj.AddUnresolvedLocation(bpt_location_);
226 } 229 }
227 } 230 }
228 231
229 232
230 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { 233 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 if (bpt == NULL) { 426 if (bpt == NULL) {
424 bpt = new Breakpoint(dbg->nextId(), this); 427 bpt = new Breakpoint(dbg->nextId(), this);
425 bpt->SetIsSingleShot(); 428 bpt->SetIsSingleShot();
426 AddBreakpoint(bpt, dbg); 429 AddBreakpoint(bpt, dbg);
427 } 430 }
428 return bpt; 431 return bpt;
429 } 432 }
430 433
431 434
432 Breakpoint* BreakpointLocation::AddPerClosure(Debugger* dbg, 435 Breakpoint* BreakpointLocation::AddPerClosure(Debugger* dbg,
433 const Instance& closure) { 436 const Instance& closure,
437 bool for_over_await) {
434 Breakpoint* bpt = breakpoints(); 438 Breakpoint* bpt = breakpoints();
435 while (bpt != NULL) { 439 while (bpt != NULL) {
436 if (bpt->IsPerClosure() && bpt->closure() == closure.raw()) break; 440 if (bpt->IsPerClosure() && bpt->closure() == closure.raw()) break;
437 bpt = bpt->next(); 441 bpt = bpt->next();
438 } 442 }
439 if (bpt == NULL) { 443 if (bpt == NULL) {
440 bpt = new Breakpoint(dbg->nextId(), this); 444 bpt = new Breakpoint(dbg->nextId(), this);
441 bpt->SetIsPerClosure(closure); 445 bpt->SetIsPerClosure(closure);
446 bpt->set_is_synthetic_async(for_over_await);
442 AddBreakpoint(bpt, dbg); 447 AddBreakpoint(bpt, dbg);
443 } 448 }
444 return bpt; 449 return bpt;
445 } 450 }
446 451
447 452
448 const char* Debugger::QualifiedFunctionName(const Function& func) { 453 const char* Debugger::QualifiedFunctionName(const Function& func) {
449 const String& func_name = String::Handle(func.name()); 454 const String& func_name = String::Handle(func.name());
450 Class& func_class = Class::Handle(func.Owner()); 455 Class& func_class = Class::Handle(func.Owner());
451 String& class_name = String::Handle(func_class.Name()); 456 String& class_name = String::Handle(func_class.Name());
(...skipping 809 matching lines...) Expand 10 before | Expand all | Expand 10 after
1261 latent_locations_(NULL), 1266 latent_locations_(NULL),
1262 breakpoint_locations_(NULL), 1267 breakpoint_locations_(NULL),
1263 code_breakpoints_(NULL), 1268 code_breakpoints_(NULL),
1264 resume_action_(kContinue), 1269 resume_action_(kContinue),
1265 ignore_breakpoints_(false), 1270 ignore_breakpoints_(false),
1266 pause_event_(NULL), 1271 pause_event_(NULL),
1267 obj_cache_(NULL), 1272 obj_cache_(NULL),
1268 stack_trace_(NULL), 1273 stack_trace_(NULL),
1269 stepping_fp_(0), 1274 stepping_fp_(0),
1270 skip_next_step_(false), 1275 skip_next_step_(false),
1276 synthetic_async_breakpoint_(NULL),
1271 exc_pause_info_(kNoPauseOnExceptions) { 1277 exc_pause_info_(kNoPauseOnExceptions) {
1272 } 1278 }
1273 1279
1274 1280
1275 Debugger::~Debugger() { 1281 Debugger::~Debugger() {
1276 isolate_id_ = ILLEGAL_ISOLATE_ID; 1282 isolate_id_ = ILLEGAL_ISOLATE_ID;
1277 ASSERT(!IsPaused()); 1283 ASSERT(!IsPaused());
1278 ASSERT(latent_locations_ == NULL); 1284 ASSERT(latent_locations_ == NULL);
1279 ASSERT(breakpoint_locations_ == NULL); 1285 ASSERT(breakpoint_locations_ == NULL);
1280 ASSERT(code_breakpoints_ == NULL); 1286 ASSERT(code_breakpoints_ == NULL);
1281 ASSERT(stack_trace_ == NULL); 1287 ASSERT(stack_trace_ == NULL);
1282 ASSERT(obj_cache_ == NULL); 1288 ASSERT(obj_cache_ == NULL);
1289 ASSERT(synthetic_async_breakpoint_ == NULL);
1283 } 1290 }
1284 1291
1285 1292
1286 void Debugger::Shutdown() { 1293 void Debugger::Shutdown() {
1287 // TODO(johnmccutchan): Do not create a debugger for isolates that don't need 1294 // TODO(johnmccutchan): Do not create a debugger for isolates that don't need
1288 // them. Then, assert here that isolate_ is not one of those isolates. 1295 // them. Then, assert here that isolate_ is not one of those isolates.
1289 if ((isolate_ == Dart::vm_isolate()) || 1296 if ((isolate_ == Dart::vm_isolate()) ||
1290 ServiceIsolate::IsServiceIsolateDescendant(isolate_)) { 1297 ServiceIsolate::IsServiceIsolateDescendant(isolate_)) {
1291 return; 1298 return;
1292 } 1299 }
(...skipping 26 matching lines...) Expand all
1319 const String& fname) { 1326 const String& fname) {
1320 ASSERT(!library.IsNull()); 1327 ASSERT(!library.IsNull());
1321 const Object& object = Object::Handle(library.ResolveName(fname)); 1328 const Object& object = Object::Handle(library.ResolveName(fname));
1322 if (!object.IsNull() && object.IsFunction()) { 1329 if (!object.IsNull() && object.IsFunction()) {
1323 return Function::Cast(object).raw(); 1330 return Function::Cast(object).raw();
1324 } 1331 }
1325 return Function::null(); 1332 return Function::null();
1326 } 1333 }
1327 1334
1328 1335
1336 bool Debugger::SetupStepOverAsyncSuspension() {
1337 ActivationFrame* top_frame = TopDartFrame();
1338 if (!IsAtAsyncJump(top_frame)) {
1339 // Not at an async operation.
1340 return false;
1341 }
1342 Object& closure = Object::Handle(top_frame->GetAsyncOperation());
1343 ASSERT(!closure.IsNull());
1344 ASSERT(closure.IsInstance());
1345 ASSERT(Instance::Cast(closure).IsClosure());
1346 Breakpoint* bpt = SetBreakpointAtActivation(Instance::Cast(closure), true);
1347 if (bpt == NULL) {
1348 // Unable to set the breakpoint.
1349 return false;
1350 }
1351 return true;
1352 }
1353
1354
1329 void Debugger::SetSingleStep() { 1355 void Debugger::SetSingleStep() {
1330 resume_action_ = kSingleStep; 1356 resume_action_ = kSingleStep;
1331 } 1357 }
1332 1358
1333 1359
1334 void Debugger::SetStepOver() { 1360 void Debugger::SetStepOver() {
1335 resume_action_ = kStepOver; 1361 resume_action_ = kStepOver;
1336 } 1362 }
1337 1363
1338 1364
(...skipping 809 matching lines...) Expand 10 before | Expand all | Expand 10 after
2148 target_function.end_token_pos(), 2174 target_function.end_token_pos(),
2149 -1, -1 /* no requested line/col */); 2175 -1, -1 /* no requested line/col */);
2150 if (single_shot) { 2176 if (single_shot) {
2151 return bpt_location->AddSingleShot(this); 2177 return bpt_location->AddSingleShot(this);
2152 } else { 2178 } else {
2153 return bpt_location->AddRepeated(this); 2179 return bpt_location->AddRepeated(this);
2154 } 2180 }
2155 } 2181 }
2156 2182
2157 2183
2158 Breakpoint* Debugger::SetBreakpointAtActivation(const Instance& closure) { 2184 Breakpoint* Debugger::SetBreakpointAtActivation(
2185 const Instance& closure, bool for_over_await) {
2159 if (!closure.IsClosure()) { 2186 if (!closure.IsClosure()) {
2160 return NULL; 2187 return NULL;
2161 } 2188 }
2162 const Function& func = Function::Handle(Closure::Cast(closure).function()); 2189 const Function& func = Function::Handle(Closure::Cast(closure).function());
2163 const Script& script = Script::Handle(func.script()); 2190 const Script& script = Script::Handle(func.script());
2164 BreakpointLocation* bpt_location = SetBreakpoint(script, 2191 BreakpointLocation* bpt_location = SetBreakpoint(script,
2165 func.token_pos(), 2192 func.token_pos(),
2166 func.end_token_pos(), 2193 func.end_token_pos(),
2167 -1, -1 /* no line/col */); 2194 -1, -1 /* no line/col */);
2168 return bpt_location->AddPerClosure(this, closure); 2195 return bpt_location->AddPerClosure(this, closure, for_over_await);
2169 } 2196 }
2170 2197
2171 2198
2172 Breakpoint* Debugger::BreakpointAtActivation(const Instance& closure) { 2199 Breakpoint* Debugger::BreakpointAtActivation(const Instance& closure) {
2173 if (!closure.IsClosure()) { 2200 if (!closure.IsClosure()) {
2174 return NULL; 2201 return NULL;
2175 } 2202 }
2176 2203
2177 BreakpointLocation* loc = breakpoint_locations_; 2204 BreakpointLocation* loc = breakpoint_locations_;
2178 while (loc != NULL) { 2205 while (loc != NULL) {
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after
2610 ASSERT(!IsPaused()); 2637 ASSERT(!IsPaused());
2611 ASSERT(obj_cache_ == NULL); 2638 ASSERT(obj_cache_ == NULL);
2612 if ((bpt != NULL) && bpt->IsSingleShot()) { 2639 if ((bpt != NULL) && bpt->IsSingleShot()) {
2613 RemoveBreakpoint(bpt->id()); 2640 RemoveBreakpoint(bpt->id());
2614 bpt = NULL; 2641 bpt = NULL;
2615 } 2642 }
2616 2643
2617 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointReached); 2644 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointReached);
2618 event.set_top_frame(top_frame); 2645 event.set_top_frame(top_frame);
2619 event.set_breakpoint(bpt); 2646 event.set_breakpoint(bpt);
2647 event.set_at_async_jump(IsAtAsyncJump(top_frame));
2648 Pause(&event);
2649 }
2650
2651
2652 bool Debugger::IsAtAsyncJump(ActivationFrame* top_frame) {
2620 Object& closure_or_null = Object::Handle(top_frame->GetAsyncOperation()); 2653 Object& closure_or_null = Object::Handle(top_frame->GetAsyncOperation());
2621 if (!closure_or_null.IsNull()) { 2654 if (!closure_or_null.IsNull()) {
2622 ASSERT(closure_or_null.IsInstance()); 2655 ASSERT(closure_or_null.IsInstance());
2623 ASSERT(Instance::Cast(closure_or_null).IsClosure()); 2656 ASSERT(Instance::Cast(closure_or_null).IsClosure());
2624 event.set_async_continuation(&closure_or_null);
2625 const Script& script = Script::Handle(top_frame->SourceScript()); 2657 const Script& script = Script::Handle(top_frame->SourceScript());
2626 const TokenStream& tokens = TokenStream::Handle(script.tokens()); 2658 const TokenStream& tokens = TokenStream::Handle(script.tokens());
2627 TokenStream::Iterator iter(tokens, top_frame->TokenPos()); 2659 TokenStream::Iterator iter(tokens, top_frame->TokenPos());
2628 if ((iter.CurrentTokenKind() == Token::kIDENT) && 2660 if ((iter.CurrentTokenKind() == Token::kIDENT) &&
2629 ((iter.CurrentLiteral() == Symbols::Await().raw()) || 2661 ((iter.CurrentLiteral() == Symbols::Await().raw()) ||
2630 (iter.CurrentLiteral() == Symbols::YieldKw().raw()))) { 2662 (iter.CurrentLiteral() == Symbols::YieldKw().raw()))) {
2631 event.set_at_async_jump(true); 2663 return true;
2632 } 2664 }
2633 } 2665 }
2634 Pause(&event); 2666 return false;
2635 } 2667 }
2636 2668
2637
2638 RawError* Debugger::DebuggerStepCallback() { 2669 RawError* Debugger::DebuggerStepCallback() {
2639 ASSERT(isolate_->single_step()); 2670 ASSERT(isolate_->single_step());
2640 // Don't pause recursively. 2671 // Don't pause recursively.
2641 if (IsPaused()) { 2672 if (IsPaused()) {
2642 return Error::null(); 2673 return Error::null();
2643 } 2674 }
2644 if (skip_next_step_) { 2675 if (skip_next_step_) {
2645 skip_next_step_ = false; 2676 skip_next_step_ = false;
2646 return Error::null(); 2677 return Error::null();
2647 } 2678 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2684 if (FLAG_verbose_debug) { 2715 if (FLAG_verbose_debug) {
2685 OS::Print(">>> single step break at %s:%" Pd " (func %s token %s)\n", 2716 OS::Print(">>> single step break at %s:%" Pd " (func %s token %s)\n",
2686 String::Handle(frame->SourceUrl()).ToCString(), 2717 String::Handle(frame->SourceUrl()).ToCString(),
2687 frame->LineNumber(), 2718 frame->LineNumber(),
2688 String::Handle(frame->QualifiedFunctionName()).ToCString(), 2719 String::Handle(frame->QualifiedFunctionName()).ToCString(),
2689 frame->TokenPos().ToCString()); 2720 frame->TokenPos().ToCString());
2690 } 2721 }
2691 2722
2692 ASSERT(stack_trace_ == NULL); 2723 ASSERT(stack_trace_ == NULL);
2693 stack_trace_ = CollectStackTrace(); 2724 stack_trace_ = CollectStackTrace();
2694 SignalPausedEvent(frame, NULL); 2725 // If this step callback is part of stepping over an await statement,
2726 // we saved the synthetic async breakpoint in SignalBpReached. We report
2727 // that we are paused at that breakpoint and then delete it after continuing.
2728 SignalPausedEvent(frame, synthetic_async_breakpoint_);
2729 if (synthetic_async_breakpoint_ != NULL) {
2730 RemoveBreakpoint(synthetic_async_breakpoint_->id());
2731 synthetic_async_breakpoint_ = NULL;
2732 }
2695 HandleSteppingRequest(stack_trace_); 2733 HandleSteppingRequest(stack_trace_);
2696 stack_trace_ = NULL; 2734 stack_trace_ = NULL;
2697 2735
2698 // If any error occurred while in the debug message loop, return it here. 2736 // If any error occurred while in the debug message loop, return it here.
2699 const Error& error = Error::Handle(Thread::Current()->sticky_error()); 2737 const Error& error = Error::Handle(Thread::Current()->sticky_error());
2700 Thread::Current()->clear_sticky_error(); 2738 Thread::Current()->clear_sticky_error();
2701 return error.raw(); 2739 return error.raw();
2702 } 2740 }
2703 2741
2704 2742
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2757 } 2795 }
2758 bpt = bpt->next(); 2796 bpt = bpt->next();
2759 } 2797 }
2760 } 2798 }
2761 } 2799 }
2762 2800
2763 if (bpt_hit == NULL) { 2801 if (bpt_hit == NULL) {
2764 return Error::null(); 2802 return Error::null();
2765 } 2803 }
2766 2804
2805 if (bpt_hit->is_synthetic_async()) {
2806 DebuggerStackTrace* stack_trace = CollectStackTrace();
2807 ASSERT(stack_trace->Length() > 0);
2808 ASSERT(stack_trace_ == NULL);
2809 stack_trace_ = stack_trace;
2810
2811 // Hit a synthetic async breakpoint.
2812 if (FLAG_verbose_debug) {
2813 OS::Print(">>> hit synthetic breakpoint at %s:%" Pd " "
2814 "(token %s) (address %#" Px ")\n",
2815 String::Handle(cbpt->SourceUrl()).ToCString(),
2816 cbpt->LineNumber(),
2817 cbpt->token_pos().ToCString(),
2818 top_frame->pc());
2819 }
2820
2821 ASSERT(synthetic_async_breakpoint_ == NULL);
2822 synthetic_async_breakpoint_ = bpt_hit;
2823 bpt_hit = NULL;
2824
2825 // We are at the entry of an async function.
2826 // We issue a step over to resume at the point after the await statement.
2827 SetStepOver();
2828 // When we single step from a user breakpoint, our next stepping
2829 // point will be at the exact same pc. Skip it.
2830 HandleSteppingRequest(stack_trace_, true /* skip next step */);
2831 stack_trace_ = NULL;
2832 return Error::null();
2833 }
2834
2767 if (FLAG_verbose_debug) { 2835 if (FLAG_verbose_debug) {
2768 OS::Print(">>> hit %s breakpoint at %s:%" Pd " " 2836 OS::Print(">>> hit %s breakpoint at %s:%" Pd " "
2769 "(token %s) (address %#" Px ")\n", 2837 "(token %s) (address %#" Px ")\n",
2770 cbpt->IsInternal() ? "internal" : "user", 2838 cbpt->IsInternal() ? "internal" : "user",
2771 String::Handle(cbpt->SourceUrl()).ToCString(), 2839 String::Handle(cbpt->SourceUrl()).ToCString(),
2772 cbpt->LineNumber(), 2840 cbpt->LineNumber(),
2773 cbpt->token_pos().ToCString(), 2841 cbpt->token_pos().ToCString(),
2774 top_frame->pc()); 2842 top_frame->pc());
2775 } 2843 }
2776 2844
(...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after
3274 3342
3275 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 3343 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
3276 ASSERT(bpt->next() == NULL); 3344 ASSERT(bpt->next() == NULL);
3277 bpt->set_next(code_breakpoints_); 3345 bpt->set_next(code_breakpoints_);
3278 code_breakpoints_ = bpt; 3346 code_breakpoints_ = bpt;
3279 } 3347 }
3280 3348
3281 #endif // !PRODUCT 3349 #endif // !PRODUCT
3282 3350
3283 } // namespace dart 3351 } // namespace dart
OLDNEW
« 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