Chromium Code Reviews| 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 "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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |