| 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_position.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 22 matching lines...) Expand all Loading... |
| 62 | 63 |
| 63 private: | 64 private: |
| 64 GrowableObjectArray* objs_; | 65 GrowableObjectArray* objs_; |
| 65 | 66 |
| 66 DISALLOW_COPY_AND_ASSIGN(RemoteObjectCache); | 67 DISALLOW_COPY_AND_ASSIGN(RemoteObjectCache); |
| 67 }; | 68 }; |
| 68 | 69 |
| 69 | 70 |
| 70 // Create an unresolved breakpoint in given token range and script. | 71 // Create an unresolved breakpoint in given token range and script. |
| 71 BreakpointLocation::BreakpointLocation(const Script& script, | 72 BreakpointLocation::BreakpointLocation(const Script& script, |
| 72 intptr_t token_pos, | 73 TokenPosition token_pos, |
| 73 intptr_t end_token_pos, | 74 TokenPosition end_token_pos, |
| 74 intptr_t requested_line_number, | 75 intptr_t requested_line_number, |
| 75 intptr_t requested_column_number) | 76 intptr_t requested_column_number) |
| 76 : script_(script.raw()), | 77 : script_(script.raw()), |
| 77 url_(script.url()), | 78 url_(script.url()), |
| 78 token_pos_(token_pos), | 79 token_pos_(token_pos), |
| 79 end_token_pos_(end_token_pos), | 80 end_token_pos_(end_token_pos), |
| 80 is_resolved_(false), | 81 is_resolved_(false), |
| 81 next_(NULL), | 82 next_(NULL), |
| 82 conditions_(NULL), | 83 conditions_(NULL), |
| 83 requested_line_number_(requested_line_number), | 84 requested_line_number_(requested_line_number), |
| 84 requested_column_number_(requested_column_number), | 85 requested_column_number_(requested_column_number), |
| 85 function_(Function::null()), | 86 function_(Function::null()), |
| 86 line_number_(-1), | 87 line_number_(-1), |
| 87 column_number_(-1) { | 88 column_number_(-1) { |
| 88 ASSERT(!script.IsNull()); | 89 ASSERT(!script.IsNull()); |
| 89 ASSERT(Token::IsReal(token_pos_)); | 90 ASSERT(token_pos_.IsReal()); |
| 90 } | 91 } |
| 91 | 92 |
| 92 // Create a latent breakpoint at given url and line number. | 93 // Create a latent breakpoint at given url and line number. |
| 93 BreakpointLocation::BreakpointLocation(const String& url, | 94 BreakpointLocation::BreakpointLocation(const String& url, |
| 94 intptr_t requested_line_number, | 95 intptr_t requested_line_number, |
| 95 intptr_t requested_column_number) | 96 intptr_t requested_column_number) |
| 96 : script_(Script::null()), | 97 : script_(Script::null()), |
| 97 url_(url.raw()), | 98 url_(url.raw()), |
| 98 token_pos_(Token::kNoSourcePos), | 99 token_pos_(TokenPosition::kNoSource), |
| 99 end_token_pos_(Token::kNoSourcePos), | 100 end_token_pos_(TokenPosition::kNoSource), |
| 100 is_resolved_(false), | 101 is_resolved_(false), |
| 101 next_(NULL), | 102 next_(NULL), |
| 102 conditions_(NULL), | 103 conditions_(NULL), |
| 103 requested_line_number_(requested_line_number), | 104 requested_line_number_(requested_line_number), |
| 104 requested_column_number_(requested_column_number), | 105 requested_column_number_(requested_column_number), |
| 105 function_(Function::null()), | 106 function_(Function::null()), |
| 106 line_number_(-1), | 107 line_number_(-1), |
| 107 column_number_(-1) { | 108 column_number_(-1) { |
| 108 ASSERT(requested_line_number_ >= 0); | 109 ASSERT(requested_line_number_ >= 0); |
| 109 } | 110 } |
| 110 | 111 |
| 111 | 112 |
| 112 BreakpointLocation::~BreakpointLocation() { | 113 BreakpointLocation::~BreakpointLocation() { |
| 113 Breakpoint* bpt = breakpoints(); | 114 Breakpoint* bpt = breakpoints(); |
| 114 while (bpt != NULL) { | 115 while (bpt != NULL) { |
| 115 Breakpoint* temp = bpt; | 116 Breakpoint* temp = bpt; |
| 116 bpt = bpt->next(); | 117 bpt = bpt->next(); |
| 117 delete temp; | 118 delete temp; |
| 118 } | 119 } |
| 119 } | 120 } |
| 120 | 121 |
| 121 | 122 |
| 122 bool BreakpointLocation::AnyEnabled() const { | 123 bool BreakpointLocation::AnyEnabled() const { |
| 123 return breakpoints() != NULL; | 124 return breakpoints() != NULL; |
| 124 } | 125 } |
| 125 | 126 |
| 126 | 127 |
| 127 void BreakpointLocation::SetResolved(const Function& func, intptr_t token_pos) { | 128 void BreakpointLocation::SetResolved(const Function& func, |
| 129 TokenPosition token_pos) { |
| 128 ASSERT(!IsLatent()); | 130 ASSERT(!IsLatent()); |
| 129 ASSERT(func.script() == script_); | 131 ASSERT(func.script() == script_); |
| 130 ASSERT((func.token_pos() <= token_pos) && | 132 ASSERT((func.token_pos() <= token_pos) && |
| 131 (token_pos <= func.end_token_pos())); | 133 (token_pos <= func.end_token_pos())); |
| 132 ASSERT(func.is_debuggable()); | 134 ASSERT(func.is_debuggable()); |
| 133 function_ = func.raw(); | 135 function_ = func.raw(); |
| 134 token_pos_ = token_pos; | 136 token_pos_ = token_pos; |
| 135 end_token_pos_ = token_pos; | 137 end_token_pos_ = token_pos; |
| 136 is_resolved_ = true; | 138 is_resolved_ = true; |
| 137 } | 139 } |
| 138 | 140 |
| 139 | 141 |
| 140 // TODO(hausner): Get rid of library parameter. A source breakpoint location | 142 // TODO(hausner): Get rid of library parameter. A source breakpoint location |
| 141 // does not imply a library, since the same source code can be included | 143 // does not imply a library, since the same source code can be included |
| 142 // in more than one library, e.g. the text location of mixin functions. | 144 // in more than one library, e.g. the text location of mixin functions. |
| 143 void BreakpointLocation::GetCodeLocation(Library* lib, | 145 void BreakpointLocation::GetCodeLocation(Library* lib, |
| 144 Script* script, | 146 Script* script, |
| 145 intptr_t* pos) const { | 147 TokenPosition* pos) const { |
| 146 if (IsLatent()) { | 148 if (IsLatent()) { |
| 147 *lib = Library::null(); | 149 *lib = Library::null(); |
| 148 *script = Script::null(); | 150 *script = Script::null(); |
| 149 *pos = -1; | 151 *pos = TokenPosition::kNoSource; |
| 150 } else { | 152 } else { |
| 151 *script = this->script(); | 153 *script = this->script(); |
| 152 *pos = token_pos_; | 154 *pos = token_pos_; |
| 153 if (IsResolved()) { | 155 if (IsResolved()) { |
| 154 const Function& func = Function::Handle(function_); | 156 const Function& func = Function::Handle(function_); |
| 155 ASSERT(!func.IsNull()); | 157 ASSERT(!func.IsNull()); |
| 156 const Class& cls = Class::Handle(func.origin()); | 158 const Class& cls = Class::Handle(func.origin()); |
| 157 *lib = cls.library(); | 159 *lib = cls.library(); |
| 158 } else { | 160 } else { |
| 159 *lib = Library::null(); | 161 *lib = Library::null(); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 uword fp, | 236 uword fp, |
| 235 uword sp, | 237 uword sp, |
| 236 const Code& code, | 238 const Code& code, |
| 237 const Array& deopt_frame, | 239 const Array& deopt_frame, |
| 238 intptr_t deopt_frame_offset) | 240 intptr_t deopt_frame_offset) |
| 239 : pc_(pc), fp_(fp), sp_(sp), | 241 : pc_(pc), fp_(fp), sp_(sp), |
| 240 ctx_(Context::ZoneHandle()), | 242 ctx_(Context::ZoneHandle()), |
| 241 code_(Code::ZoneHandle(code.raw())), | 243 code_(Code::ZoneHandle(code.raw())), |
| 242 function_(Function::ZoneHandle(code.function())), | 244 function_(Function::ZoneHandle(code.function())), |
| 243 token_pos_initialized_(false), | 245 token_pos_initialized_(false), |
| 244 token_pos_(Token::kNoSourcePos), | 246 token_pos_(TokenPosition::kNoSource), |
| 245 try_index_(-1), | 247 try_index_(-1), |
| 246 line_number_(-1), | 248 line_number_(-1), |
| 247 column_number_(-1), | 249 column_number_(-1), |
| 248 context_level_(-1), | 250 context_level_(-1), |
| 249 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())), | 251 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())), |
| 250 deopt_frame_offset_(deopt_frame_offset), | 252 deopt_frame_offset_(deopt_frame_offset), |
| 251 vars_initialized_(false), | 253 vars_initialized_(false), |
| 252 var_descriptors_(LocalVarDescriptors::ZoneHandle()), | 254 var_descriptors_(LocalVarDescriptors::ZoneHandle()), |
| 253 desc_indices_(8), | 255 desc_indices_(8), |
| 254 pc_desc_(PcDescriptors::ZoneHandle()) { | 256 pc_desc_(PcDescriptors::ZoneHandle()) { |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 450 return OS::SCreate(Thread::Current()->zone(), | 452 return OS::SCreate(Thread::Current()->zone(), |
| 451 "%s%s%s", func_class.IsTopLevel() ? "" : class_name.ToCString(), | 453 "%s%s%s", func_class.IsTopLevel() ? "" : class_name.ToCString(), |
| 452 func_class.IsTopLevel() ? "" : ".", | 454 func_class.IsTopLevel() ? "" : ".", |
| 453 func_name.ToCString()); | 455 func_name.ToCString()); |
| 454 } | 456 } |
| 455 | 457 |
| 456 | 458 |
| 457 // Returns true if function contains the token position in the given script. | 459 // Returns true if function contains the token position in the given script. |
| 458 static bool FunctionContains(const Function& func, | 460 static bool FunctionContains(const Function& func, |
| 459 const Script& script, | 461 const Script& script, |
| 460 intptr_t token_pos) { | 462 TokenPosition token_pos) { |
| 461 if ((func.token_pos() <= token_pos) && (token_pos <= func.end_token_pos())) { | 463 if ((func.token_pos() <= token_pos) && (token_pos <= func.end_token_pos())) { |
| 462 // Check script equality second because it allocates | 464 // Check script equality second because it allocates |
| 463 // handles as a side effect. | 465 // handles as a side effect. |
| 464 return func.script() == script.raw(); | 466 return func.script() == script.raw(); |
| 465 } | 467 } |
| 466 return false; | 468 return false; |
| 467 } | 469 } |
| 468 | 470 |
| 469 | 471 |
| 470 bool Debugger::HasBreakpoint(const Function& func, Zone* zone) { | 472 bool Debugger::HasBreakpoint(const Function& func, Zone* zone) { |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 562 | 564 |
| 563 void ActivationFrame::GetPcDescriptors() { | 565 void ActivationFrame::GetPcDescriptors() { |
| 564 if (pc_desc_.IsNull()) { | 566 if (pc_desc_.IsNull()) { |
| 565 pc_desc_ = code().pc_descriptors(); | 567 pc_desc_ = code().pc_descriptors(); |
| 566 ASSERT(!pc_desc_.IsNull()); | 568 ASSERT(!pc_desc_.IsNull()); |
| 567 } | 569 } |
| 568 } | 570 } |
| 569 | 571 |
| 570 | 572 |
| 571 // Compute token_pos_ and try_index_ and token_pos_initialized_. | 573 // Compute token_pos_ and try_index_ and token_pos_initialized_. |
| 572 intptr_t ActivationFrame::TokenPos() { | 574 TokenPosition ActivationFrame::TokenPos() { |
| 573 if (!token_pos_initialized_) { | 575 if (!token_pos_initialized_) { |
| 574 token_pos_initialized_ = true; | 576 token_pos_initialized_ = true; |
| 575 token_pos_ = Token::kNoSourcePos; | 577 token_pos_ = TokenPosition::kNoSource; |
| 576 GetPcDescriptors(); | 578 GetPcDescriptors(); |
| 577 PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind); | 579 PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind); |
| 578 uword pc_offset = pc_ - code().EntryPoint(); | 580 uword pc_offset = pc_ - code().EntryPoint(); |
| 579 while (iter.MoveNext()) { | 581 while (iter.MoveNext()) { |
| 580 if (iter.PcOffset() == pc_offset) { | 582 if (iter.PcOffset() == pc_offset) { |
| 581 try_index_ = iter.TryIndex(); | 583 try_index_ = iter.TryIndex(); |
| 582 token_pos_ = iter.TokenPos(); | 584 token_pos_ = iter.TokenPos(); |
| 583 break; | 585 break; |
| 584 } | 586 } |
| 585 } | 587 } |
| 586 } | 588 } |
| 587 return token_pos_; | 589 return token_pos_; |
| 588 } | 590 } |
| 589 | 591 |
| 590 | 592 |
| 591 intptr_t ActivationFrame::TryIndex() { | 593 intptr_t ActivationFrame::TryIndex() { |
| 592 if (!token_pos_initialized_) { | 594 if (!token_pos_initialized_) { |
| 593 TokenPos(); // Side effect: computes token_pos_initialized_, try_index_. | 595 TokenPos(); // Side effect: computes token_pos_initialized_, try_index_. |
| 594 } | 596 } |
| 595 return try_index_; | 597 return try_index_; |
| 596 } | 598 } |
| 597 | 599 |
| 598 | 600 |
| 599 intptr_t ActivationFrame::LineNumber() { | 601 intptr_t ActivationFrame::LineNumber() { |
| 600 // Compute line number lazily since it causes scanning of the script. | 602 // Compute line number lazily since it causes scanning of the script. |
| 601 if ((line_number_ < 0) && Token::IsReal(TokenPos())) { | 603 if ((line_number_ < 0) && TokenPos().IsReal()) { |
| 602 const intptr_t token_pos = TokenPos(); | 604 const TokenPosition token_pos = TokenPos(); |
| 603 const Script& script = Script::Handle(SourceScript()); | 605 const Script& script = Script::Handle(SourceScript()); |
| 604 script.GetTokenLocation(token_pos, &line_number_, NULL); | 606 script.GetTokenLocation(token_pos, &line_number_, NULL); |
| 605 } | 607 } |
| 606 return line_number_; | 608 return line_number_; |
| 607 } | 609 } |
| 608 | 610 |
| 609 | 611 |
| 610 intptr_t ActivationFrame::ColumnNumber() { | 612 intptr_t ActivationFrame::ColumnNumber() { |
| 611 // Compute column number lazily since it causes scanning of the script. | 613 // Compute column number lazily since it causes scanning of the script. |
| 612 if ((column_number_ < 0) && Token::IsReal(TokenPos())) { | 614 if ((column_number_ < 0) && TokenPos().IsReal()) { |
| 613 const intptr_t token_pos = TokenPos(); | 615 const TokenPosition token_pos = TokenPos(); |
| 614 const Script& script = Script::Handle(SourceScript()); | 616 const Script& script = Script::Handle(SourceScript()); |
| 615 if (script.HasSource()) { | 617 if (script.HasSource()) { |
| 616 script.GetTokenLocation(token_pos, &line_number_, &column_number_); | 618 script.GetTokenLocation(token_pos, &line_number_, &column_number_); |
| 617 } else { | 619 } else { |
| 618 column_number_ = -1; | 620 column_number_ = -1; |
| 619 } | 621 } |
| 620 } | 622 } |
| 621 return column_number_; | 623 return column_number_; |
| 622 } | 624 } |
| 623 | 625 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 648 // Calculate the context level at the current token index of the frame. | 650 // Calculate the context level at the current token index of the frame. |
| 649 intptr_t ActivationFrame::ContextLevel() { | 651 intptr_t ActivationFrame::ContextLevel() { |
| 650 const Context& ctx = GetSavedCurrentContext(); | 652 const Context& ctx = GetSavedCurrentContext(); |
| 651 if (context_level_ < 0 && !ctx.IsNull()) { | 653 if (context_level_ < 0 && !ctx.IsNull()) { |
| 652 ASSERT(!code_.is_optimized()); | 654 ASSERT(!code_.is_optimized()); |
| 653 context_level_ = 0; | 655 context_level_ = 0; |
| 654 // TODO(hausner): What to do if there is no descriptor entry | 656 // TODO(hausner): What to do if there is no descriptor entry |
| 655 // for the code position of the frame? For now say we are at context | 657 // for the code position of the frame? For now say we are at context |
| 656 // level 0. | 658 // level 0. |
| 657 TokenPos(); | 659 TokenPos(); |
| 658 if (token_pos_ == -1) { | 660 if (token_pos_ == TokenPosition::kNoSource) { |
| 659 // No PcDescriptor. | 661 // No PcDescriptor. |
| 660 return context_level_; | 662 return context_level_; |
| 661 } | 663 } |
| 662 ASSERT(!pc_desc_.IsNull()); | 664 ASSERT(!pc_desc_.IsNull()); |
| 663 intptr_t innermost_begin_pos = 0; | 665 TokenPosition innermost_begin_pos = TokenPosition::kMinSource; |
| 664 intptr_t activation_token_pos = TokenPos(); | 666 TokenPosition activation_token_pos = TokenPos(); |
| 665 ASSERT(Token::IsReal(activation_token_pos)); | 667 ASSERT(activation_token_pos.IsReal()); |
| 666 GetVarDescriptors(); | 668 GetVarDescriptors(); |
| 667 intptr_t var_desc_len = var_descriptors_.Length(); | 669 intptr_t var_desc_len = var_descriptors_.Length(); |
| 668 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { | 670 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { |
| 669 RawLocalVarDescriptors::VarInfo var_info; | 671 RawLocalVarDescriptors::VarInfo var_info; |
| 670 var_descriptors_.GetInfo(cur_idx, &var_info); | 672 var_descriptors_.GetInfo(cur_idx, &var_info); |
| 671 const int8_t kind = var_info.kind(); | 673 const int8_t kind = var_info.kind(); |
| 672 if ((kind == RawLocalVarDescriptors::kContextLevel) && | 674 if ((kind == RawLocalVarDescriptors::kContextLevel) && |
| 673 (var_info.begin_pos <= activation_token_pos) && | 675 (var_info.begin_pos <= activation_token_pos) && |
| 674 (activation_token_pos < var_info.end_pos)) { | 676 (activation_token_pos < var_info.end_pos)) { |
| 675 // This var_descriptors_ entry is a context scope which is in scope | 677 // 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... |
| 767 return NULL; | 769 return NULL; |
| 768 } | 770 } |
| 769 | 771 |
| 770 | 772 |
| 771 void ActivationFrame::GetDescIndices() { | 773 void ActivationFrame::GetDescIndices() { |
| 772 if (vars_initialized_) { | 774 if (vars_initialized_) { |
| 773 return; | 775 return; |
| 774 } | 776 } |
| 775 GetVarDescriptors(); | 777 GetVarDescriptors(); |
| 776 | 778 |
| 777 intptr_t activation_token_pos = TokenPos(); | 779 TokenPosition activation_token_pos = TokenPos(); |
| 778 if (!Token::IsDebugPause(activation_token_pos)) { | 780 if (!activation_token_pos.IsDebugPause()) { |
| 779 // We don't have a token position for this frame, so can't determine | 781 // We don't have a token position for this frame, so can't determine |
| 780 // which variables are visible. | 782 // which variables are visible. |
| 781 vars_initialized_ = true; | 783 vars_initialized_ = true; |
| 782 return; | 784 return; |
| 783 } | 785 } |
| 784 | 786 |
| 785 GrowableArray<String*> var_names(8); | 787 GrowableArray<String*> var_names(8); |
| 786 intptr_t var_desc_len = var_descriptors_.Length(); | 788 intptr_t var_desc_len = var_descriptors_.Length(); |
| 787 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { | 789 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { |
| 788 ASSERT(var_names.length() == desc_indices_.length()); | 790 ASSERT(var_names.length() == desc_indices_.length()); |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 928 intptr_t num = 0; | 930 intptr_t num = 0; |
| 929 while ((frame != NULL)) { | 931 while ((frame != NULL)) { |
| 930 OS::PrintErr("#%04" Pd " %s\n", num++, frame->ToCString()); | 932 OS::PrintErr("#%04" Pd " %s\n", num++, frame->ToCString()); |
| 931 frame = iterator.NextFrame(); | 933 frame = iterator.NextFrame(); |
| 932 } | 934 } |
| 933 } | 935 } |
| 934 | 936 |
| 935 | 937 |
| 936 void ActivationFrame::VariableAt(intptr_t i, | 938 void ActivationFrame::VariableAt(intptr_t i, |
| 937 String* name, | 939 String* name, |
| 938 intptr_t* token_pos, | 940 TokenPosition* token_pos, |
| 939 intptr_t* end_pos, | 941 TokenPosition* end_pos, |
| 940 Object* value) { | 942 Object* value) { |
| 941 GetDescIndices(); | 943 GetDescIndices(); |
| 942 ASSERT(i < desc_indices_.length()); | 944 ASSERT(i < desc_indices_.length()); |
| 943 intptr_t desc_index = desc_indices_[i]; | 945 intptr_t desc_index = desc_indices_[i]; |
| 944 ASSERT(name != NULL); | 946 ASSERT(name != NULL); |
| 945 | 947 |
| 946 *name = var_descriptors_.GetName(desc_index); | 948 *name = var_descriptors_.GetName(desc_index); |
| 947 | 949 |
| 948 RawLocalVarDescriptors::VarInfo var_info; | 950 RawLocalVarDescriptors::VarInfo var_info; |
| 949 var_descriptors_.GetInfo(desc_index, &var_info); | 951 var_descriptors_.GetInfo(desc_index, &var_info); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 997 } | 999 } |
| 998 | 1000 |
| 999 | 1001 |
| 1000 RawArray* ActivationFrame::GetLocalVariables() { | 1002 RawArray* ActivationFrame::GetLocalVariables() { |
| 1001 GetDescIndices(); | 1003 GetDescIndices(); |
| 1002 intptr_t num_variables = desc_indices_.length(); | 1004 intptr_t num_variables = desc_indices_.length(); |
| 1003 String& var_name = String::Handle(); | 1005 String& var_name = String::Handle(); |
| 1004 Object& value = Instance::Handle(); | 1006 Object& value = Instance::Handle(); |
| 1005 const Array& list = Array::Handle(Array::New(2 * num_variables)); | 1007 const Array& list = Array::Handle(Array::New(2 * num_variables)); |
| 1006 for (intptr_t i = 0; i < num_variables; i++) { | 1008 for (intptr_t i = 0; i < num_variables; i++) { |
| 1007 intptr_t ignore; | 1009 TokenPosition ignore; |
| 1008 VariableAt(i, &var_name, &ignore, &ignore, &value); | 1010 VariableAt(i, &var_name, &ignore, &ignore, &value); |
| 1009 list.SetAt(2 * i, var_name); | 1011 list.SetAt(2 * i, var_name); |
| 1010 list.SetAt((2 * i) + 1, value); | 1012 list.SetAt((2 * i) + 1, value); |
| 1011 } | 1013 } |
| 1012 return list.raw(); | 1014 return list.raw(); |
| 1013 } | 1015 } |
| 1014 | 1016 |
| 1015 | 1017 |
| 1016 RawObject* ActivationFrame::GetReceiver() { | 1018 RawObject* ActivationFrame::GetReceiver() { |
| 1017 GetDescIndices(); | 1019 GetDescIndices(); |
| 1018 intptr_t num_variables = desc_indices_.length(); | 1020 intptr_t num_variables = desc_indices_.length(); |
| 1019 String& var_name = String::Handle(); | 1021 String& var_name = String::Handle(); |
| 1020 Instance& value = Instance::Handle(); | 1022 Instance& value = Instance::Handle(); |
| 1021 for (intptr_t i = 0; i < num_variables; i++) { | 1023 for (intptr_t i = 0; i < num_variables; i++) { |
| 1022 intptr_t ignore; | 1024 TokenPosition ignore; |
| 1023 VariableAt(i, &var_name, &ignore, &ignore, &value); | 1025 VariableAt(i, &var_name, &ignore, &ignore, &value); |
| 1024 if (var_name.Equals(Symbols::This())) { | 1026 if (var_name.Equals(Symbols::This())) { |
| 1025 return value.raw(); | 1027 return value.raw(); |
| 1026 } | 1028 } |
| 1027 } | 1029 } |
| 1028 return Symbols::OptimizedOut().raw(); | 1030 return Symbols::OptimizedOut().raw(); |
| 1029 } | 1031 } |
| 1030 | 1032 |
| 1031 | 1033 |
| 1032 bool IsPrivateVariableName(const String& var_name) { | 1034 bool IsPrivateVariableName(const String& var_name) { |
| 1033 return (var_name.Length() >= 1) && (var_name.CharAt(0) == '_'); | 1035 return (var_name.Length() >= 1) && (var_name.CharAt(0) == '_'); |
| 1034 } | 1036 } |
| 1035 | 1037 |
| 1036 | 1038 |
| 1037 RawObject* ActivationFrame::Evaluate(const String& expr) { | 1039 RawObject* ActivationFrame::Evaluate(const String& expr) { |
| 1038 GetDescIndices(); | 1040 GetDescIndices(); |
| 1039 const GrowableObjectArray& param_names = | 1041 const GrowableObjectArray& param_names = |
| 1040 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 1042 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
| 1041 const GrowableObjectArray& param_values = | 1043 const GrowableObjectArray& param_values = |
| 1042 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 1044 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
| 1043 String& name = String::Handle(); | 1045 String& name = String::Handle(); |
| 1044 Object& value = Instance::Handle(); | 1046 Object& value = Instance::Handle(); |
| 1045 intptr_t num_variables = desc_indices_.length(); | 1047 intptr_t num_variables = desc_indices_.length(); |
| 1046 for (intptr_t i = 0; i < num_variables; i++) { | 1048 for (intptr_t i = 0; i < num_variables; i++) { |
| 1047 intptr_t ignore; | 1049 TokenPosition ignore; |
| 1048 VariableAt(i, &name, &ignore, &ignore, &value); | 1050 VariableAt(i, &name, &ignore, &ignore, &value); |
| 1049 if (!name.Equals(Symbols::This())) { | 1051 if (!name.Equals(Symbols::This())) { |
| 1050 if (IsPrivateVariableName(name)) { | 1052 if (IsPrivateVariableName(name)) { |
| 1051 name = String::IdentifierPrettyName(name); | 1053 name = String::IdentifierPrettyName(name); |
| 1052 } | 1054 } |
| 1053 param_names.Add(name); | 1055 param_names.Add(name); |
| 1054 param_values.Add(value); | 1056 param_values.Add(value); |
| 1055 } | 1057 } |
| 1056 } | 1058 } |
| 1057 | 1059 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1108 // in the world where we pass the script as part of the | 1110 // in the world where we pass the script as part of the |
| 1109 // location. | 1111 // location. |
| 1110 jsobj->AddProperty("script", script, !full); | 1112 jsobj->AddProperty("script", script, !full); |
| 1111 } | 1113 } |
| 1112 { | 1114 { |
| 1113 JSONArray jsvars(jsobj, "vars"); | 1115 JSONArray jsvars(jsobj, "vars"); |
| 1114 const int num_vars = NumLocalVariables(); | 1116 const int num_vars = NumLocalVariables(); |
| 1115 for (intptr_t v = 0; v < num_vars; v++) { | 1117 for (intptr_t v = 0; v < num_vars; v++) { |
| 1116 String& var_name = String::Handle(); | 1118 String& var_name = String::Handle(); |
| 1117 Instance& var_value = Instance::Handle(); | 1119 Instance& var_value = Instance::Handle(); |
| 1118 intptr_t token_pos; | 1120 TokenPosition token_pos; |
| 1119 intptr_t end_token_pos; | 1121 TokenPosition end_token_pos; |
| 1120 VariableAt(v, &var_name, &token_pos, &end_token_pos, &var_value); | 1122 VariableAt(v, &var_name, &token_pos, &end_token_pos, &var_value); |
| 1121 if (var_name.raw() != Symbols::AsyncOperation().raw()) { | 1123 if (var_name.raw() != Symbols::AsyncOperation().raw()) { |
| 1122 JSONObject jsvar(&jsvars); | 1124 JSONObject jsvar(&jsvars); |
| 1123 jsvar.AddProperty("type", "BoundVariable"); | 1125 jsvar.AddProperty("type", "BoundVariable"); |
| 1124 var_name = String::IdentifierPrettyName(var_name); | 1126 var_name = String::IdentifierPrettyName(var_name); |
| 1125 jsvar.AddProperty("name", var_name.ToCString()); | 1127 jsvar.AddProperty("name", var_name.ToCString()); |
| 1126 jsvar.AddProperty("value", var_value, !full); | 1128 jsvar.AddProperty("value", var_value, !full); |
| 1127 // TODO(turnidge): Do we really want to provide this on every | 1129 // TODO(turnidge): Do we really want to provide this on every |
| 1128 // stack dump? Should be associated with the function object, I | 1130 // stack dump? Should be associated with the function object, I |
| 1129 // think, and not the stack frame. | 1131 // think, and not the stack frame. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1142 } | 1144 } |
| 1143 } | 1145 } |
| 1144 | 1146 |
| 1145 | 1147 |
| 1146 const uint8_t kSafepointKind = RawPcDescriptors::kIcCall | 1148 const uint8_t kSafepointKind = RawPcDescriptors::kIcCall |
| 1147 | RawPcDescriptors::kUnoptStaticCall | 1149 | RawPcDescriptors::kUnoptStaticCall |
| 1148 | RawPcDescriptors::kRuntimeCall; | 1150 | RawPcDescriptors::kRuntimeCall; |
| 1149 | 1151 |
| 1150 | 1152 |
| 1151 CodeBreakpoint::CodeBreakpoint(const Code& code, | 1153 CodeBreakpoint::CodeBreakpoint(const Code& code, |
| 1152 intptr_t token_pos, | 1154 TokenPosition token_pos, |
| 1153 uword pc, | 1155 uword pc, |
| 1154 RawPcDescriptors::Kind kind) | 1156 RawPcDescriptors::Kind kind) |
| 1155 : code_(code.raw()), | 1157 : code_(code.raw()), |
| 1156 token_pos_(token_pos), | 1158 token_pos_(token_pos), |
| 1157 pc_(pc), | 1159 pc_(pc), |
| 1158 line_number_(-1), | 1160 line_number_(-1), |
| 1159 is_enabled_(false), | 1161 is_enabled_(false), |
| 1160 bpt_location_(NULL), | 1162 bpt_location_(NULL), |
| 1161 next_(NULL), | 1163 next_(NULL), |
| 1162 breakpoint_kind_(kind), | 1164 breakpoint_kind_(kind), |
| 1163 saved_value_(Code::null()) { | 1165 saved_value_(Code::null()) { |
| 1164 ASSERT(!code.IsNull()); | 1166 ASSERT(!code.IsNull()); |
| 1165 ASSERT(token_pos_ > 0); | 1167 ASSERT(token_pos_.IsReal()); |
| 1166 ASSERT(pc_ != 0); | 1168 ASSERT(pc_ != 0); |
| 1167 ASSERT((breakpoint_kind_ & kSafepointKind) != 0); | 1169 ASSERT((breakpoint_kind_ & kSafepointKind) != 0); |
| 1168 } | 1170 } |
| 1169 | 1171 |
| 1170 | 1172 |
| 1171 CodeBreakpoint::~CodeBreakpoint() { | 1173 CodeBreakpoint::~CodeBreakpoint() { |
| 1172 // Make sure we don't leave patched code behind. | 1174 // Make sure we don't leave patched code behind. |
| 1173 ASSERT(!IsEnabled()); | 1175 ASSERT(!IsEnabled()); |
| 1174 // Poison the data so we catch use after free errors. | 1176 // Poison the data so we catch use after free errors. |
| 1175 #ifdef DEBUG | 1177 #ifdef DEBUG |
| (...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1646 event.set_exception(&exc); | 1648 event.set_exception(&exc); |
| 1647 ASSERT(stack_trace->Length() > 0); | 1649 ASSERT(stack_trace->Length() > 0); |
| 1648 event.set_top_frame(stack_trace->FrameAt(0)); | 1650 event.set_top_frame(stack_trace->FrameAt(0)); |
| 1649 ASSERT(stack_trace_ == NULL); | 1651 ASSERT(stack_trace_ == NULL); |
| 1650 stack_trace_ = stack_trace; | 1652 stack_trace_ = stack_trace; |
| 1651 Pause(&event); | 1653 Pause(&event); |
| 1652 stack_trace_ = NULL; | 1654 stack_trace_ = NULL; |
| 1653 } | 1655 } |
| 1654 | 1656 |
| 1655 | 1657 |
| 1656 static intptr_t LastTokenOnLine(const TokenStream& tokens, intptr_t pos) { | 1658 static TokenPosition LastTokenOnLine(const TokenStream& tokens, |
| 1657 TokenStream::Iterator iter(tokens, pos, TokenStream::Iterator::kAllTokens); | 1659 TokenPosition pos) { |
| 1660 TokenStream::Iterator iter(tokens, |
| 1661 pos, |
| 1662 TokenStream::Iterator::kAllTokens); |
| 1658 ASSERT(iter.IsValid()); | 1663 ASSERT(iter.IsValid()); |
| 1659 intptr_t last_pos = pos; | 1664 TokenPosition last_pos = pos; |
| 1660 while ((iter.CurrentTokenKind() != Token::kNEWLINE) && | 1665 while ((iter.CurrentTokenKind() != Token::kNEWLINE) && |
| 1661 (iter.CurrentTokenKind() != Token::kEOS)) { | 1666 (iter.CurrentTokenKind() != Token::kEOS)) { |
| 1662 last_pos = iter.CurrentPosition(); | 1667 last_pos = iter.CurrentPosition(); |
| 1663 iter.Advance(); | 1668 iter.Advance(); |
| 1664 } | 1669 } |
| 1665 return last_pos; | 1670 return last_pos; |
| 1666 } | 1671 } |
| 1667 | 1672 |
| 1668 | 1673 |
| 1669 // Returns the best fit token position for a breakpoint. | 1674 // Returns the best fit token position for a breakpoint. |
| 1670 // | 1675 // |
| 1671 // Takes a range of tokens [requested_token_pos, last_token_pos] and | 1676 // Takes a range of tokens [requested_token_pos, last_token_pos] and |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1715 // | 1720 // |
| 1716 // If no best fit token can be found, the search is expanded, | 1721 // If no best fit token can be found, the search is expanded, |
| 1717 // searching through the rest of the current function by calling this | 1722 // searching through the rest of the current function by calling this |
| 1718 // function recursively. | 1723 // function recursively. |
| 1719 // | 1724 // |
| 1720 // TODO(turnidge): Given that we usually call this function with a | 1725 // TODO(turnidge): Given that we usually call this function with a |
| 1721 // token range restricted to a single line, this could be a one-pass | 1726 // token range restricted to a single line, this could be a one-pass |
| 1722 // algorithm, which would be simpler. I believe that it only needs | 1727 // algorithm, which would be simpler. I believe that it only needs |
| 1723 // two passes to support the recursive try-the-whole-function case. | 1728 // two passes to support the recursive try-the-whole-function case. |
| 1724 // Rewrite this later, once there are more tests in place. | 1729 // Rewrite this later, once there are more tests in place. |
| 1725 intptr_t Debugger::ResolveBreakpointPos(const Function& func, | 1730 TokenPosition Debugger::ResolveBreakpointPos( |
| 1726 intptr_t requested_token_pos, | 1731 const Function& func, |
| 1727 intptr_t last_token_pos, | 1732 TokenPosition requested_token_pos, |
| 1728 intptr_t requested_column) { | 1733 TokenPosition last_token_pos, |
| 1734 intptr_t requested_column) { |
| 1729 ASSERT(func.HasCode()); | 1735 ASSERT(func.HasCode()); |
| 1730 ASSERT(!func.HasOptimizedCode()); | 1736 ASSERT(!func.HasOptimizedCode()); |
| 1731 | 1737 |
| 1732 if (requested_token_pos < func.token_pos()) { | 1738 if (requested_token_pos < func.token_pos()) { |
| 1733 requested_token_pos = func.token_pos(); | 1739 requested_token_pos = func.token_pos(); |
| 1734 } | 1740 } |
| 1735 if (last_token_pos > func.end_token_pos()) { | 1741 if (last_token_pos > func.end_token_pos()) { |
| 1736 last_token_pos = func.end_token_pos(); | 1742 last_token_pos = func.end_token_pos(); |
| 1737 } | 1743 } |
| 1738 | 1744 |
| 1739 Script& script = Script::Handle(func.script()); | 1745 Script& script = Script::Handle(func.script()); |
| 1740 Code& code = Code::Handle(func.unoptimized_code()); | 1746 Code& code = Code::Handle(func.unoptimized_code()); |
| 1741 ASSERT(!code.IsNull()); | 1747 ASSERT(!code.IsNull()); |
| 1742 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 1748 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
| 1743 | 1749 |
| 1744 // First pass: find the safe point which is closest to the beginning | 1750 // First pass: find the safe point which is closest to the beginning |
| 1745 // of the given token range. | 1751 // of the given token range. |
| 1746 intptr_t best_fit_pos = INT_MAX; | 1752 TokenPosition best_fit_pos = TokenPosition::kMaxSource; |
| 1747 intptr_t best_column = INT_MAX; | 1753 intptr_t best_column = INT_MAX; |
| 1748 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1754 PcDescriptors::Iterator iter(desc, kSafepointKind); |
| 1749 while (iter.MoveNext()) { | 1755 while (iter.MoveNext()) { |
| 1750 const intptr_t pos = iter.TokenPos(); | 1756 const TokenPosition pos = iter.TokenPos(); |
| 1751 if ((!Token::IsReal(pos)) || | 1757 if ((!pos.IsReal()) || |
| 1752 (pos < requested_token_pos) || | 1758 (pos < requested_token_pos) || |
| 1753 (pos > last_token_pos)) { | 1759 (pos > last_token_pos)) { |
| 1754 // Token is not in the target range. | 1760 // Token is not in the target range. |
| 1755 continue; | 1761 continue; |
| 1756 } | 1762 } |
| 1757 | 1763 |
| 1758 intptr_t token_start_column = -1; | 1764 intptr_t token_start_column = -1; |
| 1759 if (requested_column >= 0) { | 1765 if (requested_column >= 0) { |
| 1760 intptr_t ignored = -1; | 1766 intptr_t ignored = -1; |
| 1761 intptr_t token_len = -1; | 1767 intptr_t token_len = -1; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1778 // Prefer the lowest (first) token pos. | 1784 // Prefer the lowest (first) token pos. |
| 1779 if (pos < best_fit_pos) { | 1785 if (pos < best_fit_pos) { |
| 1780 best_fit_pos = pos; | 1786 best_fit_pos = pos; |
| 1781 best_column = token_start_column; | 1787 best_column = token_start_column; |
| 1782 } | 1788 } |
| 1783 } | 1789 } |
| 1784 | 1790 |
| 1785 // Second pass (if we found a safe point in the first pass). Find | 1791 // Second pass (if we found a safe point in the first pass). Find |
| 1786 // the token on the line which is at the best fit column (if column | 1792 // the token on the line which is at the best fit column (if column |
| 1787 // was specified) and has the lowest code address. | 1793 // was specified) and has the lowest code address. |
| 1788 if (best_fit_pos != INT_MAX) { | 1794 if (best_fit_pos != TokenPosition::kMaxSource) { |
| 1789 const Script& script = Script::Handle(func.script()); | 1795 const Script& script = Script::Handle(func.script()); |
| 1790 const TokenStream& tokens = TokenStream::Handle(script.tokens()); | 1796 const TokenStream& tokens = TokenStream::Handle(script.tokens()); |
| 1791 const intptr_t begin_pos = best_fit_pos; | 1797 const TokenPosition begin_pos = best_fit_pos; |
| 1792 const intptr_t end_of_line_pos = LastTokenOnLine(tokens, begin_pos); | 1798 const TokenPosition end_of_line_pos = LastTokenOnLine(tokens, begin_pos); |
| 1793 uword lowest_pc_offset = kUwordMax; | 1799 uword lowest_pc_offset = kUwordMax; |
| 1794 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1800 PcDescriptors::Iterator iter(desc, kSafepointKind); |
| 1795 while (iter.MoveNext()) { | 1801 while (iter.MoveNext()) { |
| 1796 const intptr_t pos = iter.TokenPos(); | 1802 const TokenPosition pos = iter.TokenPos(); |
| 1797 if ((!Token::IsReal(pos)) || | 1803 if (!pos.IsReal() || |
| 1798 (pos < begin_pos) || | 1804 (pos < begin_pos) || |
| 1799 (pos > end_of_line_pos)) { | 1805 (pos > end_of_line_pos)) { |
| 1800 // Token is not on same line as best fit. | 1806 // Token is not on same line as best fit. |
| 1801 continue; | 1807 continue; |
| 1802 } | 1808 } |
| 1803 | 1809 |
| 1804 if (requested_column >= 0) { | 1810 if (requested_column >= 0) { |
| 1805 intptr_t ignored = -1; | 1811 intptr_t ignored = -1; |
| 1806 intptr_t token_start_column = -1; | 1812 intptr_t token_start_column = -1; |
| 1807 // We look for other tokens at the best column in case there | 1813 // We look for other tokens at the best column in case there |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1822 } | 1828 } |
| 1823 | 1829 |
| 1824 // We didn't find a safe point in the given token range. Try and | 1830 // We didn't find a safe point in the given token range. Try and |
| 1825 // find a safe point in the remaining source code of the function. | 1831 // find a safe point in the remaining source code of the function. |
| 1826 // Since we have moved to the next line of the function, we no | 1832 // Since we have moved to the next line of the function, we no |
| 1827 // longer are requesting a specific column number. | 1833 // longer are requesting a specific column number. |
| 1828 if (last_token_pos < func.end_token_pos()) { | 1834 if (last_token_pos < func.end_token_pos()) { |
| 1829 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos(), | 1835 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos(), |
| 1830 -1 /* no column */); | 1836 -1 /* no column */); |
| 1831 } | 1837 } |
| 1832 return Token::kNoSourcePos; | 1838 return TokenPosition::kNoSource; |
| 1833 } | 1839 } |
| 1834 | 1840 |
| 1835 | 1841 |
| 1836 void Debugger::MakeCodeBreakpointAt(const Function& func, | 1842 void Debugger::MakeCodeBreakpointAt(const Function& func, |
| 1837 BreakpointLocation* loc) { | 1843 BreakpointLocation* loc) { |
| 1838 ASSERT(Token::IsReal(loc->token_pos_)); | 1844 ASSERT(loc->token_pos_.IsReal()); |
| 1839 ASSERT((loc != NULL) && loc->IsResolved()); | 1845 ASSERT((loc != NULL) && loc->IsResolved()); |
| 1840 ASSERT(!func.HasOptimizedCode()); | 1846 ASSERT(!func.HasOptimizedCode()); |
| 1841 Code& code = Code::Handle(func.unoptimized_code()); | 1847 Code& code = Code::Handle(func.unoptimized_code()); |
| 1842 ASSERT(!code.IsNull()); | 1848 ASSERT(!code.IsNull()); |
| 1843 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 1849 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
| 1844 uword lowest_pc_offset = kUwordMax; | 1850 uword lowest_pc_offset = kUwordMax; |
| 1845 RawPcDescriptors::Kind lowest_kind = RawPcDescriptors::kAnyKind; | 1851 RawPcDescriptors::Kind lowest_kind = RawPcDescriptors::kAnyKind; |
| 1846 // Find the safe point with the lowest compiled code address | 1852 // Find the safe point with the lowest compiled code address |
| 1847 // that maps to the token position of the source breakpoint. | 1853 // that maps to the token position of the source breakpoint. |
| 1848 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1854 PcDescriptors::Iterator iter(desc, kSafepointKind); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1866 RegisterCodeBreakpoint(code_bpt); | 1872 RegisterCodeBreakpoint(code_bpt); |
| 1867 } | 1873 } |
| 1868 code_bpt->set_bpt_location(loc); | 1874 code_bpt->set_bpt_location(loc); |
| 1869 if (loc->AnyEnabled()) { | 1875 if (loc->AnyEnabled()) { |
| 1870 code_bpt->Enable(); | 1876 code_bpt->Enable(); |
| 1871 } | 1877 } |
| 1872 } | 1878 } |
| 1873 | 1879 |
| 1874 | 1880 |
| 1875 void Debugger::FindCompiledFunctions(const Script& script, | 1881 void Debugger::FindCompiledFunctions(const Script& script, |
| 1876 intptr_t start_pos, | 1882 TokenPosition start_pos, |
| 1877 intptr_t end_pos, | 1883 TokenPosition end_pos, |
| 1878 GrowableObjectArray* function_list) { | 1884 GrowableObjectArray* function_list) { |
| 1879 Zone* zone = Thread::Current()->zone(); | 1885 Zone* zone = Thread::Current()->zone(); |
| 1880 Class& cls = Class::Handle(zone); | 1886 Class& cls = Class::Handle(zone); |
| 1881 Array& functions = Array::Handle(zone); | 1887 Array& functions = Array::Handle(zone); |
| 1882 GrowableObjectArray& closures = GrowableObjectArray::Handle(zone); | 1888 GrowableObjectArray& closures = GrowableObjectArray::Handle(zone); |
| 1883 Function& function = Function::Handle(zone); | 1889 Function& function = Function::Handle(zone); |
| 1884 | 1890 |
| 1885 closures = isolate_->object_store()->closure_functions(); | 1891 closures = isolate_->object_store()->closure_functions(); |
| 1886 const intptr_t num_closures = closures.Length(); | 1892 const intptr_t num_closures = closures.Length(); |
| 1887 for (intptr_t pos = 0; pos < num_closures; pos++) { | 1893 for (intptr_t pos = 0; pos < num_closures; pos++) { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1951 } else { | 1957 } else { |
| 1952 if ((func->token_pos() > best_fit->token_pos()) && | 1958 if ((func->token_pos() > best_fit->token_pos()) && |
| 1953 ((func->end_token_pos() <= best_fit->end_token_pos()))) { | 1959 ((func->end_token_pos() <= best_fit->end_token_pos()))) { |
| 1954 *best_fit = func->raw(); | 1960 *best_fit = func->raw(); |
| 1955 } | 1961 } |
| 1956 } | 1962 } |
| 1957 } | 1963 } |
| 1958 | 1964 |
| 1959 | 1965 |
| 1960 RawFunction* Debugger::FindBestFit(const Script& script, | 1966 RawFunction* Debugger::FindBestFit(const Script& script, |
| 1961 intptr_t token_pos) { | 1967 TokenPosition token_pos) { |
| 1962 Zone* zone = Thread::Current()->zone(); | 1968 Zone* zone = Thread::Current()->zone(); |
| 1963 Class& cls = Class::Handle(zone); | 1969 Class& cls = Class::Handle(zone); |
| 1964 Array& functions = Array::Handle(zone); | 1970 Array& functions = Array::Handle(zone); |
| 1965 GrowableObjectArray& closures = GrowableObjectArray::Handle(zone); | 1971 GrowableObjectArray& closures = GrowableObjectArray::Handle(zone); |
| 1966 Function& function = Function::Handle(zone); | 1972 Function& function = Function::Handle(zone); |
| 1967 Function& best_fit = Function::Handle(zone); | 1973 Function& best_fit = Function::Handle(zone); |
| 1968 Error& error = Error::Handle(zone); | 1974 Error& error = Error::Handle(zone); |
| 1969 | 1975 |
| 1970 closures = isolate_->object_store()->closure_functions(); | 1976 closures = isolate_->object_store()->closure_functions(); |
| 1971 const intptr_t num_closures = closures.Length(); | 1977 const intptr_t num_closures = closures.Length(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2010 } | 2016 } |
| 2011 } | 2017 } |
| 2012 } | 2018 } |
| 2013 } | 2019 } |
| 2014 } | 2020 } |
| 2015 return best_fit.raw(); | 2021 return best_fit.raw(); |
| 2016 } | 2022 } |
| 2017 | 2023 |
| 2018 | 2024 |
| 2019 BreakpointLocation* Debugger::SetBreakpoint(const Script& script, | 2025 BreakpointLocation* Debugger::SetBreakpoint(const Script& script, |
| 2020 intptr_t token_pos, | 2026 TokenPosition token_pos, |
| 2021 intptr_t last_token_pos, | 2027 TokenPosition last_token_pos, |
| 2022 intptr_t requested_line, | 2028 intptr_t requested_line, |
| 2023 intptr_t requested_column) { | 2029 intptr_t requested_column) { |
| 2024 Function& func = Function::Handle(); | 2030 Function& func = Function::Handle(); |
| 2025 func = FindBestFit(script, token_pos); | 2031 func = FindBestFit(script, token_pos); |
| 2026 if (func.IsNull()) { | 2032 if (func.IsNull()) { |
| 2027 return NULL; | 2033 return NULL; |
| 2028 } | 2034 } |
| 2029 // There may be more than one function object for a given function | 2035 // There may be more than one function object for a given function |
| 2030 // in source code. There may be implicit closure functions, and | 2036 // in source code. There may be implicit closure functions, and |
| 2031 // there may be copies of mixin functions. Collect all compiled | 2037 // there may be copies of mixin functions. Collect all compiled |
| 2032 // functions whose source code range matches exactly the best fit | 2038 // functions whose source code range matches exactly the best fit |
| 2033 // function we found. | 2039 // function we found. |
| 2034 GrowableObjectArray& functions = | 2040 GrowableObjectArray& functions = |
| 2035 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 2041 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
| 2036 FindCompiledFunctions(script, | 2042 FindCompiledFunctions(script, |
| 2037 func.token_pos(), | 2043 func.token_pos(), |
| 2038 func.end_token_pos(), | 2044 func.end_token_pos(), |
| 2039 &functions); | 2045 &functions); |
| 2040 | 2046 |
| 2041 if (functions.Length() > 0) { | 2047 if (functions.Length() > 0) { |
| 2042 // One or more function object containing this breakpoint location | 2048 // One or more function object containing this breakpoint location |
| 2043 // have already been compiled. We can resolve the breakpoint now. | 2049 // have already been compiled. We can resolve the breakpoint now. |
| 2044 DeoptimizeWorld(); | 2050 DeoptimizeWorld(); |
| 2045 func ^= functions.At(0); | 2051 func ^= functions.At(0); |
| 2046 intptr_t breakpoint_pos = | 2052 TokenPosition breakpoint_pos = |
| 2047 ResolveBreakpointPos(func, token_pos, last_token_pos, requested_column); | 2053 ResolveBreakpointPos(func, token_pos, last_token_pos, requested_column); |
| 2048 if (breakpoint_pos >= 0) { | 2054 if (breakpoint_pos.IsReal()) { |
| 2049 BreakpointLocation* bpt = | 2055 BreakpointLocation* bpt = |
| 2050 GetBreakpointLocation(script, breakpoint_pos, requested_column); | 2056 GetBreakpointLocation(script, breakpoint_pos, requested_column); |
| 2051 if (bpt != NULL) { | 2057 if (bpt != NULL) { |
| 2052 // A source breakpoint for this location already exists. | 2058 // A source breakpoint for this location already exists. |
| 2053 return bpt; | 2059 return bpt; |
| 2054 } | 2060 } |
| 2055 bpt = new BreakpointLocation(script, token_pos, last_token_pos, | 2061 bpt = new BreakpointLocation(script, token_pos, last_token_pos, |
| 2056 requested_line, requested_column); | 2062 requested_line, requested_column); |
| 2057 bpt->SetResolved(func, breakpoint_pos); | 2063 bpt->SetResolved(func, breakpoint_pos); |
| 2058 RegisterBreakpointLocation(bpt); | 2064 RegisterBreakpointLocation(bpt); |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2241 } | 2247 } |
| 2242 return latent_bpt; | 2248 return latent_bpt; |
| 2243 } | 2249 } |
| 2244 if (scripts.Length() > 1) { | 2250 if (scripts.Length() > 1) { |
| 2245 if (FLAG_verbose_debug) { | 2251 if (FLAG_verbose_debug) { |
| 2246 OS::Print("Multiple scripts match url '%s'\n", script_url.ToCString()); | 2252 OS::Print("Multiple scripts match url '%s'\n", script_url.ToCString()); |
| 2247 } | 2253 } |
| 2248 return NULL; | 2254 return NULL; |
| 2249 } | 2255 } |
| 2250 script ^= scripts.At(0); | 2256 script ^= scripts.At(0); |
| 2251 intptr_t first_token_idx, last_token_idx; | 2257 TokenPosition first_token_idx, last_token_idx; |
| 2252 script.TokenRangeAtLine(line_number, &first_token_idx, &last_token_idx); | 2258 script.TokenRangeAtLine(line_number, &first_token_idx, &last_token_idx); |
| 2253 if (!Token::IsReal(first_token_idx)) { | 2259 if (!first_token_idx.IsReal()) { |
| 2254 // Script does not contain the given line number. | 2260 // Script does not contain the given line number. |
| 2255 if (FLAG_verbose_debug) { | 2261 if (FLAG_verbose_debug) { |
| 2256 OS::Print("Script '%s' does not contain line number %" Pd "\n", | 2262 OS::Print("Script '%s' does not contain line number %" Pd "\n", |
| 2257 script_url.ToCString(), line_number); | 2263 script_url.ToCString(), line_number); |
| 2258 } | 2264 } |
| 2259 return NULL; | 2265 return NULL; |
| 2260 } else if (!Token::IsReal(last_token_idx)) { | 2266 } else if (!last_token_idx.IsReal()) { |
| 2261 // Line does not contain any tokens. | 2267 // Line does not contain any tokens. |
| 2262 if (FLAG_verbose_debug) { | 2268 if (FLAG_verbose_debug) { |
| 2263 OS::Print("No executable code at line %" Pd " in '%s'\n", | 2269 OS::Print("No executable code at line %" Pd " in '%s'\n", |
| 2264 line_number, script_url.ToCString()); | 2270 line_number, script_url.ToCString()); |
| 2265 } | 2271 } |
| 2266 return NULL; | 2272 return NULL; |
| 2267 } | 2273 } |
| 2268 | 2274 |
| 2269 BreakpointLocation* bpt = NULL; | 2275 BreakpointLocation* bpt = NULL; |
| 2270 ASSERT(first_token_idx <= last_token_idx); | 2276 ASSERT(first_token_idx <= last_token_idx); |
| 2271 while ((bpt == NULL) && (first_token_idx <= last_token_idx)) { | 2277 while ((bpt == NULL) && (first_token_idx <= last_token_idx)) { |
| 2272 bpt = SetBreakpoint(script, first_token_idx, last_token_idx, | 2278 bpt = SetBreakpoint(script, first_token_idx, last_token_idx, |
| 2273 line_number, column_number); | 2279 line_number, column_number); |
| 2274 first_token_idx++; | 2280 first_token_idx.Next(); |
| 2275 } | 2281 } |
| 2276 if ((bpt == NULL) && FLAG_verbose_debug) { | 2282 if ((bpt == NULL) && FLAG_verbose_debug) { |
| 2277 OS::Print("No executable code at line %" Pd " in '%s'\n", | 2283 OS::Print("No executable code at line %" Pd " in '%s'\n", |
| 2278 line_number, script_url.ToCString()); | 2284 line_number, script_url.ToCString()); |
| 2279 } | 2285 } |
| 2280 return bpt; | 2286 return bpt; |
| 2281 } | 2287 } |
| 2282 | 2288 |
| 2283 | 2289 |
| 2284 intptr_t Debugger::CacheObject(const Object& obj) { | 2290 intptr_t Debugger::CacheObject(const Object& obj) { |
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2658 // We returned from the "interesting frame", there can be no more | 2664 // We returned from the "interesting frame", there can be no more |
| 2659 // stepping breaks for it. Pause at the next appropriate location | 2665 // stepping breaks for it. Pause at the next appropriate location |
| 2660 // and let the user set the "interesting" frame again. | 2666 // and let the user set the "interesting" frame again. |
| 2661 stepping_fp_ = 0; | 2667 stepping_fp_ = 0; |
| 2662 } | 2668 } |
| 2663 } | 2669 } |
| 2664 | 2670 |
| 2665 if (!frame->IsDebuggable()) { | 2671 if (!frame->IsDebuggable()) { |
| 2666 return Error::null(); | 2672 return Error::null(); |
| 2667 } | 2673 } |
| 2668 if (!Token::IsDebugPause(frame->TokenPos())) { | 2674 if (!frame->TokenPos().IsDebugPause()) { |
| 2669 return Error::null(); | 2675 return Error::null(); |
| 2670 } | 2676 } |
| 2671 | 2677 |
| 2672 // If there is an active breakpoint at this pc, then we should have | 2678 // If there is an active breakpoint at this pc, then we should have |
| 2673 // already bailed out of this function in the skip_next_step_ test | 2679 // already bailed out of this function in the skip_next_step_ test |
| 2674 // above. | 2680 // above. |
| 2675 ASSERT(!HasActiveBreakpoint(frame->pc())); | 2681 ASSERT(!HasActiveBreakpoint(frame->pc())); |
| 2676 | 2682 |
| 2677 if (FLAG_verbose_debug) { | 2683 if (FLAG_verbose_debug) { |
| 2678 OS::Print(">>> single step break at %s:%" Pd " (func %s token %" Pd ")\n", | 2684 OS::Print(">>> single step break at %s:%" Pd " (func %s token %s)\n", |
| 2679 String::Handle(frame->SourceUrl()).ToCString(), | 2685 String::Handle(frame->SourceUrl()).ToCString(), |
| 2680 frame->LineNumber(), | 2686 frame->LineNumber(), |
| 2681 String::Handle(frame->QualifiedFunctionName()).ToCString(), | 2687 String::Handle(frame->QualifiedFunctionName()).ToCString(), |
| 2682 frame->TokenPos()); | 2688 frame->TokenPos().ToCString()); |
| 2683 } | 2689 } |
| 2684 | 2690 |
| 2685 ASSERT(stack_trace_ == NULL); | 2691 ASSERT(stack_trace_ == NULL); |
| 2686 stack_trace_ = CollectStackTrace(); | 2692 stack_trace_ = CollectStackTrace(); |
| 2687 SignalPausedEvent(frame, NULL); | 2693 SignalPausedEvent(frame, NULL); |
| 2688 HandleSteppingRequest(stack_trace_); | 2694 HandleSteppingRequest(stack_trace_); |
| 2689 stack_trace_ = NULL; | 2695 stack_trace_ = NULL; |
| 2690 | 2696 |
| 2691 // If any error occurred while in the debug message loop, return it here. | 2697 // If any error occurred while in the debug message loop, return it here. |
| 2692 const Error& error = | 2698 const Error& error = |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2753 } | 2759 } |
| 2754 } | 2760 } |
| 2755 } | 2761 } |
| 2756 | 2762 |
| 2757 if (bpt_hit == NULL) { | 2763 if (bpt_hit == NULL) { |
| 2758 return Error::null(); | 2764 return Error::null(); |
| 2759 } | 2765 } |
| 2760 | 2766 |
| 2761 if (FLAG_verbose_debug) { | 2767 if (FLAG_verbose_debug) { |
| 2762 OS::Print(">>> hit %s breakpoint at %s:%" Pd " " | 2768 OS::Print(">>> hit %s breakpoint at %s:%" Pd " " |
| 2763 "(token %" Pd ") (address %#" Px ")\n", | 2769 "(token %s) (address %#" Px ")\n", |
| 2764 cbpt->IsInternal() ? "internal" : "user", | 2770 cbpt->IsInternal() ? "internal" : "user", |
| 2765 String::Handle(cbpt->SourceUrl()).ToCString(), | 2771 String::Handle(cbpt->SourceUrl()).ToCString(), |
| 2766 cbpt->LineNumber(), | 2772 cbpt->LineNumber(), |
| 2767 cbpt->token_pos(), | 2773 cbpt->token_pos().ToCString(), |
| 2768 top_frame->pc()); | 2774 top_frame->pc()); |
| 2769 } | 2775 } |
| 2770 | 2776 |
| 2771 ASSERT(stack_trace_ == NULL); | 2777 ASSERT(stack_trace_ == NULL); |
| 2772 stack_trace_ = stack_trace; | 2778 stack_trace_ = stack_trace; |
| 2773 SignalPausedEvent(top_frame, bpt_hit); | 2779 SignalPausedEvent(top_frame, bpt_hit); |
| 2774 // When we single step from a user breakpoint, our next stepping | 2780 // When we single step from a user breakpoint, our next stepping |
| 2775 // point will be at the exact same pc. Skip it. | 2781 // point will be at the exact same pc. Skip it. |
| 2776 HandleSteppingRequest(stack_trace_, true /* skip next step */); | 2782 HandleSteppingRequest(stack_trace_, true /* skip next step */); |
| 2777 stack_trace_ = NULL; | 2783 stack_trace_ = NULL; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2836 !ServiceIsolate::IsServiceIsolateDescendant(isolate_)) { | 2842 !ServiceIsolate::IsServiceIsolateDescendant(isolate_)) { |
| 2837 SignalIsolateEvent(DebuggerEvent::kIsolateCreated); | 2843 SignalIsolateEvent(DebuggerEvent::kIsolateCreated); |
| 2838 creation_message_sent_ = true; | 2844 creation_message_sent_ = true; |
| 2839 } | 2845 } |
| 2840 } | 2846 } |
| 2841 | 2847 |
| 2842 | 2848 |
| 2843 // Return innermost closure contained in 'function' that contains | 2849 // Return innermost closure contained in 'function' that contains |
| 2844 // the given token position. | 2850 // the given token position. |
| 2845 RawFunction* Debugger::FindInnermostClosure(const Function& function, | 2851 RawFunction* Debugger::FindInnermostClosure(const Function& function, |
| 2846 intptr_t token_pos) { | 2852 TokenPosition token_pos) { |
| 2847 Zone* zone = Thread::Current()->zone(); | 2853 Zone* zone = Thread::Current()->zone(); |
| 2848 const Script& outer_origin = Script::Handle(zone, function.script()); | 2854 const Script& outer_origin = Script::Handle(zone, function.script()); |
| 2849 const GrowableObjectArray& closures = | 2855 const GrowableObjectArray& closures = |
| 2850 GrowableObjectArray::Handle(zone, | 2856 GrowableObjectArray::Handle(zone, |
| 2851 Isolate::Current()->object_store()->closure_functions()); | 2857 Isolate::Current()->object_store()->closure_functions()); |
| 2852 const intptr_t num_closures = closures.Length(); | 2858 const intptr_t num_closures = closures.Length(); |
| 2853 Function& closure = Function::Handle(zone); | 2859 Function& closure = Function::Handle(zone); |
| 2854 Function& best_fit = Function::Handle(zone); | 2860 Function& best_fit = Function::Handle(zone); |
| 2855 for (intptr_t i = 0; i < num_closures; i++) { | 2861 for (intptr_t i = 0; i < num_closures; i++) { |
| 2856 closure ^= closures.At(i); | 2862 closure ^= closures.At(i); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2901 | 2907 |
| 2902 // TODO(hausner): What should we do if function is optimized? | 2908 // TODO(hausner): What should we do if function is optimized? |
| 2903 // Can we deoptimize the function? | 2909 // Can we deoptimize the function? |
| 2904 ASSERT(!func.HasOptimizedCode()); | 2910 ASSERT(!func.HasOptimizedCode()); |
| 2905 | 2911 |
| 2906 // There is no local function within func that contains the | 2912 // There is no local function within func that contains the |
| 2907 // breakpoint token position. Resolve the breakpoint if necessary | 2913 // breakpoint token position. Resolve the breakpoint if necessary |
| 2908 // and set the code breakpoints. | 2914 // and set the code breakpoints. |
| 2909 if (!loc->IsResolved()) { | 2915 if (!loc->IsResolved()) { |
| 2910 // Resolve source breakpoint in the newly compiled function. | 2916 // Resolve source breakpoint in the newly compiled function. |
| 2911 intptr_t bp_pos = | 2917 TokenPosition bp_pos = |
| 2912 ResolveBreakpointPos(func, loc->token_pos(), loc->end_token_pos(), | 2918 ResolveBreakpointPos(func, loc->token_pos(), loc->end_token_pos(), |
| 2913 loc->requested_column_number()); | 2919 loc->requested_column_number()); |
| 2914 if (!Token::IsDebugPause(bp_pos)) { | 2920 if (!bp_pos.IsDebugPause()) { |
| 2915 if (FLAG_verbose_debug) { | 2921 if (FLAG_verbose_debug) { |
| 2916 OS::Print("Failed resolving breakpoint for function '%s'\n", | 2922 OS::Print("Failed resolving breakpoint for function '%s'\n", |
| 2917 String::Handle(func.name()).ToCString()); | 2923 String::Handle(func.name()).ToCString()); |
| 2918 } | 2924 } |
| 2919 continue; | 2925 continue; |
| 2920 } | 2926 } |
| 2921 intptr_t requested_pos = loc->token_pos(); | 2927 TokenPosition requested_pos = loc->token_pos(); |
| 2922 intptr_t requested_end_pos = loc->end_token_pos(); | 2928 TokenPosition requested_end_pos = loc->end_token_pos(); |
| 2923 loc->SetResolved(func, bp_pos); | 2929 loc->SetResolved(func, bp_pos); |
| 2924 Breakpoint* bpt = loc->breakpoints(); | 2930 Breakpoint* bpt = loc->breakpoints(); |
| 2925 while (bpt != NULL) { | 2931 while (bpt != NULL) { |
| 2926 if (FLAG_verbose_debug) { | 2932 if (FLAG_verbose_debug) { |
| 2927 OS::Print("Resolved BP %" Pd " to pos %" Pd ", " | 2933 OS::Print("Resolved BP %" Pd " to pos %s, " |
| 2928 "line %" Pd " col %" Pd ", " | 2934 "line %" Pd " col %" Pd ", " |
| 2929 "function '%s' (requested range %" Pd "-%" Pd ", " | 2935 "function '%s' (requested range %s-%s, " |
| 2930 "requested col %" Pd ")\n", | 2936 "requested col %" Pd ")\n", |
| 2931 bpt->id(), | 2937 bpt->id(), |
| 2932 loc->token_pos(), | 2938 loc->token_pos().ToCString(), |
| 2933 loc->LineNumber(), | 2939 loc->LineNumber(), |
| 2934 loc->ColumnNumber(), | 2940 loc->ColumnNumber(), |
| 2935 func.ToFullyQualifiedCString(), | 2941 func.ToFullyQualifiedCString(), |
| 2936 requested_pos, | 2942 requested_pos.ToCString(), |
| 2937 requested_end_pos, | 2943 requested_end_pos.ToCString(), |
| 2938 loc->requested_column_number()); | 2944 loc->requested_column_number()); |
| 2939 } | 2945 } |
| 2940 SignalBpResolved(bpt); | 2946 SignalBpResolved(bpt); |
| 2941 SendServiceBreakpointEvent(ServiceEvent::kBreakpointResolved, bpt); | 2947 SendServiceBreakpointEvent(ServiceEvent::kBreakpointResolved, bpt); |
| 2942 bpt = bpt->next(); | 2948 bpt = bpt->next(); |
| 2943 } | 2949 } |
| 2944 } | 2950 } |
| 2945 ASSERT(loc->IsResolved()); | 2951 ASSERT(loc->IsResolved()); |
| 2946 if (FLAG_verbose_debug) { | 2952 if (FLAG_verbose_debug) { |
| 2947 Breakpoint* bpt = loc->breakpoints(); | 2953 Breakpoint* bpt = loc->breakpoints(); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2990 if (prev_loc == NULL) { | 2996 if (prev_loc == NULL) { |
| 2991 latent_locations_ = loc; | 2997 latent_locations_ = loc; |
| 2992 } else { | 2998 } else { |
| 2993 prev_loc->set_next(loc); | 2999 prev_loc->set_next(loc); |
| 2994 } | 3000 } |
| 2995 // Now find the token range at the requested line and make a | 3001 // Now find the token range at the requested line and make a |
| 2996 // new unresolved source breakpoint. | 3002 // new unresolved source breakpoint. |
| 2997 intptr_t line_number = matched_loc->requested_line_number(); | 3003 intptr_t line_number = matched_loc->requested_line_number(); |
| 2998 intptr_t column_number = matched_loc->requested_column_number(); | 3004 intptr_t column_number = matched_loc->requested_column_number(); |
| 2999 ASSERT(line_number >= 0); | 3005 ASSERT(line_number >= 0); |
| 3000 intptr_t first_token_pos, last_token_pos; | 3006 TokenPosition first_token_pos, last_token_pos; |
| 3001 script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos); | 3007 script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos); |
| 3002 if (!Token::IsDebugPause(first_token_pos) || | 3008 if (!first_token_pos.IsDebugPause() || !last_token_pos.IsDebugPause()) { |
| 3003 !Token::IsDebugPause(last_token_pos)) { | |
| 3004 // Script does not contain the given line number or there are no | 3009 // Script does not contain the given line number or there are no |
| 3005 // tokens on the line. Drop the breakpoint silently. | 3010 // tokens on the line. Drop the breakpoint silently. |
| 3006 Breakpoint* bpt = matched_loc->breakpoints(); | 3011 Breakpoint* bpt = matched_loc->breakpoints(); |
| 3007 while (bpt != NULL) { | 3012 while (bpt != NULL) { |
| 3008 if (FLAG_verbose_debug) { | 3013 if (FLAG_verbose_debug) { |
| 3009 OS::Print("No code found at line %" Pd ": " | 3014 OS::Print("No code found at line %" Pd ": " |
| 3010 "dropping latent breakpoint %" Pd " in '%s'\n", | 3015 "dropping latent breakpoint %" Pd " in '%s'\n", |
| 3011 line_number, | 3016 line_number, |
| 3012 bpt->id(), | 3017 bpt->id(), |
| 3013 url.ToCString()); | 3018 url.ToCString()); |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3201 delete temp_bpt; | 3206 delete temp_bpt; |
| 3202 } else { | 3207 } else { |
| 3203 prev_bpt = curr_bpt; | 3208 prev_bpt = curr_bpt; |
| 3204 curr_bpt = curr_bpt->next(); | 3209 curr_bpt = curr_bpt->next(); |
| 3205 } | 3210 } |
| 3206 } | 3211 } |
| 3207 } | 3212 } |
| 3208 | 3213 |
| 3209 | 3214 |
| 3210 BreakpointLocation* Debugger::GetBreakpointLocation(const Script& script, | 3215 BreakpointLocation* Debugger::GetBreakpointLocation(const Script& script, |
| 3211 intptr_t token_pos, | 3216 TokenPosition token_pos, |
| 3212 intptr_t requested_column) { | 3217 intptr_t requested_column) { |
| 3213 BreakpointLocation* bpt = breakpoint_locations_; | 3218 BreakpointLocation* bpt = breakpoint_locations_; |
| 3214 while (bpt != NULL) { | 3219 while (bpt != NULL) { |
| 3215 if ((bpt->script_ == script.raw()) && | 3220 if ((bpt->script_ == script.raw()) && |
| 3216 (bpt->token_pos_ == token_pos) && | 3221 (bpt->token_pos_ == token_pos) && |
| 3217 (bpt->requested_column_number_ == requested_column)) { | 3222 (bpt->requested_column_number_ == requested_column)) { |
| 3218 return bpt; | 3223 return bpt; |
| 3219 } | 3224 } |
| 3220 bpt = bpt->next(); | 3225 bpt = bpt->next(); |
| 3221 } | 3226 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3268 } | 3273 } |
| 3269 | 3274 |
| 3270 | 3275 |
| 3271 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 3276 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
| 3272 ASSERT(bpt->next() == NULL); | 3277 ASSERT(bpt->next() == NULL); |
| 3273 bpt->set_next(code_breakpoints_); | 3278 bpt->set_next(code_breakpoints_); |
| 3274 code_breakpoints_ = bpt; | 3279 code_breakpoints_ = bpt; |
| 3275 } | 3280 } |
| 3276 | 3281 |
| 3277 } // namespace dart | 3282 } // namespace dart |
| OLD | NEW |