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

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

Issue 2904793002: Allow setting breakpoints in literal function initializers of fields. (Closed)
Patch Set: Add comments Created 3 years, 7 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
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
11 #include "vm/code_patcher.h" 11 #include "vm/code_patcher.h"
12 #include "vm/compiler.h" 12 #include "vm/compiler.h"
13 #include "vm/dart_entry.h" 13 #include "vm/dart_entry.h"
14 #include "vm/deopt_instructions.h" 14 #include "vm/deopt_instructions.h"
15 #include "vm/flags.h" 15 #include "vm/flags.h"
16 #include "vm/globals.h" 16 #include "vm/globals.h"
17 #include "vm/json_stream.h" 17 #include "vm/json_stream.h"
18 #include "vm/longjump.h" 18 #include "vm/longjump.h"
19 #include "vm/message_handler.h" 19 #include "vm/message_handler.h"
20 #include "vm/object.h" 20 #include "vm/object.h"
21 #include "vm/object_store.h" 21 #include "vm/object_store.h"
22 #include "vm/os.h" 22 #include "vm/os.h"
23 #include "vm/parser.h"
23 #include "vm/port.h" 24 #include "vm/port.h"
24 #include "vm/runtime_entry.h" 25 #include "vm/runtime_entry.h"
25 #include "vm/service.h" 26 #include "vm/service.h"
26 #include "vm/service_event.h" 27 #include "vm/service_event.h"
27 #include "vm/service_isolate.h" 28 #include "vm/service_isolate.h"
28 #include "vm/stack_frame.h" 29 #include "vm/stack_frame.h"
29 #include "vm/stack_trace.h" 30 #include "vm/stack_trace.h"
30 #include "vm/stub_code.h" 31 #include "vm/stub_code.h"
31 #include "vm/symbols.h" 32 #include "vm/symbols.h"
32 #include "vm/thread_interrupter.h" 33 #include "vm/thread_interrupter.h"
(...skipping 2668 matching lines...) Expand 10 before | Expand all | Expand 10 after
2701 SelectBestFit(&best_fit, &function); 2702 SelectBestFit(&best_fit, &function);
2702 } 2703 }
2703 } 2704 }
2704 } 2705 }
2705 } 2706 }
2706 } 2707 }
2707 return best_fit.raw(); 2708 return best_fit.raw();
2708 } 2709 }
2709 2710
2710 2711
2712 // Return true if |token_pos| is within the token range of a function
2713 // literal initializer of a field.
2714 bool Debugger::MatchesLiteralFunctionPos(const Script& script,
2715 TokenPosition token_pos,
2716 TokenPosition last_token_pos) {
2717 Zone* zone = Thread::Current()->zone();
2718 Class& cls = Class::Handle(zone);
2719 Array& fields = Array::Handle(zone);
2720 Field& field = Field::Handle(zone);
2721 Error& error = Error::Handle(zone);
2722
2723 const ClassTable& class_table = *isolate_->class_table();
2724 const intptr_t num_classes = class_table.NumCids();
2725 for (intptr_t i = 1; i < num_classes; i++) {
2726 if (class_table.HasValidClassAt(i)) {
2727 cls = class_table.At(i);
2728 ASSERT(!cls.IsNull());
2729 if (cls.script() != script.raw()) {
2730 continue;
2731 }
2732 error = cls.EnsureIsFinalized(Thread::Current());
2733 if (!error.IsNull()) {
2734 continue;
2735 }
2736 fields = cls.fields();
2737 if (!fields.IsNull()) {
2738 const intptr_t num_fields = fields.Length();
2739 for (intptr_t pos = 0; pos < num_fields; pos++) {
2740 TokenPosition start;
2741 TokenPosition end;
2742 field ^= fields.At(pos);
2743 ASSERT(!field.IsNull());
2744 if (Parser::FieldHasFunctionLiteralInitializer(field, &start, &end)) {
2745 if ((start <= token_pos && token_pos <= end) ||
2746 (token_pos <= start && start <= last_token_pos)) {
siva 2017/05/24 19:51:23 Not sure why this last_token_pos check needs to be
sivachandra 2017/05/26 07:17:58 We want the field initializer to start within the
2747 return true;
2748 }
2749 }
2750 }
2751 }
2752 }
siva 2017/05/24 19:51:23 Can the loop above be folded into Debugger::FindBe
sivachandra 2017/05/26 07:17:58 I have removed this new method and folded the esse
2753 }
2754 return false;
2755 }
2756
2757
2711 BreakpointLocation* Debugger::SetBreakpoint(const Script& script, 2758 BreakpointLocation* Debugger::SetBreakpoint(const Script& script,
2712 TokenPosition token_pos, 2759 TokenPosition token_pos,
2713 TokenPosition last_token_pos, 2760 TokenPosition last_token_pos,
2714 intptr_t requested_line, 2761 intptr_t requested_line,
2715 intptr_t requested_column) { 2762 intptr_t requested_column) {
2716 Function& func = Function::Handle(); 2763 Function& func = Function::Handle();
2717 func = FindBestFit(script, token_pos); 2764 func = FindBestFit(script, token_pos);
2718 if (func.IsNull()) { 2765 if (!func.IsNull()) {
2766 // There may be more than one function object for a given function
2767 // in source code. There may be implicit closure functions, and
2768 // there may be copies of mixin functions. Collect all compiled
2769 // functions whose source code range matches exactly the best fit
2770 // function we found.
2771 GrowableObjectArray& functions =
2772 GrowableObjectArray::Handle(GrowableObjectArray::New());
2773 FindCompiledFunctions(script, func.token_pos(), func.end_token_pos(),
2774 &functions);
2775
2776 if (functions.Length() > 0) {
2777 // One or more function object containing this breakpoint location
2778 // have already been compiled. We can resolve the breakpoint now.
2779 DeoptimizeWorld();
2780 func ^= functions.At(0);
2781 TokenPosition breakpoint_pos = ResolveBreakpointPos(
2782 func, token_pos, last_token_pos, requested_column);
2783 if (breakpoint_pos.IsReal()) {
2784 BreakpointLocation* bpt =
2785 GetBreakpointLocation(script, breakpoint_pos, requested_column);
2786 if (bpt != NULL) {
2787 // A source breakpoint for this location already exists.
2788 return bpt;
2789 }
2790 bpt = new BreakpointLocation(script, token_pos, last_token_pos,
2791 requested_line, requested_column);
2792 bpt->SetResolved(func, breakpoint_pos);
2793 RegisterBreakpointLocation(bpt);
2794
2795 // Create code breakpoints for all compiled functions we found.
2796 const intptr_t num_functions = functions.Length();
2797 for (intptr_t i = 0; i < num_functions; i++) {
2798 func ^= functions.At(i);
2799 ASSERT(func.HasCode());
2800 MakeCodeBreakpointAt(func, bpt);
2801 }
2802 if (FLAG_verbose_debug) {
2803 intptr_t line_number;
2804 intptr_t column_number;
2805 script.GetTokenLocation(breakpoint_pos, &line_number, &column_number);
2806 OS::Print(
2807 "Resolved BP for "
2808 "function '%s' at line %" Pd " col %" Pd "\n",
2809 func.ToFullyQualifiedCString(), line_number, column_number);
2810 }
2811 return bpt;
2812 }
2813 }
2814 } else if (!MatchesLiteralFunctionPos(script, token_pos, last_token_pos)) {
2815 // |token_pos| is not within the range of a function literal initializer of
2816 // a field.
2719 return NULL; 2817 return NULL;
2720 } 2818 }
2721 // There may be more than one function object for a given function 2819 // There is either an uncompiled function, or an uncompiled function literal
2722 // in source code. There may be implicit closure functions, and 2820 // initializer of a field at |token_pos|. Hence, Register an unresolved
2723 // there may be copies of mixin functions. Collect all compiled 2821 // breakpoint.
2724 // functions whose source code range matches exactly the best fit 2822 if (FLAG_verbose_debug) {
2725 // function we found.
2726 GrowableObjectArray& functions =
2727 GrowableObjectArray::Handle(GrowableObjectArray::New());
2728 FindCompiledFunctions(script, func.token_pos(), func.end_token_pos(),
2729 &functions);
2730
2731 if (functions.Length() > 0) {
2732 // One or more function object containing this breakpoint location
2733 // have already been compiled. We can resolve the breakpoint now.
2734 DeoptimizeWorld();
2735 func ^= functions.At(0);
2736 TokenPosition breakpoint_pos =
2737 ResolveBreakpointPos(func, token_pos, last_token_pos, requested_column);
2738 if (breakpoint_pos.IsReal()) {
2739 BreakpointLocation* bpt =
2740 GetBreakpointLocation(script, breakpoint_pos, requested_column);
2741 if (bpt != NULL) {
2742 // A source breakpoint for this location already exists.
2743 return bpt;
2744 }
2745 bpt = new BreakpointLocation(script, token_pos, last_token_pos,
2746 requested_line, requested_column);
2747 bpt->SetResolved(func, breakpoint_pos);
2748 RegisterBreakpointLocation(bpt);
2749
2750 // Create code breakpoints for all compiled functions we found.
2751 const intptr_t num_functions = functions.Length();
2752 for (intptr_t i = 0; i < num_functions; i++) {
2753 func ^= functions.At(i);
2754 ASSERT(func.HasCode());
2755 MakeCodeBreakpointAt(func, bpt);
2756 }
2757 if (FLAG_verbose_debug) {
2758 intptr_t line_number;
2759 intptr_t column_number;
2760 script.GetTokenLocation(breakpoint_pos, &line_number, &column_number);
2761 OS::Print(
2762 "Resolved BP for "
2763 "function '%s' at line %" Pd " col %" Pd "\n",
2764 func.ToFullyQualifiedCString(), line_number, column_number);
2765 }
2766 return bpt;
2767 }
2768 }
2769 // There is no compiled function at this token position.
2770 // Register an unresolved breakpoint.
2771 if (FLAG_verbose_debug && !func.IsNull()) {
2772 intptr_t line_number; 2823 intptr_t line_number;
2773 intptr_t column_number; 2824 intptr_t column_number;
2774 script.GetTokenLocation(token_pos, &line_number, &column_number); 2825 script.GetTokenLocation(token_pos, &line_number, &column_number);
2775 OS::Print( 2826 if (func.IsNull()) {
2776 "Registering pending breakpoint for " 2827 OS::Print(
2777 "uncompiled function '%s' at line %" Pd " col %" Pd "\n", 2828 "Registering pending breakpoint for "
2778 func.ToFullyQualifiedCString(), line_number, column_number); 2829 "an uncompiled function literal at line %" Pd " col %" Pd "\n",
2830 line_number, column_number);
2831 } else {
2832 OS::Print(
2833 "Registering pending breakpoint for "
2834 "uncompiled function '%s' at line %" Pd " col %" Pd "\n",
2835 func.ToFullyQualifiedCString(), line_number, column_number);
2836 }
2779 } 2837 }
2780 BreakpointLocation* bpt = 2838 BreakpointLocation* bpt =
2781 GetBreakpointLocation(script, token_pos, requested_column); 2839 GetBreakpointLocation(script, token_pos, requested_column);
2782 if (bpt == NULL) { 2840 if (bpt == NULL) {
2783 bpt = new BreakpointLocation(script, token_pos, last_token_pos, 2841 bpt = new BreakpointLocation(script, token_pos, last_token_pos,
2784 requested_line, requested_column); 2842 requested_line, requested_column);
2785 RegisterBreakpointLocation(bpt); 2843 RegisterBreakpointLocation(bpt);
2786 } 2844 }
2787 return bpt; 2845 return bpt;
2788 } 2846 }
(...skipping 1639 matching lines...) Expand 10 before | Expand all | Expand 10 after
4428 4486
4429 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 4487 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
4430 ASSERT(bpt->next() == NULL); 4488 ASSERT(bpt->next() == NULL);
4431 bpt->set_next(code_breakpoints_); 4489 bpt->set_next(code_breakpoints_);
4432 code_breakpoints_ = bpt; 4490 code_breakpoints_ = bpt;
4433 } 4491 }
4434 4492
4435 #endif // !PRODUCT 4493 #endif // !PRODUCT
4436 4494
4437 } // namespace dart 4495 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/debugger_test.cc » ('j') | runtime/vm/debugger_test.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698