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

Side by Side Diff: runtime/vm/debugger.cc

Issue 2912763005: Hit breakpoints in single line closures. (Closed)
Patch Set: Created 3 years, 6 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 | « no previous file | runtime/vm/debugger_test.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 "platform/address_sanitizer.h" 9 #include "platform/address_sanitizer.h"
10 10
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 const String& func_name = String::Handle(func.name()); 472 const String& func_name = String::Handle(func.name());
473 Class& func_class = Class::Handle(func.Owner()); 473 Class& func_class = Class::Handle(func.Owner());
474 String& class_name = String::Handle(func_class.Name()); 474 String& class_name = String::Handle(func_class.Name());
475 475
476 return OS::SCreate(Thread::Current()->zone(), "%s%s%s", 476 return OS::SCreate(Thread::Current()->zone(), "%s%s%s",
477 func_class.IsTopLevel() ? "" : class_name.ToCString(), 477 func_class.IsTopLevel() ? "" : class_name.ToCString(),
478 func_class.IsTopLevel() ? "" : ".", func_name.ToCString()); 478 func_class.IsTopLevel() ? "" : ".", func_name.ToCString());
479 } 479 }
480 480
481 481
482 // Returns true if function contains the token position in the given script. 482 // Returns true if the function |func| overlaps the token range
483 static bool FunctionContains(const Function& func, 483 // [|token_pos|, |end_token_pos|] in |script|.
484 static bool FunctionOverlaps(const Function& func,
484 const Script& script, 485 const Script& script,
485 TokenPosition token_pos) { 486 TokenPosition token_pos,
486 if ((func.token_pos() <= token_pos) && (token_pos <= func.end_token_pos())) { 487 TokenPosition end_token_pos) {
488 TokenPosition func_start = func.token_pos();
489 if (((func_start <= token_pos) && (token_pos <= func.end_token_pos())) ||
490 ((token_pos <= func_start) && (func_start <= end_token_pos))) {
487 // Check script equality second because it allocates 491 // Check script equality second because it allocates
488 // handles as a side effect. 492 // handles as a side effect.
489 return func.script() == script.raw(); 493 return func.script() == script.raw();
490 } 494 }
491 return false; 495 return false;
492 } 496 }
493 497
494 498
499 static bool IsImplicitFunction(const Function& func) {
500 switch (func.kind()) {
501 case RawFunction::kImplicitGetter:
502 case RawFunction::kImplicitSetter:
503 case RawFunction::kImplicitStaticFinalGetter:
504 return true;
505 default:
506 return false;
507 }
508 }
509
510
495 bool Debugger::HasBreakpoint(const Function& func, Zone* zone) { 511 bool Debugger::HasBreakpoint(const Function& func, Zone* zone) {
496 if (!func.HasCode()) { 512 if (!func.HasCode()) {
497 // If the function is not compiled yet, just check whether there 513 // If the function is not compiled yet, just check whether there
498 // is a user-defined breakpoint that falls into the token 514 // is a user-defined breakpoint that falls into the token
499 // range of the function. This may be a false positive: the breakpoint 515 // range of the function. This may be a false positive: the breakpoint
500 // might be inside a local closure. 516 // might be inside a local closure.
501 Script& script = Script::Handle(zone); 517 Script& script = Script::Handle(zone);
502 BreakpointLocation* sbpt = breakpoint_locations_; 518 BreakpointLocation* sbpt = breakpoint_locations_;
503 while (sbpt != NULL) { 519 while (sbpt != NULL) {
504 script = sbpt->script(); 520 script = sbpt->script();
505 if (FunctionContains(func, script, sbpt->token_pos())) { 521 if (FunctionOverlaps(func, script, sbpt->token_pos(),
522 sbpt->end_token_pos())) {
506 return true; 523 return true;
507 } 524 }
508 sbpt = sbpt->next_; 525 sbpt = sbpt->next_;
509 } 526 }
510 return false; 527 return false;
511 } 528 }
512 CodeBreakpoint* cbpt = code_breakpoints_; 529 CodeBreakpoint* cbpt = code_breakpoints_;
513 while (cbpt != NULL) { 530 while (cbpt != NULL) {
514 if (func.raw() == cbpt->function()) { 531 if (func.raw() == cbpt->function()) {
515 return true; 532 return true;
(...skipping 2127 matching lines...) Expand 10 before | Expand all | Expand 10 after
2643 *best_fit = func->raw(); 2660 *best_fit = func->raw();
2644 } else { 2661 } else {
2645 if ((func->token_pos() > best_fit->token_pos()) && 2662 if ((func->token_pos() > best_fit->token_pos()) &&
2646 ((func->end_token_pos() <= best_fit->end_token_pos()))) { 2663 ((func->end_token_pos() <= best_fit->end_token_pos()))) {
2647 *best_fit = func->raw(); 2664 *best_fit = func->raw();
2648 } 2665 }
2649 } 2666 }
2650 } 2667 }
2651 2668
2652 2669
2653 static bool IsTokenPosWithinFunction(const Function& func, TokenPosition pos) {
2654 return (func.token_pos() <= pos && pos <= func.end_token_pos());
2655 }
2656
2657
2658 // Returns true if a best fit is found. A best fit can either be a function 2670 // Returns true if a best fit is found. A best fit can either be a function
2659 // or a field. If it is a function, then the best fit function is returned 2671 // or a field. If it is a function, then the best fit function is returned
2660 // in |best_fit|. If a best fit is a field, it means that a latent 2672 // in |best_fit|. If a best fit is a field, it means that a latent
2661 // breakpoint can be set in the range |token_pos| to |last_token_pos|. 2673 // breakpoint can be set in the range |token_pos| to |last_token_pos|.
2662 bool Debugger::FindBestFit(const Script& script, 2674 bool Debugger::FindBestFit(const Script& script,
2663 TokenPosition token_pos, 2675 TokenPosition token_pos,
2664 TokenPosition last_token_pos, 2676 TokenPosition last_token_pos,
2665 Function* best_fit) { 2677 Function* best_fit) {
2666 Zone* zone = Thread::Current()->zone(); 2678 Zone* zone = Thread::Current()->zone();
2667 Class& cls = Class::Handle(zone); 2679 Class& cls = Class::Handle(zone);
2668 const GrowableObjectArray& closures = GrowableObjectArray::Handle( 2680 const GrowableObjectArray& closures = GrowableObjectArray::Handle(
2669 zone, isolate_->object_store()->closure_functions()); 2681 zone, isolate_->object_store()->closure_functions());
2670 Array& functions = Array::Handle(zone); 2682 Array& functions = Array::Handle(zone);
2671 Function& function = Function::Handle(zone); 2683 Function& function = Function::Handle(zone);
2672 Array& fields = Array::Handle(zone); 2684 Array& fields = Array::Handle(zone);
2673 Field& field = Field::Handle(zone); 2685 Field& field = Field::Handle(zone);
2674 Error& error = Error::Handle(zone); 2686 Error& error = Error::Handle(zone);
2675 2687
2676 const intptr_t num_closures = closures.Length(); 2688 const intptr_t num_closures = closures.Length();
2677 for (intptr_t i = 0; i < num_closures; i++) { 2689 for (intptr_t i = 0; i < num_closures; i++) {
2678 function ^= closures.At(i); 2690 function ^= closures.At(i);
2679 if (function.script() != script.raw()) { 2691 if (FunctionOverlaps(function, script, token_pos, last_token_pos)) {
2680 continue;
2681 }
2682 if (IsTokenPosWithinFunction(function, token_pos)) {
2683 // Select the inner most closure. 2692 // Select the inner most closure.
2684 SelectBestFit(best_fit, &function); 2693 SelectBestFit(best_fit, &function);
2685 } 2694 }
2686 } 2695 }
2687 if (!best_fit->IsNull()) { 2696 if (!best_fit->IsNull()) {
2688 // The inner most closure found will be the best fit. Going 2697 // The inner most closure found will be the best fit. Going
2689 // over class functions below will not help in any further 2698 // over class functions below will not help in any further
2690 // narrowing. 2699 // narrowing.
2691 return true; 2700 return true;
2692 } 2701 }
(...skipping 16 matching lines...) Expand all
2709 // EnsureIsFinalized only returns an error object if there 2718 // EnsureIsFinalized only returns an error object if there
2710 // is no longjump base on the stack. 2719 // is no longjump base on the stack.
2711 continue; 2720 continue;
2712 } 2721 }
2713 functions = cls.functions(); 2722 functions = cls.functions();
2714 if (!functions.IsNull()) { 2723 if (!functions.IsNull()) {
2715 const intptr_t num_functions = functions.Length(); 2724 const intptr_t num_functions = functions.Length();
2716 for (intptr_t pos = 0; pos < num_functions; pos++) { 2725 for (intptr_t pos = 0; pos < num_functions; pos++) {
2717 function ^= functions.At(pos); 2726 function ^= functions.At(pos);
2718 ASSERT(!function.IsNull()); 2727 ASSERT(!function.IsNull());
2719 if (IsTokenPosWithinFunction(function, token_pos)) { 2728 if (IsImplicitFunction(function)) {
siva 2017/05/31 19:20:54 Should this also include other function types that
sivachandra 2017/05/31 20:16:46 Likewise, I think there are implicit constructors
2729 // Implicit functions do not have a user specifiable source
2730 // location.
2731 continue;
2732 }
2733 if (FunctionOverlaps(function, script, token_pos, last_token_pos)) {
2720 // Closures and inner functions within a class method are not 2734 // Closures and inner functions within a class method are not
2721 // present in the functions of a class. Hence, we can return 2735 // present in the functions of a class. Hence, we can return
2722 // right away as looking through other functions of a class 2736 // right away as looking through other functions of a class
2723 // will not narrow down to any inner function/closure. 2737 // will not narrow down to any inner function/closure.
2724 *best_fit = function.raw(); 2738 *best_fit = function.raw();
2725 return true; 2739 return true;
2726 } 2740 }
2727 } 2741 }
2728 } 2742 }
2729 // If none of the functions in the class contain token_pos, then we 2743 // If none of the functions in the class contain token_pos, then we
(...skipping 1307 matching lines...) Expand 10 before | Expand all | Expand 10 after
4037 // we'll resolve the breakpoint when the inner function is compiled. 4051 // we'll resolve the breakpoint when the inner function is compiled.
4038 return; 4052 return;
4039 } 4053 }
4040 // Iterate over all source breakpoints to check whether breakpoints 4054 // Iterate over all source breakpoints to check whether breakpoints
4041 // need to be set in the newly compiled function. 4055 // need to be set in the newly compiled function.
4042 Zone* zone = Thread::Current()->zone(); 4056 Zone* zone = Thread::Current()->zone();
4043 Script& script = Script::Handle(zone); 4057 Script& script = Script::Handle(zone);
4044 for (BreakpointLocation* loc = breakpoint_locations_; loc != NULL; 4058 for (BreakpointLocation* loc = breakpoint_locations_; loc != NULL;
4045 loc = loc->next()) { 4059 loc = loc->next()) {
4046 script = loc->script(); 4060 script = loc->script();
4047 if (FunctionContains(func, script, loc->token_pos())) { 4061 if (FunctionOverlaps(func, script, loc->token_pos(),
4062 loc->end_token_pos())) {
4048 Function& inner_function = Function::Handle(zone); 4063 Function& inner_function = Function::Handle(zone);
4049 inner_function = FindInnermostClosure(func, loc->token_pos()); 4064 inner_function = FindInnermostClosure(func, loc->token_pos());
4050 if (!inner_function.IsNull()) { 4065 if (!inner_function.IsNull()) {
4051 // The local function of a function we just compiled cannot 4066 // The local function of a function we just compiled cannot
4052 // be compiled already. 4067 // be compiled already.
4053 ASSERT(!inner_function.HasCode()); 4068 ASSERT(!inner_function.HasCode());
4054 if (FLAG_verbose_debug) { 4069 if (FLAG_verbose_debug) {
4055 OS::Print("Pending BP remains unresolved in inner function '%s'\n", 4070 OS::Print("Pending BP remains unresolved in inner function '%s'\n",
4056 inner_function.ToFullyQualifiedCString()); 4071 inner_function.ToFullyQualifiedCString());
4057 } 4072 }
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after
4481 4496
4482 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 4497 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
4483 ASSERT(bpt->next() == NULL); 4498 ASSERT(bpt->next() == NULL);
4484 bpt->set_next(code_breakpoints_); 4499 bpt->set_next(code_breakpoints_);
4485 code_breakpoints_ = bpt; 4500 code_breakpoints_ = bpt;
4486 } 4501 }
4487 4502
4488 #endif // !PRODUCT 4503 #endif // !PRODUCT
4489 4504
4490 } // namespace dart 4505 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/debugger_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698