OLD | NEW |
---|---|
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 Loading... | |
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("isSyntheticAsyncBreakpoint", 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 Loading... | |
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 867 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1319 const String& fname) { | 1324 const String& fname) { |
1320 ASSERT(!library.IsNull()); | 1325 ASSERT(!library.IsNull()); |
1321 const Object& object = Object::Handle(library.ResolveName(fname)); | 1326 const Object& object = Object::Handle(library.ResolveName(fname)); |
1322 if (!object.IsNull() && object.IsFunction()) { | 1327 if (!object.IsNull() && object.IsFunction()) { |
1323 return Function::Cast(object).raw(); | 1328 return Function::Cast(object).raw(); |
1324 } | 1329 } |
1325 return Function::null(); | 1330 return Function::null(); |
1326 } | 1331 } |
1327 | 1332 |
1328 | 1333 |
1334 bool Debugger::SetupStepOverAwait() { | |
1335 ActivationFrame* top_frame = TopDartFrame(); | |
1336 Object& closure_or_null = Object::Handle(top_frame->GetAsyncOperation()); | |
1337 if (closure_or_null.IsNull()) { | |
1338 // Not at an async operation. | |
1339 return false; | |
1340 } | |
1341 // Add a break point at the async continuation closure. | |
1342 ASSERT(closure_or_null.IsInstance()); | |
1343 ASSERT(Instance::Cast(closure_or_null).IsClosure()); | |
1344 Breakpoint* bpt = | |
1345 SetBreakpointAtActivation(Instance::Cast(closure_or_null), true); | |
1346 if (bpt == NULL) { | |
1347 // Unable to set the breakpoint. | |
1348 return false; | |
1349 } | |
1350 return true; | |
1351 } | |
1352 | |
1353 | |
1329 void Debugger::SetSingleStep() { | 1354 void Debugger::SetSingleStep() { |
1330 resume_action_ = kSingleStep; | 1355 resume_action_ = kSingleStep; |
1331 } | 1356 } |
1332 | 1357 |
1333 | 1358 |
1334 void Debugger::SetStepOver() { | 1359 void Debugger::SetStepOver() { |
1335 resume_action_ = kStepOver; | 1360 resume_action_ = kStepOver; |
1336 } | 1361 } |
1337 | 1362 |
1338 | 1363 |
(...skipping 809 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2148 target_function.end_token_pos(), | 2173 target_function.end_token_pos(), |
2149 -1, -1 /* no requested line/col */); | 2174 -1, -1 /* no requested line/col */); |
2150 if (single_shot) { | 2175 if (single_shot) { |
2151 return bpt_location->AddSingleShot(this); | 2176 return bpt_location->AddSingleShot(this); |
2152 } else { | 2177 } else { |
2153 return bpt_location->AddRepeated(this); | 2178 return bpt_location->AddRepeated(this); |
2154 } | 2179 } |
2155 } | 2180 } |
2156 | 2181 |
2157 | 2182 |
2158 Breakpoint* Debugger::SetBreakpointAtActivation(const Instance& closure) { | 2183 Breakpoint* Debugger::SetBreakpointAtActivation( |
2184 const Instance& closure, bool for_over_await) { | |
2159 if (!closure.IsClosure()) { | 2185 if (!closure.IsClosure()) { |
2160 return NULL; | 2186 return NULL; |
2161 } | 2187 } |
2162 const Function& func = Function::Handle(Closure::Cast(closure).function()); | 2188 const Function& func = Function::Handle(Closure::Cast(closure).function()); |
2163 const Script& script = Script::Handle(func.script()); | 2189 const Script& script = Script::Handle(func.script()); |
2164 BreakpointLocation* bpt_location = SetBreakpoint(script, | 2190 BreakpointLocation* bpt_location = SetBreakpoint(script, |
2165 func.token_pos(), | 2191 func.token_pos(), |
2166 func.end_token_pos(), | 2192 func.end_token_pos(), |
2167 -1, -1 /* no line/col */); | 2193 -1, -1 /* no line/col */); |
2168 return bpt_location->AddPerClosure(this, closure); | 2194 return bpt_location->AddPerClosure(this, closure, for_over_await); |
2169 } | 2195 } |
2170 | 2196 |
2171 | 2197 |
2172 Breakpoint* Debugger::BreakpointAtActivation(const Instance& closure) { | 2198 Breakpoint* Debugger::BreakpointAtActivation(const Instance& closure) { |
2173 if (!closure.IsClosure()) { | 2199 if (!closure.IsClosure()) { |
2174 return NULL; | 2200 return NULL; |
2175 } | 2201 } |
2176 | 2202 |
2177 BreakpointLocation* loc = breakpoint_locations_; | 2203 BreakpointLocation* loc = breakpoint_locations_; |
2178 while (loc != NULL) { | 2204 while (loc != NULL) { |
(...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2757 } | 2783 } |
2758 bpt = bpt->next(); | 2784 bpt = bpt->next(); |
2759 } | 2785 } |
2760 } | 2786 } |
2761 } | 2787 } |
2762 | 2788 |
2763 if (bpt_hit == NULL) { | 2789 if (bpt_hit == NULL) { |
2764 return Error::null(); | 2790 return Error::null(); |
2765 } | 2791 } |
2766 | 2792 |
2793 if (bpt_hit->is_synthetic_async()) { | |
2794 DebuggerStackTrace* stack_trace = CollectStackTrace(); | |
2795 ASSERT(stack_trace->Length() > 0); | |
2796 ASSERT(stack_trace_ == NULL); | |
2797 stack_trace_ = stack_trace; | |
2798 | |
2799 // Hit a synthetic async breakpoint. | |
2800 if (FLAG_verbose_debug) { | |
2801 OS::Print(">>> hit synthetic breakpoint at %s:%" Pd " " | |
2802 "(token %s) (address %#" Px ")\n", | |
2803 String::Handle(cbpt->SourceUrl()).ToCString(), | |
2804 cbpt->LineNumber(), | |
2805 cbpt->token_pos().ToCString(), | |
2806 top_frame->pc()); | |
2807 } | |
2808 | |
2809 RemoveBreakpoint(bpt_hit->id()); | |
2810 bpt_hit = NULL; | |
rmacnak
2016/02/16 21:21:58
It would clearer from the client's perspective if
Cutch
2016/02/17 18:24:21
Done.
| |
2811 | |
2812 // We are at the entry of an async function. | |
2813 // We issue a step over to resume at the point after the await statement. | |
2814 SetStepOver(); | |
2815 // When we single step from a user breakpoint, our next stepping | |
2816 // point will be at the exact same pc. Skip it. | |
2817 HandleSteppingRequest(stack_trace_, true /* skip next step */); | |
2818 stack_trace_ = NULL; | |
2819 return Error::null(); | |
2820 } | |
2821 | |
2767 if (FLAG_verbose_debug) { | 2822 if (FLAG_verbose_debug) { |
2768 OS::Print(">>> hit %s breakpoint at %s:%" Pd " " | 2823 OS::Print(">>> hit %s breakpoint at %s:%" Pd " " |
2769 "(token %s) (address %#" Px ")\n", | 2824 "(token %s) (address %#" Px ")\n", |
2770 cbpt->IsInternal() ? "internal" : "user", | 2825 cbpt->IsInternal() ? "internal" : "user", |
2771 String::Handle(cbpt->SourceUrl()).ToCString(), | 2826 String::Handle(cbpt->SourceUrl()).ToCString(), |
2772 cbpt->LineNumber(), | 2827 cbpt->LineNumber(), |
2773 cbpt->token_pos().ToCString(), | 2828 cbpt->token_pos().ToCString(), |
2774 top_frame->pc()); | 2829 top_frame->pc()); |
2775 } | 2830 } |
2776 | 2831 |
(...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3274 | 3329 |
3275 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 3330 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
3276 ASSERT(bpt->next() == NULL); | 3331 ASSERT(bpt->next() == NULL); |
3277 bpt->set_next(code_breakpoints_); | 3332 bpt->set_next(code_breakpoints_); |
3278 code_breakpoints_ = bpt; | 3333 code_breakpoints_ = bpt; |
3279 } | 3334 } |
3280 | 3335 |
3281 #endif // !PRODUCT | 3336 #endif // !PRODUCT |
3282 | 3337 |
3283 } // namespace dart | 3338 } // namespace dart |
OLD | NEW |