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" |
11 #include "vm/compiler.h" | 11 #include "vm/compiler.h" |
12 #include "vm/dart_entry.h" | 12 #include "vm/dart_entry.h" |
13 #include "vm/deopt_instructions.h" | 13 #include "vm/deopt_instructions.h" |
14 #include "vm/flags.h" | 14 #include "vm/flags.h" |
15 #include "vm/globals.h" | 15 #include "vm/globals.h" |
16 #include "vm/longjump.h" | 16 #include "vm/longjump.h" |
17 #include "vm/json_stream.h" | 17 #include "vm/json_stream.h" |
18 #include "vm/message_handler.h" | 18 #include "vm/message_handler.h" |
19 #include "vm/object.h" | 19 #include "vm/object.h" |
20 #include "vm/object_store.h" | 20 #include "vm/object_store.h" |
21 #include "vm/os.h" | 21 #include "vm/os.h" |
22 #include "vm/port.h" | 22 #include "vm/port.h" |
23 #include "vm/service_event.h" | 23 #include "vm/service_event.h" |
24 #include "vm/service_isolate.h" | 24 #include "vm/service_isolate.h" |
25 #include "vm/service.h" | 25 #include "vm/service.h" |
26 #include "vm/stack_frame.h" | 26 #include "vm/stack_frame.h" |
27 #include "vm/stub_code.h" | 27 #include "vm/stub_code.h" |
28 #include "vm/symbols.h" | 28 #include "vm/symbols.h" |
29 #include "vm/thread_interrupter.h" | 29 #include "vm/thread_interrupter.h" |
| 30 #include "vm/token_descriptor.h" |
30 #include "vm/visitor.h" | 31 #include "vm/visitor.h" |
31 | 32 |
32 | 33 |
33 namespace dart { | 34 namespace dart { |
34 | 35 |
35 DEFINE_FLAG(bool, show_invisible_frames, false, | 36 DEFINE_FLAG(bool, show_invisible_frames, false, |
36 "Show invisible frames in debugger stack traces"); | 37 "Show invisible frames in debugger stack traces"); |
37 DEFINE_FLAG(bool, trace_debugger_stacktrace, false, | 38 DEFINE_FLAG(bool, trace_debugger_stacktrace, false, |
38 "Trace debugger stacktrace collection"); | 39 "Trace debugger stacktrace collection"); |
39 DEFINE_FLAG(bool, verbose_debug, false, "Verbose debugger messages"); | 40 DEFINE_FLAG(bool, verbose_debug, false, "Verbose debugger messages"); |
(...skipping 20 matching lines...) Expand all Loading... |
60 | 61 |
61 private: | 62 private: |
62 GrowableObjectArray* objs_; | 63 GrowableObjectArray* objs_; |
63 | 64 |
64 DISALLOW_COPY_AND_ASSIGN(RemoteObjectCache); | 65 DISALLOW_COPY_AND_ASSIGN(RemoteObjectCache); |
65 }; | 66 }; |
66 | 67 |
67 | 68 |
68 // Create an unresolved breakpoint in given token range and script. | 69 // Create an unresolved breakpoint in given token range and script. |
69 BreakpointLocation::BreakpointLocation(const Script& script, | 70 BreakpointLocation::BreakpointLocation(const Script& script, |
70 intptr_t token_pos, | 71 TokenDescriptor token_pos, |
71 intptr_t end_token_pos, | 72 TokenDescriptor end_token_pos, |
72 intptr_t requested_line_number, | 73 intptr_t requested_line_number, |
73 intptr_t requested_column_number) | 74 intptr_t requested_column_number) |
74 : script_(script.raw()), | 75 : script_(script.raw()), |
75 url_(script.url()), | 76 url_(script.url()), |
76 token_pos_(token_pos), | 77 token_pos_(token_pos), |
77 end_token_pos_(end_token_pos), | 78 end_token_pos_(end_token_pos), |
78 is_resolved_(false), | 79 is_resolved_(false), |
79 next_(NULL), | 80 next_(NULL), |
80 conditions_(NULL), | 81 conditions_(NULL), |
81 requested_line_number_(requested_line_number), | 82 requested_line_number_(requested_line_number), |
82 requested_column_number_(requested_column_number), | 83 requested_column_number_(requested_column_number), |
83 function_(Function::null()), | 84 function_(Function::null()), |
84 line_number_(-1), | 85 line_number_(-1), |
85 column_number_(-1) { | 86 column_number_(-1) { |
86 ASSERT(!script.IsNull()); | 87 ASSERT(!script.IsNull()); |
87 ASSERT(Token::IsReal(token_pos_)); | 88 ASSERT(TokenDescriptor(token_pos_).IsReal()); |
88 } | 89 } |
89 | 90 |
90 // Create a latent breakpoint at given url and line number. | 91 // Create a latent breakpoint at given url and line number. |
91 BreakpointLocation::BreakpointLocation(const String& url, | 92 BreakpointLocation::BreakpointLocation(const String& url, |
92 intptr_t requested_line_number, | 93 intptr_t requested_line_number, |
93 intptr_t requested_column_number) | 94 intptr_t requested_column_number) |
94 : script_(Script::null()), | 95 : script_(Script::null()), |
95 url_(url.raw()), | 96 url_(url.raw()), |
96 token_pos_(Token::kNoSourcePos), | 97 token_pos_(TokenDescriptor::kNoSource), |
97 end_token_pos_(Token::kNoSourcePos), | 98 end_token_pos_(TokenDescriptor::kNoSource), |
98 is_resolved_(false), | 99 is_resolved_(false), |
99 next_(NULL), | 100 next_(NULL), |
100 conditions_(NULL), | 101 conditions_(NULL), |
101 requested_line_number_(requested_line_number), | 102 requested_line_number_(requested_line_number), |
102 requested_column_number_(requested_column_number), | 103 requested_column_number_(requested_column_number), |
103 function_(Function::null()), | 104 function_(Function::null()), |
104 line_number_(-1), | 105 line_number_(-1), |
105 column_number_(-1) { | 106 column_number_(-1) { |
106 ASSERT(requested_line_number_ >= 0); | 107 ASSERT(requested_line_number_ >= 0); |
107 } | 108 } |
108 | 109 |
109 | 110 |
110 BreakpointLocation::~BreakpointLocation() { | 111 BreakpointLocation::~BreakpointLocation() { |
111 Breakpoint* bpt = breakpoints(); | 112 Breakpoint* bpt = breakpoints(); |
112 while (bpt != NULL) { | 113 while (bpt != NULL) { |
113 Breakpoint* temp = bpt; | 114 Breakpoint* temp = bpt; |
114 bpt = bpt->next(); | 115 bpt = bpt->next(); |
115 delete temp; | 116 delete temp; |
116 } | 117 } |
117 } | 118 } |
118 | 119 |
119 | 120 |
120 bool BreakpointLocation::AnyEnabled() const { | 121 bool BreakpointLocation::AnyEnabled() const { |
121 return breakpoints() != NULL; | 122 return breakpoints() != NULL; |
122 } | 123 } |
123 | 124 |
124 | 125 |
125 void BreakpointLocation::SetResolved(const Function& func, intptr_t token_pos) { | 126 void BreakpointLocation::SetResolved(const Function& func, |
| 127 TokenDescriptor token_pos) { |
126 ASSERT(!IsLatent()); | 128 ASSERT(!IsLatent()); |
127 ASSERT(func.script() == script_); | 129 ASSERT(func.script() == script_); |
128 ASSERT((func.token_pos() <= token_pos) && | 130 ASSERT((func.token_pos() <= token_pos) && |
129 (token_pos <= func.end_token_pos())); | 131 (token_pos <= func.end_token_pos())); |
130 ASSERT(func.is_debuggable()); | 132 ASSERT(func.is_debuggable()); |
131 function_ = func.raw(); | 133 function_ = func.raw(); |
132 token_pos_ = token_pos; | 134 token_pos_ = token_pos; |
133 end_token_pos_ = token_pos; | 135 end_token_pos_ = token_pos; |
134 is_resolved_ = true; | 136 is_resolved_ = true; |
135 } | 137 } |
136 | 138 |
137 | 139 |
138 // TODO(hausner): Get rid of library parameter. A source breakpoint location | 140 // TODO(hausner): Get rid of library parameter. A source breakpoint location |
139 // does not imply a library, since the same source code can be included | 141 // does not imply a library, since the same source code can be included |
140 // in more than one library, e.g. the text location of mixin functions. | 142 // in more than one library, e.g. the text location of mixin functions. |
141 void BreakpointLocation::GetCodeLocation(Library* lib, | 143 void BreakpointLocation::GetCodeLocation(Library* lib, |
142 Script* script, | 144 Script* script, |
143 intptr_t* pos) const { | 145 TokenDescriptor* pos) const { |
144 if (IsLatent()) { | 146 if (IsLatent()) { |
145 *lib = Library::null(); | 147 *lib = Library::null(); |
146 *script = Script::null(); | 148 *script = Script::null(); |
147 *pos = -1; | 149 *pos = TokenDescriptor::kNoSource; |
148 } else { | 150 } else { |
149 *script = this->script(); | 151 *script = this->script(); |
150 *pos = token_pos_; | 152 *pos = token_pos_; |
151 if (IsResolved()) { | 153 if (IsResolved()) { |
152 const Function& func = Function::Handle(function_); | 154 const Function& func = Function::Handle(function_); |
153 ASSERT(!func.IsNull()); | 155 ASSERT(!func.IsNull()); |
154 const Class& cls = Class::Handle(func.origin()); | 156 const Class& cls = Class::Handle(func.origin()); |
155 *lib = cls.library(); | 157 *lib = cls.library(); |
156 } else { | 158 } else { |
157 *lib = Library::null(); | 159 *lib = Library::null(); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 uword fp, | 234 uword fp, |
233 uword sp, | 235 uword sp, |
234 const Code& code, | 236 const Code& code, |
235 const Array& deopt_frame, | 237 const Array& deopt_frame, |
236 intptr_t deopt_frame_offset) | 238 intptr_t deopt_frame_offset) |
237 : pc_(pc), fp_(fp), sp_(sp), | 239 : pc_(pc), fp_(fp), sp_(sp), |
238 ctx_(Context::ZoneHandle()), | 240 ctx_(Context::ZoneHandle()), |
239 code_(Code::ZoneHandle(code.raw())), | 241 code_(Code::ZoneHandle(code.raw())), |
240 function_(Function::ZoneHandle(code.function())), | 242 function_(Function::ZoneHandle(code.function())), |
241 token_pos_initialized_(false), | 243 token_pos_initialized_(false), |
242 token_pos_(Token::kNoSourcePos), | 244 token_pos_(TokenDescriptor::kNoSource), |
243 try_index_(-1), | 245 try_index_(-1), |
244 line_number_(-1), | 246 line_number_(-1), |
245 column_number_(-1), | 247 column_number_(-1), |
246 context_level_(-1), | 248 context_level_(-1), |
247 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())), | 249 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())), |
248 deopt_frame_offset_(deopt_frame_offset), | 250 deopt_frame_offset_(deopt_frame_offset), |
249 vars_initialized_(false), | 251 vars_initialized_(false), |
250 var_descriptors_(LocalVarDescriptors::ZoneHandle()), | 252 var_descriptors_(LocalVarDescriptors::ZoneHandle()), |
251 desc_indices_(8), | 253 desc_indices_(8), |
252 pc_desc_(PcDescriptors::ZoneHandle()) { | 254 pc_desc_(PcDescriptors::ZoneHandle()) { |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 return OS::SCreate(Thread::Current()->zone(), | 446 return OS::SCreate(Thread::Current()->zone(), |
445 "%s%s%s", func_class.IsTopLevel() ? "" : class_name.ToCString(), | 447 "%s%s%s", func_class.IsTopLevel() ? "" : class_name.ToCString(), |
446 func_class.IsTopLevel() ? "" : ".", | 448 func_class.IsTopLevel() ? "" : ".", |
447 func_name.ToCString()); | 449 func_name.ToCString()); |
448 } | 450 } |
449 | 451 |
450 | 452 |
451 // Returns true if function contains the token position in the given script. | 453 // Returns true if function contains the token position in the given script. |
452 static bool FunctionContains(const Function& func, | 454 static bool FunctionContains(const Function& func, |
453 const Script& script, | 455 const Script& script, |
454 intptr_t token_pos) { | 456 TokenDescriptor token_pos) { |
455 if ((func.token_pos() <= token_pos) && (token_pos <= func.end_token_pos())) { | 457 if ((func.token_pos() <= token_pos) && (token_pos <= func.end_token_pos())) { |
456 // Check script equality second because it allocates | 458 // Check script equality second because it allocates |
457 // handles as a side effect. | 459 // handles as a side effect. |
458 return func.script() == script.raw(); | 460 return func.script() == script.raw(); |
459 } | 461 } |
460 return false; | 462 return false; |
461 } | 463 } |
462 | 464 |
463 | 465 |
464 bool Debugger::HasBreakpoint(const Function& func, Zone* zone) { | 466 bool Debugger::HasBreakpoint(const Function& func, Zone* zone) { |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
556 | 558 |
557 void ActivationFrame::GetPcDescriptors() { | 559 void ActivationFrame::GetPcDescriptors() { |
558 if (pc_desc_.IsNull()) { | 560 if (pc_desc_.IsNull()) { |
559 pc_desc_ = code().pc_descriptors(); | 561 pc_desc_ = code().pc_descriptors(); |
560 ASSERT(!pc_desc_.IsNull()); | 562 ASSERT(!pc_desc_.IsNull()); |
561 } | 563 } |
562 } | 564 } |
563 | 565 |
564 | 566 |
565 // Compute token_pos_ and try_index_ and token_pos_initialized_. | 567 // Compute token_pos_ and try_index_ and token_pos_initialized_. |
566 intptr_t ActivationFrame::TokenPos() { | 568 TokenDescriptor ActivationFrame::TokenPos() { |
567 if (!token_pos_initialized_) { | 569 if (!token_pos_initialized_) { |
568 token_pos_initialized_ = true; | 570 token_pos_initialized_ = true; |
569 token_pos_ = Token::kNoSourcePos; | 571 token_pos_ = TokenDescriptor::kNoSource; |
570 GetPcDescriptors(); | 572 GetPcDescriptors(); |
571 PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind); | 573 PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind); |
572 uword pc_offset = pc_ - code().EntryPoint(); | 574 uword pc_offset = pc_ - code().EntryPoint(); |
573 while (iter.MoveNext()) { | 575 while (iter.MoveNext()) { |
574 if (iter.PcOffset() == pc_offset) { | 576 if (iter.PcOffset() == pc_offset) { |
575 try_index_ = iter.TryIndex(); | 577 try_index_ = iter.TryIndex(); |
576 token_pos_ = iter.TokenPos(); | 578 token_pos_ = iter.TokenPos(); |
577 break; | 579 break; |
578 } | 580 } |
579 } | 581 } |
580 } | 582 } |
581 return token_pos_; | 583 return token_pos_; |
582 } | 584 } |
583 | 585 |
584 | 586 |
585 intptr_t ActivationFrame::TryIndex() { | 587 intptr_t ActivationFrame::TryIndex() { |
586 if (!token_pos_initialized_) { | 588 if (!token_pos_initialized_) { |
587 TokenPos(); // Side effect: computes token_pos_initialized_, try_index_. | 589 TokenPos(); // Side effect: computes token_pos_initialized_, try_index_. |
588 } | 590 } |
589 return try_index_; | 591 return try_index_; |
590 } | 592 } |
591 | 593 |
592 | 594 |
593 intptr_t ActivationFrame::LineNumber() { | 595 intptr_t ActivationFrame::LineNumber() { |
594 // Compute line number lazily since it causes scanning of the script. | 596 // Compute line number lazily since it causes scanning of the script. |
595 if ((line_number_ < 0) && Token::IsReal(TokenPos())) { | 597 if ((line_number_ < 0) && TokenPos().IsReal()) { |
596 const intptr_t token_pos = TokenPos(); | 598 const TokenDescriptor token_pos = TokenPos(); |
597 const Script& script = Script::Handle(SourceScript()); | 599 const Script& script = Script::Handle(SourceScript()); |
598 script.GetTokenLocation(token_pos, &line_number_, NULL); | 600 script.GetTokenLocation(token_pos, &line_number_, NULL); |
599 } | 601 } |
600 return line_number_; | 602 return line_number_; |
601 } | 603 } |
602 | 604 |
603 | 605 |
604 intptr_t ActivationFrame::ColumnNumber() { | 606 intptr_t ActivationFrame::ColumnNumber() { |
605 // Compute column number lazily since it causes scanning of the script. | 607 // Compute column number lazily since it causes scanning of the script. |
606 if ((column_number_ < 0) && Token::IsReal(TokenPos())) { | 608 if ((column_number_ < 0) && TokenPos().IsReal()) { |
607 const intptr_t token_pos = TokenPos(); | 609 const TokenDescriptor token_pos = TokenPos(); |
608 const Script& script = Script::Handle(SourceScript()); | 610 const Script& script = Script::Handle(SourceScript()); |
609 if (script.HasSource()) { | 611 if (script.HasSource()) { |
610 script.GetTokenLocation(token_pos, &line_number_, &column_number_); | 612 script.GetTokenLocation(token_pos, &line_number_, &column_number_); |
611 } else { | 613 } else { |
612 column_number_ = -1; | 614 column_number_ = -1; |
613 } | 615 } |
614 } | 616 } |
615 return column_number_; | 617 return column_number_; |
616 } | 618 } |
617 | 619 |
(...skipping 24 matching lines...) Expand all Loading... |
642 // Calculate the context level at the current token index of the frame. | 644 // Calculate the context level at the current token index of the frame. |
643 intptr_t ActivationFrame::ContextLevel() { | 645 intptr_t ActivationFrame::ContextLevel() { |
644 const Context& ctx = GetSavedCurrentContext(); | 646 const Context& ctx = GetSavedCurrentContext(); |
645 if (context_level_ < 0 && !ctx.IsNull()) { | 647 if (context_level_ < 0 && !ctx.IsNull()) { |
646 ASSERT(!code_.is_optimized()); | 648 ASSERT(!code_.is_optimized()); |
647 context_level_ = 0; | 649 context_level_ = 0; |
648 // TODO(hausner): What to do if there is no descriptor entry | 650 // TODO(hausner): What to do if there is no descriptor entry |
649 // for the code position of the frame? For now say we are at context | 651 // for the code position of the frame? For now say we are at context |
650 // level 0. | 652 // level 0. |
651 TokenPos(); | 653 TokenPos(); |
652 if (token_pos_ == -1) { | 654 if (token_pos_ == TokenDescriptor::kNoSource) { |
653 // No PcDescriptor. | 655 // No PcDescriptor. |
654 return context_level_; | 656 return context_level_; |
655 } | 657 } |
656 ASSERT(!pc_desc_.IsNull()); | 658 ASSERT(!pc_desc_.IsNull()); |
657 intptr_t innermost_begin_pos = 0; | 659 TokenDescriptor innermost_begin_pos = TokenDescriptor::kMinSource; |
658 intptr_t activation_token_pos = TokenPos(); | 660 TokenDescriptor activation_token_pos = TokenPos(); |
659 ASSERT(Token::IsReal(activation_token_pos)); | 661 ASSERT(activation_token_pos.IsReal()); |
660 GetVarDescriptors(); | 662 GetVarDescriptors(); |
661 intptr_t var_desc_len = var_descriptors_.Length(); | 663 intptr_t var_desc_len = var_descriptors_.Length(); |
662 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { | 664 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { |
663 RawLocalVarDescriptors::VarInfo var_info; | 665 RawLocalVarDescriptors::VarInfo var_info; |
664 var_descriptors_.GetInfo(cur_idx, &var_info); | 666 var_descriptors_.GetInfo(cur_idx, &var_info); |
665 const int8_t kind = var_info.kind(); | 667 const int8_t kind = var_info.kind(); |
666 if ((kind == RawLocalVarDescriptors::kContextLevel) && | 668 if ((kind == RawLocalVarDescriptors::kContextLevel) && |
667 (var_info.begin_pos <= activation_token_pos) && | 669 (var_info.begin_pos <= activation_token_pos) && |
668 (activation_token_pos < var_info.end_pos)) { | 670 (activation_token_pos < var_info.end_pos)) { |
669 // This var_descriptors_ entry is a context scope which is in scope | 671 // This var_descriptors_ entry is a context scope which is in scope |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 return NULL; | 763 return NULL; |
762 } | 764 } |
763 | 765 |
764 | 766 |
765 void ActivationFrame::GetDescIndices() { | 767 void ActivationFrame::GetDescIndices() { |
766 if (vars_initialized_) { | 768 if (vars_initialized_) { |
767 return; | 769 return; |
768 } | 770 } |
769 GetVarDescriptors(); | 771 GetVarDescriptors(); |
770 | 772 |
771 intptr_t activation_token_pos = TokenPos(); | 773 TokenDescriptor activation_token_pos = TokenPos(); |
772 if (!Token::IsDebugPause(activation_token_pos)) { | 774 if (!activation_token_pos.IsDebugPause()) { |
773 // We don't have a token position for this frame, so can't determine | 775 // We don't have a token position for this frame, so can't determine |
774 // which variables are visible. | 776 // which variables are visible. |
775 vars_initialized_ = true; | 777 vars_initialized_ = true; |
776 return; | 778 return; |
777 } | 779 } |
778 | 780 |
779 GrowableArray<String*> var_names(8); | 781 GrowableArray<String*> var_names(8); |
780 intptr_t var_desc_len = var_descriptors_.Length(); | 782 intptr_t var_desc_len = var_descriptors_.Length(); |
781 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { | 783 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { |
782 ASSERT(var_names.length() == desc_indices_.length()); | 784 ASSERT(var_names.length() == desc_indices_.length()); |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
922 intptr_t num = 0; | 924 intptr_t num = 0; |
923 while ((frame != NULL)) { | 925 while ((frame != NULL)) { |
924 OS::PrintErr("#%04" Pd " %s\n", num++, frame->ToCString()); | 926 OS::PrintErr("#%04" Pd " %s\n", num++, frame->ToCString()); |
925 frame = iterator.NextFrame(); | 927 frame = iterator.NextFrame(); |
926 } | 928 } |
927 } | 929 } |
928 | 930 |
929 | 931 |
930 void ActivationFrame::VariableAt(intptr_t i, | 932 void ActivationFrame::VariableAt(intptr_t i, |
931 String* name, | 933 String* name, |
932 intptr_t* token_pos, | 934 TokenDescriptor* token_pos, |
933 intptr_t* end_pos, | 935 TokenDescriptor* end_pos, |
934 Object* value) { | 936 Object* value) { |
935 GetDescIndices(); | 937 GetDescIndices(); |
936 ASSERT(i < desc_indices_.length()); | 938 ASSERT(i < desc_indices_.length()); |
937 intptr_t desc_index = desc_indices_[i]; | 939 intptr_t desc_index = desc_indices_[i]; |
938 ASSERT(name != NULL); | 940 ASSERT(name != NULL); |
939 | 941 |
940 *name = var_descriptors_.GetName(desc_index); | 942 *name = var_descriptors_.GetName(desc_index); |
941 | 943 |
942 RawLocalVarDescriptors::VarInfo var_info; | 944 RawLocalVarDescriptors::VarInfo var_info; |
943 var_descriptors_.GetInfo(desc_index, &var_info); | 945 var_descriptors_.GetInfo(desc_index, &var_info); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
991 } | 993 } |
992 | 994 |
993 | 995 |
994 RawArray* ActivationFrame::GetLocalVariables() { | 996 RawArray* ActivationFrame::GetLocalVariables() { |
995 GetDescIndices(); | 997 GetDescIndices(); |
996 intptr_t num_variables = desc_indices_.length(); | 998 intptr_t num_variables = desc_indices_.length(); |
997 String& var_name = String::Handle(); | 999 String& var_name = String::Handle(); |
998 Object& value = Instance::Handle(); | 1000 Object& value = Instance::Handle(); |
999 const Array& list = Array::Handle(Array::New(2 * num_variables)); | 1001 const Array& list = Array::Handle(Array::New(2 * num_variables)); |
1000 for (intptr_t i = 0; i < num_variables; i++) { | 1002 for (intptr_t i = 0; i < num_variables; i++) { |
1001 intptr_t ignore; | 1003 TokenDescriptor ignore; |
1002 VariableAt(i, &var_name, &ignore, &ignore, &value); | 1004 VariableAt(i, &var_name, &ignore, &ignore, &value); |
1003 list.SetAt(2 * i, var_name); | 1005 list.SetAt(2 * i, var_name); |
1004 list.SetAt((2 * i) + 1, value); | 1006 list.SetAt((2 * i) + 1, value); |
1005 } | 1007 } |
1006 return list.raw(); | 1008 return list.raw(); |
1007 } | 1009 } |
1008 | 1010 |
1009 | 1011 |
1010 RawObject* ActivationFrame::GetReceiver() { | 1012 RawObject* ActivationFrame::GetReceiver() { |
1011 GetDescIndices(); | 1013 GetDescIndices(); |
1012 intptr_t num_variables = desc_indices_.length(); | 1014 intptr_t num_variables = desc_indices_.length(); |
1013 String& var_name = String::Handle(); | 1015 String& var_name = String::Handle(); |
1014 Instance& value = Instance::Handle(); | 1016 Instance& value = Instance::Handle(); |
1015 for (intptr_t i = 0; i < num_variables; i++) { | 1017 for (intptr_t i = 0; i < num_variables; i++) { |
1016 intptr_t ignore; | 1018 TokenDescriptor ignore; |
1017 VariableAt(i, &var_name, &ignore, &ignore, &value); | 1019 VariableAt(i, &var_name, &ignore, &ignore, &value); |
1018 if (var_name.Equals(Symbols::This())) { | 1020 if (var_name.Equals(Symbols::This())) { |
1019 return value.raw(); | 1021 return value.raw(); |
1020 } | 1022 } |
1021 } | 1023 } |
1022 return Symbols::OptimizedOut().raw(); | 1024 return Symbols::OptimizedOut().raw(); |
1023 } | 1025 } |
1024 | 1026 |
1025 | 1027 |
1026 bool IsPrivateVariableName(const String& var_name) { | 1028 bool IsPrivateVariableName(const String& var_name) { |
1027 return (var_name.Length() >= 1) && (var_name.CharAt(0) == '_'); | 1029 return (var_name.Length() >= 1) && (var_name.CharAt(0) == '_'); |
1028 } | 1030 } |
1029 | 1031 |
1030 | 1032 |
1031 RawObject* ActivationFrame::Evaluate(const String& expr) { | 1033 RawObject* ActivationFrame::Evaluate(const String& expr) { |
1032 GetDescIndices(); | 1034 GetDescIndices(); |
1033 const GrowableObjectArray& param_names = | 1035 const GrowableObjectArray& param_names = |
1034 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 1036 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
1035 const GrowableObjectArray& param_values = | 1037 const GrowableObjectArray& param_values = |
1036 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 1038 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
1037 String& name = String::Handle(); | 1039 String& name = String::Handle(); |
1038 Object& value = Instance::Handle(); | 1040 Object& value = Instance::Handle(); |
1039 intptr_t num_variables = desc_indices_.length(); | 1041 intptr_t num_variables = desc_indices_.length(); |
1040 for (intptr_t i = 0; i < num_variables; i++) { | 1042 for (intptr_t i = 0; i < num_variables; i++) { |
1041 intptr_t ignore; | 1043 TokenDescriptor ignore; |
1042 VariableAt(i, &name, &ignore, &ignore, &value); | 1044 VariableAt(i, &name, &ignore, &ignore, &value); |
1043 if (!name.Equals(Symbols::This())) { | 1045 if (!name.Equals(Symbols::This())) { |
1044 if (IsPrivateVariableName(name)) { | 1046 if (IsPrivateVariableName(name)) { |
1045 name = String::IdentifierPrettyName(name); | 1047 name = String::IdentifierPrettyName(name); |
1046 } | 1048 } |
1047 param_names.Add(name); | 1049 param_names.Add(name); |
1048 param_values.Add(value); | 1050 param_values.Add(value); |
1049 } | 1051 } |
1050 } | 1052 } |
1051 | 1053 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1102 // in the world where we pass the script as part of the | 1104 // in the world where we pass the script as part of the |
1103 // location. | 1105 // location. |
1104 jsobj->AddProperty("script", script, !full); | 1106 jsobj->AddProperty("script", script, !full); |
1105 } | 1107 } |
1106 { | 1108 { |
1107 JSONArray jsvars(jsobj, "vars"); | 1109 JSONArray jsvars(jsobj, "vars"); |
1108 const int num_vars = NumLocalVariables(); | 1110 const int num_vars = NumLocalVariables(); |
1109 for (intptr_t v = 0; v < num_vars; v++) { | 1111 for (intptr_t v = 0; v < num_vars; v++) { |
1110 String& var_name = String::Handle(); | 1112 String& var_name = String::Handle(); |
1111 Instance& var_value = Instance::Handle(); | 1113 Instance& var_value = Instance::Handle(); |
1112 intptr_t token_pos; | 1114 TokenDescriptor token_pos; |
1113 intptr_t end_token_pos; | 1115 TokenDescriptor end_token_pos; |
1114 VariableAt(v, &var_name, &token_pos, &end_token_pos, &var_value); | 1116 VariableAt(v, &var_name, &token_pos, &end_token_pos, &var_value); |
1115 if (var_name.raw() != Symbols::AsyncOperation().raw()) { | 1117 if (var_name.raw() != Symbols::AsyncOperation().raw()) { |
1116 JSONObject jsvar(&jsvars); | 1118 JSONObject jsvar(&jsvars); |
1117 jsvar.AddProperty("type", "BoundVariable"); | 1119 jsvar.AddProperty("type", "BoundVariable"); |
1118 var_name = String::IdentifierPrettyName(var_name); | 1120 var_name = String::IdentifierPrettyName(var_name); |
1119 jsvar.AddProperty("name", var_name.ToCString()); | 1121 jsvar.AddProperty("name", var_name.ToCString()); |
1120 jsvar.AddProperty("value", var_value, !full); | 1122 jsvar.AddProperty("value", var_value, !full); |
1121 // TODO(turnidge): Do we really want to provide this on every | 1123 // TODO(turnidge): Do we really want to provide this on every |
1122 // stack dump? Should be associated with the function object, I | 1124 // stack dump? Should be associated with the function object, I |
1123 // think, and not the stack frame. | 1125 // think, and not the stack frame. |
1124 jsvar.AddProperty("_tokenPos", token_pos); | 1126 jsvar.AddProperty("_tokenPos", token_pos.value()); |
1125 jsvar.AddProperty("_endTokenPos", end_token_pos); | 1127 jsvar.AddProperty("_endTokenPos", end_token_pos.value()); |
1126 } | 1128 } |
1127 } | 1129 } |
1128 } | 1130 } |
1129 } | 1131 } |
1130 | 1132 |
1131 | 1133 |
1132 | 1134 |
1133 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) { | 1135 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) { |
1134 if (FLAG_show_invisible_frames || frame->function().is_visible()) { | 1136 if (FLAG_show_invisible_frames || frame->function().is_visible()) { |
1135 trace_.Add(frame); | 1137 trace_.Add(frame); |
1136 } | 1138 } |
1137 } | 1139 } |
1138 | 1140 |
1139 | 1141 |
1140 const uint8_t kSafepointKind = RawPcDescriptors::kIcCall | 1142 const uint8_t kSafepointKind = RawPcDescriptors::kIcCall |
1141 | RawPcDescriptors::kUnoptStaticCall | 1143 | RawPcDescriptors::kUnoptStaticCall |
1142 | RawPcDescriptors::kRuntimeCall; | 1144 | RawPcDescriptors::kRuntimeCall; |
1143 | 1145 |
1144 | 1146 |
1145 CodeBreakpoint::CodeBreakpoint(const Code& code, | 1147 CodeBreakpoint::CodeBreakpoint(const Code& code, |
1146 intptr_t token_pos, | 1148 TokenDescriptor token_pos, |
1147 uword pc, | 1149 uword pc, |
1148 RawPcDescriptors::Kind kind) | 1150 RawPcDescriptors::Kind kind) |
1149 : code_(code.raw()), | 1151 : code_(code.raw()), |
1150 token_pos_(token_pos), | 1152 token_pos_(token_pos), |
1151 pc_(pc), | 1153 pc_(pc), |
1152 line_number_(-1), | 1154 line_number_(-1), |
1153 is_enabled_(false), | 1155 is_enabled_(false), |
1154 bpt_location_(NULL), | 1156 bpt_location_(NULL), |
1155 next_(NULL), | 1157 next_(NULL), |
1156 breakpoint_kind_(kind), | 1158 breakpoint_kind_(kind), |
1157 saved_value_(Code::null()) { | 1159 saved_value_(Code::null()) { |
1158 ASSERT(!code.IsNull()); | 1160 ASSERT(!code.IsNull()); |
1159 ASSERT(token_pos_ > 0); | 1161 ASSERT(token_pos_.IsReal()); |
1160 ASSERT(pc_ != 0); | 1162 ASSERT(pc_ != 0); |
1161 ASSERT((breakpoint_kind_ & kSafepointKind) != 0); | 1163 ASSERT((breakpoint_kind_ & kSafepointKind) != 0); |
1162 } | 1164 } |
1163 | 1165 |
1164 | 1166 |
1165 CodeBreakpoint::~CodeBreakpoint() { | 1167 CodeBreakpoint::~CodeBreakpoint() { |
1166 // Make sure we don't leave patched code behind. | 1168 // Make sure we don't leave patched code behind. |
1167 ASSERT(!IsEnabled()); | 1169 ASSERT(!IsEnabled()); |
1168 // Poison the data so we catch use after free errors. | 1170 // Poison the data so we catch use after free errors. |
1169 #ifdef DEBUG | 1171 #ifdef DEBUG |
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1640 event.set_exception(&exc); | 1642 event.set_exception(&exc); |
1641 ASSERT(stack_trace->Length() > 0); | 1643 ASSERT(stack_trace->Length() > 0); |
1642 event.set_top_frame(stack_trace->FrameAt(0)); | 1644 event.set_top_frame(stack_trace->FrameAt(0)); |
1643 ASSERT(stack_trace_ == NULL); | 1645 ASSERT(stack_trace_ == NULL); |
1644 stack_trace_ = stack_trace; | 1646 stack_trace_ = stack_trace; |
1645 Pause(&event); | 1647 Pause(&event); |
1646 stack_trace_ = NULL; | 1648 stack_trace_ = NULL; |
1647 } | 1649 } |
1648 | 1650 |
1649 | 1651 |
1650 static intptr_t LastTokenOnLine(const TokenStream& tokens, intptr_t pos) { | 1652 static TokenDescriptor LastTokenOnLine(const TokenStream& tokens, |
1651 TokenStream::Iterator iter(tokens, pos, TokenStream::Iterator::kAllTokens); | 1653 TokenDescriptor pos) { |
| 1654 TokenStream::Iterator iter(tokens, |
| 1655 pos.value(), |
| 1656 TokenStream::Iterator::kAllTokens); |
1652 ASSERT(iter.IsValid()); | 1657 ASSERT(iter.IsValid()); |
1653 intptr_t last_pos = pos; | 1658 TokenDescriptor last_pos = pos; |
1654 while ((iter.CurrentTokenKind() != Token::kNEWLINE) && | 1659 while ((iter.CurrentTokenKind() != Token::kNEWLINE) && |
1655 (iter.CurrentTokenKind() != Token::kEOS)) { | 1660 (iter.CurrentTokenKind() != Token::kEOS)) { |
1656 last_pos = iter.CurrentPosition(); | 1661 last_pos = TokenDescriptor(iter.CurrentPosition()); |
1657 iter.Advance(); | 1662 iter.Advance(); |
1658 } | 1663 } |
1659 return last_pos; | 1664 return last_pos; |
1660 } | 1665 } |
1661 | 1666 |
1662 | 1667 |
1663 // Returns the best fit token position for a breakpoint. | 1668 // Returns the best fit token position for a breakpoint. |
1664 // | 1669 // |
1665 // Takes a range of tokens [requested_token_pos, last_token_pos] and | 1670 // Takes a range of tokens [requested_token_pos, last_token_pos] and |
1666 // an optional column (requested_column). The range of tokens usually | 1671 // an optional column (requested_column). The range of tokens usually |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1709 // | 1714 // |
1710 // If no best fit token can be found, the search is expanded, | 1715 // If no best fit token can be found, the search is expanded, |
1711 // searching through the rest of the current function by calling this | 1716 // searching through the rest of the current function by calling this |
1712 // function recursively. | 1717 // function recursively. |
1713 // | 1718 // |
1714 // TODO(turnidge): Given that we usually call this function with a | 1719 // TODO(turnidge): Given that we usually call this function with a |
1715 // token range restricted to a single line, this could be a one-pass | 1720 // token range restricted to a single line, this could be a one-pass |
1716 // algorithm, which would be simpler. I believe that it only needs | 1721 // algorithm, which would be simpler. I believe that it only needs |
1717 // two passes to support the recursive try-the-whole-function case. | 1722 // two passes to support the recursive try-the-whole-function case. |
1718 // Rewrite this later, once there are more tests in place. | 1723 // Rewrite this later, once there are more tests in place. |
1719 intptr_t Debugger::ResolveBreakpointPos(const Function& func, | 1724 TokenDescriptor Debugger::ResolveBreakpointPos( |
1720 intptr_t requested_token_pos, | 1725 const Function& func, |
1721 intptr_t last_token_pos, | 1726 TokenDescriptor requested_token_pos, |
1722 intptr_t requested_column) { | 1727 TokenDescriptor last_token_pos, |
| 1728 intptr_t requested_column) { |
1723 ASSERT(func.HasCode()); | 1729 ASSERT(func.HasCode()); |
1724 ASSERT(!func.HasOptimizedCode()); | 1730 ASSERT(!func.HasOptimizedCode()); |
1725 | 1731 |
1726 if (requested_token_pos < func.token_pos()) { | 1732 if (requested_token_pos < func.token_pos()) { |
1727 requested_token_pos = func.token_pos(); | 1733 requested_token_pos = func.token_pos(); |
1728 } | 1734 } |
1729 if (last_token_pos > func.end_token_pos()) { | 1735 if (last_token_pos > func.end_token_pos()) { |
1730 last_token_pos = func.end_token_pos(); | 1736 last_token_pos = func.end_token_pos(); |
1731 } | 1737 } |
1732 | 1738 |
1733 Script& script = Script::Handle(func.script()); | 1739 Script& script = Script::Handle(func.script()); |
1734 Code& code = Code::Handle(func.unoptimized_code()); | 1740 Code& code = Code::Handle(func.unoptimized_code()); |
1735 ASSERT(!code.IsNull()); | 1741 ASSERT(!code.IsNull()); |
1736 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 1742 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
1737 | 1743 |
1738 // First pass: find the safe point which is closest to the beginning | 1744 // First pass: find the safe point which is closest to the beginning |
1739 // of the given token range. | 1745 // of the given token range. |
1740 intptr_t best_fit_pos = INT_MAX; | 1746 TokenDescriptor best_fit_pos = TokenDescriptor::kMaxSource; |
1741 intptr_t best_column = INT_MAX; | 1747 intptr_t best_column = INT_MAX; |
1742 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1748 PcDescriptors::Iterator iter(desc, kSafepointKind); |
1743 while (iter.MoveNext()) { | 1749 while (iter.MoveNext()) { |
1744 const intptr_t pos = iter.TokenPos(); | 1750 const TokenDescriptor pos = iter.TokenPos(); |
1745 if ((!Token::IsReal(pos)) || | 1751 if ((!pos.IsReal()) || |
1746 (pos < requested_token_pos) || | 1752 (pos < requested_token_pos) || |
1747 (pos > last_token_pos)) { | 1753 (pos > last_token_pos)) { |
1748 // Token is not in the target range. | 1754 // Token is not in the target range. |
1749 continue; | 1755 continue; |
1750 } | 1756 } |
1751 | 1757 |
1752 intptr_t token_start_column = -1; | 1758 intptr_t token_start_column = -1; |
1753 if (requested_column >= 0) { | 1759 if (requested_column >= 0) { |
1754 intptr_t ignored = -1; | 1760 intptr_t ignored = -1; |
1755 intptr_t token_len = -1; | 1761 intptr_t token_len = -1; |
(...skipping 16 matching lines...) Expand all Loading... |
1772 // Prefer the lowest (first) token pos. | 1778 // Prefer the lowest (first) token pos. |
1773 if (pos < best_fit_pos) { | 1779 if (pos < best_fit_pos) { |
1774 best_fit_pos = pos; | 1780 best_fit_pos = pos; |
1775 best_column = token_start_column; | 1781 best_column = token_start_column; |
1776 } | 1782 } |
1777 } | 1783 } |
1778 | 1784 |
1779 // Second pass (if we found a safe point in the first pass). Find | 1785 // Second pass (if we found a safe point in the first pass). Find |
1780 // the token on the line which is at the best fit column (if column | 1786 // the token on the line which is at the best fit column (if column |
1781 // was specified) and has the lowest code address. | 1787 // was specified) and has the lowest code address. |
1782 if (best_fit_pos != INT_MAX) { | 1788 if (best_fit_pos != TokenDescriptor::kMaxSource) { |
1783 const Script& script = Script::Handle(func.script()); | 1789 const Script& script = Script::Handle(func.script()); |
1784 const TokenStream& tokens = TokenStream::Handle(script.tokens()); | 1790 const TokenStream& tokens = TokenStream::Handle(script.tokens()); |
1785 const intptr_t begin_pos = best_fit_pos; | 1791 const TokenDescriptor begin_pos = best_fit_pos; |
1786 const intptr_t end_of_line_pos = LastTokenOnLine(tokens, begin_pos); | 1792 const TokenDescriptor end_of_line_pos = LastTokenOnLine(tokens, begin_pos); |
1787 uword lowest_pc_offset = kUwordMax; | 1793 uword lowest_pc_offset = kUwordMax; |
1788 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1794 PcDescriptors::Iterator iter(desc, kSafepointKind); |
1789 while (iter.MoveNext()) { | 1795 while (iter.MoveNext()) { |
1790 const intptr_t pos = iter.TokenPos(); | 1796 const TokenDescriptor pos = iter.TokenPos(); |
1791 if ((!Token::IsReal(pos)) || | 1797 if ((!TokenDescriptor(pos).IsReal()) || |
1792 (pos < begin_pos) || | 1798 (pos < begin_pos) || |
1793 (pos > end_of_line_pos)) { | 1799 (pos > end_of_line_pos)) { |
1794 // Token is not on same line as best fit. | 1800 // Token is not on same line as best fit. |
1795 continue; | 1801 continue; |
1796 } | 1802 } |
1797 | 1803 |
1798 if (requested_column >= 0) { | 1804 if (requested_column >= 0) { |
1799 intptr_t ignored = -1; | 1805 intptr_t ignored = -1; |
1800 intptr_t token_start_column = -1; | 1806 intptr_t token_start_column = -1; |
1801 // We look for other tokens at the best column in case there | 1807 // We look for other tokens at the best column in case there |
(...skipping 14 matching lines...) Expand all Loading... |
1816 } | 1822 } |
1817 | 1823 |
1818 // We didn't find a safe point in the given token range. Try and | 1824 // We didn't find a safe point in the given token range. Try and |
1819 // find a safe point in the remaining source code of the function. | 1825 // find a safe point in the remaining source code of the function. |
1820 // Since we have moved to the next line of the function, we no | 1826 // Since we have moved to the next line of the function, we no |
1821 // longer are requesting a specific column number. | 1827 // longer are requesting a specific column number. |
1822 if (last_token_pos < func.end_token_pos()) { | 1828 if (last_token_pos < func.end_token_pos()) { |
1823 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos(), | 1829 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos(), |
1824 -1 /* no column */); | 1830 -1 /* no column */); |
1825 } | 1831 } |
1826 return Token::kNoSourcePos; | 1832 return TokenDescriptor::kNoSource; |
1827 } | 1833 } |
1828 | 1834 |
1829 | 1835 |
1830 void Debugger::MakeCodeBreakpointAt(const Function& func, | 1836 void Debugger::MakeCodeBreakpointAt(const Function& func, |
1831 BreakpointLocation* loc) { | 1837 BreakpointLocation* loc) { |
1832 ASSERT(Token::IsReal(loc->token_pos_)); | 1838 ASSERT(TokenDescriptor(loc->token_pos_).IsReal()); |
1833 ASSERT((loc != NULL) && loc->IsResolved()); | 1839 ASSERT((loc != NULL) && loc->IsResolved()); |
1834 ASSERT(!func.HasOptimizedCode()); | 1840 ASSERT(!func.HasOptimizedCode()); |
1835 Code& code = Code::Handle(func.unoptimized_code()); | 1841 Code& code = Code::Handle(func.unoptimized_code()); |
1836 ASSERT(!code.IsNull()); | 1842 ASSERT(!code.IsNull()); |
1837 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 1843 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
1838 uword lowest_pc_offset = kUwordMax; | 1844 uword lowest_pc_offset = kUwordMax; |
1839 RawPcDescriptors::Kind lowest_kind = RawPcDescriptors::kAnyKind; | 1845 RawPcDescriptors::Kind lowest_kind = RawPcDescriptors::kAnyKind; |
1840 // Find the safe point with the lowest compiled code address | 1846 // Find the safe point with the lowest compiled code address |
1841 // that maps to the token position of the source breakpoint. | 1847 // that maps to the token position of the source breakpoint. |
1842 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1848 PcDescriptors::Iterator iter(desc, kSafepointKind); |
(...skipping 17 matching lines...) Expand all Loading... |
1860 RegisterCodeBreakpoint(code_bpt); | 1866 RegisterCodeBreakpoint(code_bpt); |
1861 } | 1867 } |
1862 code_bpt->set_bpt_location(loc); | 1868 code_bpt->set_bpt_location(loc); |
1863 if (loc->AnyEnabled()) { | 1869 if (loc->AnyEnabled()) { |
1864 code_bpt->Enable(); | 1870 code_bpt->Enable(); |
1865 } | 1871 } |
1866 } | 1872 } |
1867 | 1873 |
1868 | 1874 |
1869 void Debugger::FindCompiledFunctions(const Script& script, | 1875 void Debugger::FindCompiledFunctions(const Script& script, |
1870 intptr_t start_pos, | 1876 TokenDescriptor start_pos, |
1871 intptr_t end_pos, | 1877 TokenDescriptor end_pos, |
1872 GrowableObjectArray* function_list) { | 1878 GrowableObjectArray* function_list) { |
1873 Zone* zone = Thread::Current()->zone(); | 1879 Zone* zone = Thread::Current()->zone(); |
1874 Class& cls = Class::Handle(zone); | 1880 Class& cls = Class::Handle(zone); |
1875 Array& functions = Array::Handle(zone); | 1881 Array& functions = Array::Handle(zone); |
1876 GrowableObjectArray& closures = GrowableObjectArray::Handle(zone); | 1882 GrowableObjectArray& closures = GrowableObjectArray::Handle(zone); |
1877 Function& function = Function::Handle(zone); | 1883 Function& function = Function::Handle(zone); |
1878 | 1884 |
1879 closures = isolate_->object_store()->closure_functions(); | 1885 closures = isolate_->object_store()->closure_functions(); |
1880 const intptr_t num_closures = closures.Length(); | 1886 const intptr_t num_closures = closures.Length(); |
1881 for (intptr_t pos = 0; pos < num_closures; pos++) { | 1887 for (intptr_t pos = 0; pos < num_closures; pos++) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1945 } else { | 1951 } else { |
1946 if ((func->token_pos() > best_fit->token_pos()) && | 1952 if ((func->token_pos() > best_fit->token_pos()) && |
1947 ((func->end_token_pos() <= best_fit->end_token_pos()))) { | 1953 ((func->end_token_pos() <= best_fit->end_token_pos()))) { |
1948 *best_fit = func->raw(); | 1954 *best_fit = func->raw(); |
1949 } | 1955 } |
1950 } | 1956 } |
1951 } | 1957 } |
1952 | 1958 |
1953 | 1959 |
1954 RawFunction* Debugger::FindBestFit(const Script& script, | 1960 RawFunction* Debugger::FindBestFit(const Script& script, |
1955 intptr_t token_pos) { | 1961 TokenDescriptor token_pos) { |
1956 Zone* zone = Thread::Current()->zone(); | 1962 Zone* zone = Thread::Current()->zone(); |
1957 Class& cls = Class::Handle(zone); | 1963 Class& cls = Class::Handle(zone); |
1958 Array& functions = Array::Handle(zone); | 1964 Array& functions = Array::Handle(zone); |
1959 GrowableObjectArray& closures = GrowableObjectArray::Handle(zone); | 1965 GrowableObjectArray& closures = GrowableObjectArray::Handle(zone); |
1960 Function& function = Function::Handle(zone); | 1966 Function& function = Function::Handle(zone); |
1961 Function& best_fit = Function::Handle(zone); | 1967 Function& best_fit = Function::Handle(zone); |
1962 Error& error = Error::Handle(zone); | 1968 Error& error = Error::Handle(zone); |
1963 | 1969 |
1964 closures = isolate_->object_store()->closure_functions(); | 1970 closures = isolate_->object_store()->closure_functions(); |
1965 const intptr_t num_closures = closures.Length(); | 1971 const intptr_t num_closures = closures.Length(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2004 } | 2010 } |
2005 } | 2011 } |
2006 } | 2012 } |
2007 } | 2013 } |
2008 } | 2014 } |
2009 return best_fit.raw(); | 2015 return best_fit.raw(); |
2010 } | 2016 } |
2011 | 2017 |
2012 | 2018 |
2013 BreakpointLocation* Debugger::SetBreakpoint(const Script& script, | 2019 BreakpointLocation* Debugger::SetBreakpoint(const Script& script, |
2014 intptr_t token_pos, | 2020 TokenDescriptor token_pos, |
2015 intptr_t last_token_pos, | 2021 TokenDescriptor last_token_pos, |
2016 intptr_t requested_line, | 2022 intptr_t requested_line, |
2017 intptr_t requested_column) { | 2023 intptr_t requested_column) { |
2018 Function& func = Function::Handle(); | 2024 Function& func = Function::Handle(); |
2019 func = FindBestFit(script, token_pos); | 2025 func = FindBestFit(script, token_pos); |
2020 if (func.IsNull()) { | 2026 if (func.IsNull()) { |
2021 return NULL; | 2027 return NULL; |
2022 } | 2028 } |
2023 // There may be more than one function object for a given function | 2029 // There may be more than one function object for a given function |
2024 // in source code. There may be implicit closure functions, and | 2030 // in source code. There may be implicit closure functions, and |
2025 // there may be copies of mixin functions. Collect all compiled | 2031 // there may be copies of mixin functions. Collect all compiled |
2026 // functions whose source code range matches exactly the best fit | 2032 // functions whose source code range matches exactly the best fit |
2027 // function we found. | 2033 // function we found. |
2028 GrowableObjectArray& functions = | 2034 GrowableObjectArray& functions = |
2029 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 2035 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
2030 FindCompiledFunctions(script, | 2036 FindCompiledFunctions(script, |
2031 func.token_pos(), | 2037 func.token_pos(), |
2032 func.end_token_pos(), | 2038 func.end_token_pos(), |
2033 &functions); | 2039 &functions); |
2034 | 2040 |
2035 if (functions.Length() > 0) { | 2041 if (functions.Length() > 0) { |
2036 // One or more function object containing this breakpoint location | 2042 // One or more function object containing this breakpoint location |
2037 // have already been compiled. We can resolve the breakpoint now. | 2043 // have already been compiled. We can resolve the breakpoint now. |
2038 DeoptimizeWorld(); | 2044 DeoptimizeWorld(); |
2039 func ^= functions.At(0); | 2045 func ^= functions.At(0); |
2040 intptr_t breakpoint_pos = | 2046 TokenDescriptor breakpoint_pos = |
2041 ResolveBreakpointPos(func, token_pos, last_token_pos, requested_column); | 2047 ResolveBreakpointPos(func, token_pos, last_token_pos, requested_column); |
2042 if (breakpoint_pos >= 0) { | 2048 if (breakpoint_pos >= TokenDescriptor::kMinSource) { |
2043 BreakpointLocation* bpt = | 2049 BreakpointLocation* bpt = |
2044 GetBreakpointLocation(script, breakpoint_pos, requested_column); | 2050 GetBreakpointLocation(script, breakpoint_pos, requested_column); |
2045 if (bpt != NULL) { | 2051 if (bpt != NULL) { |
2046 // A source breakpoint for this location already exists. | 2052 // A source breakpoint for this location already exists. |
2047 return bpt; | 2053 return bpt; |
2048 } | 2054 } |
2049 bpt = new BreakpointLocation(script, token_pos, last_token_pos, | 2055 bpt = new BreakpointLocation(script, token_pos, last_token_pos, |
2050 requested_line, requested_column); | 2056 requested_line, requested_column); |
2051 bpt->SetResolved(func, breakpoint_pos); | 2057 bpt->SetResolved(func, breakpoint_pos); |
2052 RegisterBreakpointLocation(bpt); | 2058 RegisterBreakpointLocation(bpt); |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2235 } | 2241 } |
2236 return latent_bpt; | 2242 return latent_bpt; |
2237 } | 2243 } |
2238 if (scripts.Length() > 1) { | 2244 if (scripts.Length() > 1) { |
2239 if (FLAG_verbose_debug) { | 2245 if (FLAG_verbose_debug) { |
2240 OS::Print("Multiple scripts match url '%s'\n", script_url.ToCString()); | 2246 OS::Print("Multiple scripts match url '%s'\n", script_url.ToCString()); |
2241 } | 2247 } |
2242 return NULL; | 2248 return NULL; |
2243 } | 2249 } |
2244 script ^= scripts.At(0); | 2250 script ^= scripts.At(0); |
2245 intptr_t first_token_idx, last_token_idx; | 2251 TokenDescriptor first_token_idx, last_token_idx; |
2246 script.TokenRangeAtLine(line_number, &first_token_idx, &last_token_idx); | 2252 script.TokenRangeAtLine(line_number, &first_token_idx, &last_token_idx); |
2247 if (!Token::IsReal(first_token_idx)) { | 2253 if (!TokenDescriptor(first_token_idx).IsReal()) { |
2248 // Script does not contain the given line number. | 2254 // Script does not contain the given line number. |
2249 if (FLAG_verbose_debug) { | 2255 if (FLAG_verbose_debug) { |
2250 OS::Print("Script '%s' does not contain line number %" Pd "\n", | 2256 OS::Print("Script '%s' does not contain line number %" Pd "\n", |
2251 script_url.ToCString(), line_number); | 2257 script_url.ToCString(), line_number); |
2252 } | 2258 } |
2253 return NULL; | 2259 return NULL; |
2254 } else if (!Token::IsReal(last_token_idx)) { | 2260 } else if (!TokenDescriptor(last_token_idx).IsReal()) { |
2255 // Line does not contain any tokens. | 2261 // Line does not contain any tokens. |
2256 if (FLAG_verbose_debug) { | 2262 if (FLAG_verbose_debug) { |
2257 OS::Print("No executable code at line %" Pd " in '%s'\n", | 2263 OS::Print("No executable code at line %" Pd " in '%s'\n", |
2258 line_number, script_url.ToCString()); | 2264 line_number, script_url.ToCString()); |
2259 } | 2265 } |
2260 return NULL; | 2266 return NULL; |
2261 } | 2267 } |
2262 | 2268 |
2263 BreakpointLocation* bpt = NULL; | 2269 BreakpointLocation* bpt = NULL; |
2264 ASSERT(first_token_idx <= last_token_idx); | 2270 ASSERT(first_token_idx <= last_token_idx); |
2265 while ((bpt == NULL) && (first_token_idx <= last_token_idx)) { | 2271 while ((bpt == NULL) && (first_token_idx <= last_token_idx)) { |
2266 bpt = SetBreakpoint(script, first_token_idx, last_token_idx, | 2272 bpt = SetBreakpoint(script, first_token_idx, last_token_idx, |
2267 line_number, column_number); | 2273 line_number, column_number); |
2268 first_token_idx++; | 2274 first_token_idx = TokenDescriptor(first_token_idx.value() + 1); |
2269 } | 2275 } |
2270 if ((bpt == NULL) && FLAG_verbose_debug) { | 2276 if ((bpt == NULL) && FLAG_verbose_debug) { |
2271 OS::Print("No executable code at line %" Pd " in '%s'\n", | 2277 OS::Print("No executable code at line %" Pd " in '%s'\n", |
2272 line_number, script_url.ToCString()); | 2278 line_number, script_url.ToCString()); |
2273 } | 2279 } |
2274 return bpt; | 2280 return bpt; |
2275 } | 2281 } |
2276 | 2282 |
2277 | 2283 |
2278 intptr_t Debugger::CacheObject(const Object& obj) { | 2284 intptr_t Debugger::CacheObject(const Object& obj) { |
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2604 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointReached); | 2610 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointReached); |
2605 event.set_top_frame(top_frame); | 2611 event.set_top_frame(top_frame); |
2606 event.set_breakpoint(bpt); | 2612 event.set_breakpoint(bpt); |
2607 Object& closure_or_null = Object::Handle(top_frame->GetAsyncOperation()); | 2613 Object& closure_or_null = Object::Handle(top_frame->GetAsyncOperation()); |
2608 if (!closure_or_null.IsNull()) { | 2614 if (!closure_or_null.IsNull()) { |
2609 ASSERT(closure_or_null.IsInstance()); | 2615 ASSERT(closure_or_null.IsInstance()); |
2610 ASSERT(Instance::Cast(closure_or_null).IsClosure()); | 2616 ASSERT(Instance::Cast(closure_or_null).IsClosure()); |
2611 event.set_async_continuation(&closure_or_null); | 2617 event.set_async_continuation(&closure_or_null); |
2612 const Script& script = Script::Handle(top_frame->SourceScript()); | 2618 const Script& script = Script::Handle(top_frame->SourceScript()); |
2613 const TokenStream& tokens = TokenStream::Handle(script.tokens()); | 2619 const TokenStream& tokens = TokenStream::Handle(script.tokens()); |
2614 TokenStream::Iterator iter(tokens, top_frame->TokenPos()); | 2620 TokenStream::Iterator iter(tokens, top_frame->TokenPos().value()); |
2615 if ((iter.CurrentTokenKind() == Token::kIDENT) && | 2621 if ((iter.CurrentTokenKind() == Token::kIDENT) && |
2616 ((iter.CurrentLiteral() == Symbols::Await().raw()) || | 2622 ((iter.CurrentLiteral() == Symbols::Await().raw()) || |
2617 (iter.CurrentLiteral() == Symbols::YieldKw().raw()))) { | 2623 (iter.CurrentLiteral() == Symbols::YieldKw().raw()))) { |
2618 event.set_at_async_jump(true); | 2624 event.set_at_async_jump(true); |
2619 } | 2625 } |
2620 } | 2626 } |
2621 Pause(&event); | 2627 Pause(&event); |
2622 } | 2628 } |
2623 | 2629 |
2624 | 2630 |
(...skipping 27 matching lines...) Expand all Loading... |
2652 // We returned from the "interesting frame", there can be no more | 2658 // We returned from the "interesting frame", there can be no more |
2653 // stepping breaks for it. Pause at the next appropriate location | 2659 // stepping breaks for it. Pause at the next appropriate location |
2654 // and let the user set the "interesting" frame again. | 2660 // and let the user set the "interesting" frame again. |
2655 stepping_fp_ = 0; | 2661 stepping_fp_ = 0; |
2656 } | 2662 } |
2657 } | 2663 } |
2658 | 2664 |
2659 if (!frame->IsDebuggable()) { | 2665 if (!frame->IsDebuggable()) { |
2660 return Error::null(); | 2666 return Error::null(); |
2661 } | 2667 } |
2662 if (!Token::IsDebugPause(frame->TokenPos())) { | 2668 if (!TokenDescriptor(frame->TokenPos()).IsDebugPause()) { |
2663 return Error::null(); | 2669 return Error::null(); |
2664 } | 2670 } |
2665 | 2671 |
2666 // If there is an active breakpoint at this pc, then we should have | 2672 // If there is an active breakpoint at this pc, then we should have |
2667 // already bailed out of this function in the skip_next_step_ test | 2673 // already bailed out of this function in the skip_next_step_ test |
2668 // above. | 2674 // above. |
2669 ASSERT(!HasActiveBreakpoint(frame->pc())); | 2675 ASSERT(!HasActiveBreakpoint(frame->pc())); |
2670 | 2676 |
2671 if (FLAG_verbose_debug) { | 2677 if (FLAG_verbose_debug) { |
2672 OS::Print(">>> single step break at %s:%" Pd " (func %s token %" Pd ")\n", | 2678 OS::Print(">>> single step break at %s:%" Pd " (func %s token %" Pd ")\n", |
2673 String::Handle(frame->SourceUrl()).ToCString(), | 2679 String::Handle(frame->SourceUrl()).ToCString(), |
2674 frame->LineNumber(), | 2680 frame->LineNumber(), |
2675 String::Handle(frame->QualifiedFunctionName()).ToCString(), | 2681 String::Handle(frame->QualifiedFunctionName()).ToCString(), |
2676 frame->TokenPos()); | 2682 frame->TokenPos().value()); |
2677 } | 2683 } |
2678 | 2684 |
2679 ASSERT(stack_trace_ == NULL); | 2685 ASSERT(stack_trace_ == NULL); |
2680 stack_trace_ = CollectStackTrace(); | 2686 stack_trace_ = CollectStackTrace(); |
2681 SignalPausedEvent(frame, NULL); | 2687 SignalPausedEvent(frame, NULL); |
2682 HandleSteppingRequest(stack_trace_); | 2688 HandleSteppingRequest(stack_trace_); |
2683 stack_trace_ = NULL; | 2689 stack_trace_ = NULL; |
2684 | 2690 |
2685 // If any error occurred while in the debug message loop, return it here. | 2691 // If any error occurred while in the debug message loop, return it here. |
2686 const Error& error = | 2692 const Error& error = |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2751 if (bpt_hit == NULL) { | 2757 if (bpt_hit == NULL) { |
2752 return Error::null(); | 2758 return Error::null(); |
2753 } | 2759 } |
2754 | 2760 |
2755 if (FLAG_verbose_debug) { | 2761 if (FLAG_verbose_debug) { |
2756 OS::Print(">>> hit %s breakpoint at %s:%" Pd " " | 2762 OS::Print(">>> hit %s breakpoint at %s:%" Pd " " |
2757 "(token %" Pd ") (address %#" Px ")\n", | 2763 "(token %" Pd ") (address %#" Px ")\n", |
2758 cbpt->IsInternal() ? "internal" : "user", | 2764 cbpt->IsInternal() ? "internal" : "user", |
2759 String::Handle(cbpt->SourceUrl()).ToCString(), | 2765 String::Handle(cbpt->SourceUrl()).ToCString(), |
2760 cbpt->LineNumber(), | 2766 cbpt->LineNumber(), |
2761 cbpt->token_pos(), | 2767 cbpt->token_pos().value(), |
2762 top_frame->pc()); | 2768 top_frame->pc()); |
2763 } | 2769 } |
2764 | 2770 |
2765 ASSERT(stack_trace_ == NULL); | 2771 ASSERT(stack_trace_ == NULL); |
2766 stack_trace_ = stack_trace; | 2772 stack_trace_ = stack_trace; |
2767 SignalPausedEvent(top_frame, bpt_hit); | 2773 SignalPausedEvent(top_frame, bpt_hit); |
2768 // When we single step from a user breakpoint, our next stepping | 2774 // When we single step from a user breakpoint, our next stepping |
2769 // point will be at the exact same pc. Skip it. | 2775 // point will be at the exact same pc. Skip it. |
2770 HandleSteppingRequest(stack_trace_, true /* skip next step */); | 2776 HandleSteppingRequest(stack_trace_, true /* skip next step */); |
2771 stack_trace_ = NULL; | 2777 stack_trace_ = NULL; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2830 !ServiceIsolate::IsServiceIsolateDescendant(isolate_)) { | 2836 !ServiceIsolate::IsServiceIsolateDescendant(isolate_)) { |
2831 SignalIsolateEvent(DebuggerEvent::kIsolateCreated); | 2837 SignalIsolateEvent(DebuggerEvent::kIsolateCreated); |
2832 creation_message_sent_ = true; | 2838 creation_message_sent_ = true; |
2833 } | 2839 } |
2834 } | 2840 } |
2835 | 2841 |
2836 | 2842 |
2837 // Return innermost closure contained in 'function' that contains | 2843 // Return innermost closure contained in 'function' that contains |
2838 // the given token position. | 2844 // the given token position. |
2839 RawFunction* Debugger::FindInnermostClosure(const Function& function, | 2845 RawFunction* Debugger::FindInnermostClosure(const Function& function, |
2840 intptr_t token_pos) { | 2846 TokenDescriptor token_pos) { |
2841 Zone* zone = Thread::Current()->zone(); | 2847 Zone* zone = Thread::Current()->zone(); |
2842 const Script& outer_origin = Script::Handle(zone, function.script()); | 2848 const Script& outer_origin = Script::Handle(zone, function.script()); |
2843 const GrowableObjectArray& closures = | 2849 const GrowableObjectArray& closures = |
2844 GrowableObjectArray::Handle(zone, | 2850 GrowableObjectArray::Handle(zone, |
2845 Isolate::Current()->object_store()->closure_functions()); | 2851 Isolate::Current()->object_store()->closure_functions()); |
2846 const intptr_t num_closures = closures.Length(); | 2852 const intptr_t num_closures = closures.Length(); |
2847 Function& closure = Function::Handle(zone); | 2853 Function& closure = Function::Handle(zone); |
2848 Function& best_fit = Function::Handle(zone); | 2854 Function& best_fit = Function::Handle(zone); |
2849 for (intptr_t i = 0; i < num_closures; i++) { | 2855 for (intptr_t i = 0; i < num_closures; i++) { |
2850 closure ^= closures.At(i); | 2856 closure ^= closures.At(i); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2895 | 2901 |
2896 // TODO(hausner): What should we do if function is optimized? | 2902 // TODO(hausner): What should we do if function is optimized? |
2897 // Can we deoptimize the function? | 2903 // Can we deoptimize the function? |
2898 ASSERT(!func.HasOptimizedCode()); | 2904 ASSERT(!func.HasOptimizedCode()); |
2899 | 2905 |
2900 // There is no local function within func that contains the | 2906 // There is no local function within func that contains the |
2901 // breakpoint token position. Resolve the breakpoint if necessary | 2907 // breakpoint token position. Resolve the breakpoint if necessary |
2902 // and set the code breakpoints. | 2908 // and set the code breakpoints. |
2903 if (!loc->IsResolved()) { | 2909 if (!loc->IsResolved()) { |
2904 // Resolve source breakpoint in the newly compiled function. | 2910 // Resolve source breakpoint in the newly compiled function. |
2905 intptr_t bp_pos = | 2911 TokenDescriptor bp_pos = |
2906 ResolveBreakpointPos(func, loc->token_pos(), loc->end_token_pos(), | 2912 ResolveBreakpointPos(func, loc->token_pos(), loc->end_token_pos(), |
2907 loc->requested_column_number()); | 2913 loc->requested_column_number()); |
2908 if (!Token::IsDebugPause(bp_pos)) { | 2914 if (!TokenDescriptor(bp_pos).IsDebugPause()) { |
2909 if (FLAG_verbose_debug) { | 2915 if (FLAG_verbose_debug) { |
2910 OS::Print("Failed resolving breakpoint for function '%s'\n", | 2916 OS::Print("Failed resolving breakpoint for function '%s'\n", |
2911 String::Handle(func.name()).ToCString()); | 2917 String::Handle(func.name()).ToCString()); |
2912 } | 2918 } |
2913 continue; | 2919 continue; |
2914 } | 2920 } |
2915 intptr_t requested_pos = loc->token_pos(); | 2921 TokenDescriptor requested_pos = loc->token_pos(); |
2916 intptr_t requested_end_pos = loc->end_token_pos(); | 2922 TokenDescriptor requested_end_pos = loc->end_token_pos(); |
2917 loc->SetResolved(func, bp_pos); | 2923 loc->SetResolved(func, bp_pos); |
2918 Breakpoint* bpt = loc->breakpoints(); | 2924 Breakpoint* bpt = loc->breakpoints(); |
2919 while (bpt != NULL) { | 2925 while (bpt != NULL) { |
2920 if (FLAG_verbose_debug) { | 2926 if (FLAG_verbose_debug) { |
2921 OS::Print("Resolved BP %" Pd " to pos %" Pd ", " | 2927 OS::Print("Resolved BP %" Pd " to pos %" Pd ", " |
2922 "line %" Pd " col %" Pd ", " | 2928 "line %" Pd " col %" Pd ", " |
2923 "function '%s' (requested range %" Pd "-%" Pd ", " | 2929 "function '%s' (requested range %" Pd "-%" Pd ", " |
2924 "requested col %" Pd ")\n", | 2930 "requested col %" Pd ")\n", |
2925 bpt->id(), | 2931 bpt->id(), |
2926 loc->token_pos(), | 2932 loc->token_pos().value(), |
2927 loc->LineNumber(), | 2933 loc->LineNumber(), |
2928 loc->ColumnNumber(), | 2934 loc->ColumnNumber(), |
2929 func.ToFullyQualifiedCString(), | 2935 func.ToFullyQualifiedCString(), |
2930 requested_pos, | 2936 requested_pos.value(), |
2931 requested_end_pos, | 2937 requested_end_pos.value(), |
2932 loc->requested_column_number()); | 2938 loc->requested_column_number()); |
2933 } | 2939 } |
2934 SignalBpResolved(bpt); | 2940 SignalBpResolved(bpt); |
2935 SendServiceBreakpointEvent(ServiceEvent::kBreakpointResolved, bpt); | 2941 SendServiceBreakpointEvent(ServiceEvent::kBreakpointResolved, bpt); |
2936 bpt = bpt->next(); | 2942 bpt = bpt->next(); |
2937 } | 2943 } |
2938 } | 2944 } |
2939 ASSERT(loc->IsResolved()); | 2945 ASSERT(loc->IsResolved()); |
2940 if (FLAG_verbose_debug) { | 2946 if (FLAG_verbose_debug) { |
2941 Breakpoint* bpt = loc->breakpoints(); | 2947 Breakpoint* bpt = loc->breakpoints(); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2984 if (prev_loc == NULL) { | 2990 if (prev_loc == NULL) { |
2985 latent_locations_ = loc; | 2991 latent_locations_ = loc; |
2986 } else { | 2992 } else { |
2987 prev_loc->set_next(loc); | 2993 prev_loc->set_next(loc); |
2988 } | 2994 } |
2989 // Now find the token range at the requested line and make a | 2995 // Now find the token range at the requested line and make a |
2990 // new unresolved source breakpoint. | 2996 // new unresolved source breakpoint. |
2991 intptr_t line_number = matched_loc->requested_line_number(); | 2997 intptr_t line_number = matched_loc->requested_line_number(); |
2992 intptr_t column_number = matched_loc->requested_column_number(); | 2998 intptr_t column_number = matched_loc->requested_column_number(); |
2993 ASSERT(line_number >= 0); | 2999 ASSERT(line_number >= 0); |
2994 intptr_t first_token_pos, last_token_pos; | 3000 TokenDescriptor first_token_pos, last_token_pos; |
2995 script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos); | 3001 script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos); |
2996 if (!Token::IsDebugPause(first_token_pos) || | 3002 if (!first_token_pos.IsDebugPause() || !last_token_pos.IsDebugPause()) { |
2997 !Token::IsDebugPause(last_token_pos)) { | |
2998 // Script does not contain the given line number or there are no | 3003 // Script does not contain the given line number or there are no |
2999 // tokens on the line. Drop the breakpoint silently. | 3004 // tokens on the line. Drop the breakpoint silently. |
3000 Breakpoint* bpt = matched_loc->breakpoints(); | 3005 Breakpoint* bpt = matched_loc->breakpoints(); |
3001 while (bpt != NULL) { | 3006 while (bpt != NULL) { |
3002 if (FLAG_verbose_debug) { | 3007 if (FLAG_verbose_debug) { |
3003 OS::Print("No code found at line %" Pd ": " | 3008 OS::Print("No code found at line %" Pd ": " |
3004 "dropping latent breakpoint %" Pd " in '%s'\n", | 3009 "dropping latent breakpoint %" Pd " in '%s'\n", |
3005 line_number, | 3010 line_number, |
3006 bpt->id(), | 3011 bpt->id(), |
3007 url.ToCString()); | 3012 url.ToCString()); |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3195 delete temp_bpt; | 3200 delete temp_bpt; |
3196 } else { | 3201 } else { |
3197 prev_bpt = curr_bpt; | 3202 prev_bpt = curr_bpt; |
3198 curr_bpt = curr_bpt->next(); | 3203 curr_bpt = curr_bpt->next(); |
3199 } | 3204 } |
3200 } | 3205 } |
3201 } | 3206 } |
3202 | 3207 |
3203 | 3208 |
3204 BreakpointLocation* Debugger::GetBreakpointLocation(const Script& script, | 3209 BreakpointLocation* Debugger::GetBreakpointLocation(const Script& script, |
3205 intptr_t token_pos, | 3210 TokenDescriptor token_pos, |
3206 intptr_t requested_column) { | 3211 intptr_t requested_column) { |
3207 BreakpointLocation* bpt = breakpoint_locations_; | 3212 BreakpointLocation* bpt = breakpoint_locations_; |
3208 while (bpt != NULL) { | 3213 while (bpt != NULL) { |
3209 if ((bpt->script_ == script.raw()) && | 3214 if ((bpt->script_ == script.raw()) && |
3210 (bpt->token_pos_ == token_pos) && | 3215 (bpt->token_pos_ == token_pos) && |
3211 (bpt->requested_column_number_ == requested_column)) { | 3216 (bpt->requested_column_number_ == requested_column)) { |
3212 return bpt; | 3217 return bpt; |
3213 } | 3218 } |
3214 bpt = bpt->next(); | 3219 bpt = bpt->next(); |
3215 } | 3220 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3262 } | 3267 } |
3263 | 3268 |
3264 | 3269 |
3265 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 3270 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
3266 ASSERT(bpt->next() == NULL); | 3271 ASSERT(bpt->next() == NULL); |
3267 bpt->set_next(code_breakpoints_); | 3272 bpt->set_next(code_breakpoints_); |
3268 code_breakpoints_ = bpt; | 3273 code_breakpoints_ = bpt; |
3269 } | 3274 } |
3270 | 3275 |
3271 } // namespace dart | 3276 } // namespace dart |
OLD | NEW |