| 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" |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 end_token_pos_(end_token_pos), | 77 end_token_pos_(end_token_pos), |
| 78 is_resolved_(false), | 78 is_resolved_(false), |
| 79 next_(NULL), | 79 next_(NULL), |
| 80 conditions_(NULL), | 80 conditions_(NULL), |
| 81 requested_line_number_(requested_line_number), | 81 requested_line_number_(requested_line_number), |
| 82 requested_column_number_(requested_column_number), | 82 requested_column_number_(requested_column_number), |
| 83 function_(Function::null()), | 83 function_(Function::null()), |
| 84 line_number_(-1), | 84 line_number_(-1), |
| 85 column_number_(-1) { | 85 column_number_(-1) { |
| 86 ASSERT(!script.IsNull()); | 86 ASSERT(!script.IsNull()); |
| 87 ASSERT(token_pos_ >= 0); | 87 ASSERT(Token::IsReal(token_pos_)); |
| 88 } | 88 } |
| 89 | 89 |
| 90 // Create a latent breakpoint at given url and line number. | 90 // Create a latent breakpoint at given url and line number. |
| 91 BreakpointLocation::BreakpointLocation(const String& url, | 91 BreakpointLocation::BreakpointLocation(const String& url, |
| 92 intptr_t requested_line_number, | 92 intptr_t requested_line_number, |
| 93 intptr_t requested_column_number) | 93 intptr_t requested_column_number) |
| 94 : script_(Script::null()), | 94 : script_(Script::null()), |
| 95 url_(url.raw()), | 95 url_(url.raw()), |
| 96 token_pos_(Scanner::kNoSourcePos), | 96 token_pos_(Token::kNoSourcePos), |
| 97 end_token_pos_(Scanner::kNoSourcePos), | 97 end_token_pos_(Token::kNoSourcePos), |
| 98 is_resolved_(false), | 98 is_resolved_(false), |
| 99 next_(NULL), | 99 next_(NULL), |
| 100 conditions_(NULL), | 100 conditions_(NULL), |
| 101 requested_line_number_(requested_line_number), | 101 requested_line_number_(requested_line_number), |
| 102 requested_column_number_(requested_column_number), | 102 requested_column_number_(requested_column_number), |
| 103 function_(Function::null()), | 103 function_(Function::null()), |
| 104 line_number_(-1), | 104 line_number_(-1), |
| 105 column_number_(-1) { | 105 column_number_(-1) { |
| 106 ASSERT(requested_line_number_ >= 0); | 106 ASSERT(requested_line_number_ >= 0); |
| 107 } | 107 } |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 uword fp, | 232 uword fp, |
| 233 uword sp, | 233 uword sp, |
| 234 const Code& code, | 234 const Code& code, |
| 235 const Array& deopt_frame, | 235 const Array& deopt_frame, |
| 236 intptr_t deopt_frame_offset) | 236 intptr_t deopt_frame_offset) |
| 237 : pc_(pc), fp_(fp), sp_(sp), | 237 : pc_(pc), fp_(fp), sp_(sp), |
| 238 ctx_(Context::ZoneHandle()), | 238 ctx_(Context::ZoneHandle()), |
| 239 code_(Code::ZoneHandle(code.raw())), | 239 code_(Code::ZoneHandle(code.raw())), |
| 240 function_(Function::ZoneHandle(code.function())), | 240 function_(Function::ZoneHandle(code.function())), |
| 241 token_pos_initialized_(false), | 241 token_pos_initialized_(false), |
| 242 token_pos_(Scanner::kNoSourcePos), | 242 token_pos_(Token::kNoSourcePos), |
| 243 try_index_(-1), | 243 try_index_(-1), |
| 244 line_number_(-1), | 244 line_number_(-1), |
| 245 column_number_(-1), | 245 column_number_(-1), |
| 246 context_level_(-1), | 246 context_level_(-1), |
| 247 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())), | 247 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())), |
| 248 deopt_frame_offset_(deopt_frame_offset), | 248 deopt_frame_offset_(deopt_frame_offset), |
| 249 vars_initialized_(false), | 249 vars_initialized_(false), |
| 250 var_descriptors_(LocalVarDescriptors::ZoneHandle()), | 250 var_descriptors_(LocalVarDescriptors::ZoneHandle()), |
| 251 desc_indices_(8), | 251 desc_indices_(8), |
| 252 pc_desc_(PcDescriptors::ZoneHandle()) { | 252 pc_desc_(PcDescriptors::ZoneHandle()) { |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 559 pc_desc_ = code().pc_descriptors(); | 559 pc_desc_ = code().pc_descriptors(); |
| 560 ASSERT(!pc_desc_.IsNull()); | 560 ASSERT(!pc_desc_.IsNull()); |
| 561 } | 561 } |
| 562 } | 562 } |
| 563 | 563 |
| 564 | 564 |
| 565 // Compute token_pos_ and try_index_ and token_pos_initialized_. | 565 // Compute token_pos_ and try_index_ and token_pos_initialized_. |
| 566 intptr_t ActivationFrame::TokenPos() { | 566 intptr_t ActivationFrame::TokenPos() { |
| 567 if (!token_pos_initialized_) { | 567 if (!token_pos_initialized_) { |
| 568 token_pos_initialized_ = true; | 568 token_pos_initialized_ = true; |
| 569 token_pos_ = Scanner::kNoSourcePos; | 569 token_pos_ = Token::kNoSourcePos; |
| 570 GetPcDescriptors(); | 570 GetPcDescriptors(); |
| 571 PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind); | 571 PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind); |
| 572 uword pc_offset = pc_ - code().EntryPoint(); | 572 uword pc_offset = pc_ - code().EntryPoint(); |
| 573 while (iter.MoveNext()) { | 573 while (iter.MoveNext()) { |
| 574 if (iter.PcOffset() == pc_offset) { | 574 if (iter.PcOffset() == pc_offset) { |
| 575 try_index_ = iter.TryIndex(); | 575 try_index_ = iter.TryIndex(); |
| 576 token_pos_ = iter.TokenPos(); | 576 token_pos_ = iter.TokenPos(); |
| 577 break; | 577 break; |
| 578 } | 578 } |
| 579 } | 579 } |
| 580 } | 580 } |
| 581 return token_pos_; | 581 return token_pos_; |
| 582 } | 582 } |
| 583 | 583 |
| 584 | 584 |
| 585 intptr_t ActivationFrame::TryIndex() { | 585 intptr_t ActivationFrame::TryIndex() { |
| 586 if (!token_pos_initialized_) { | 586 if (!token_pos_initialized_) { |
| 587 TokenPos(); // Side effect: computes token_pos_initialized_, try_index_. | 587 TokenPos(); // Side effect: computes token_pos_initialized_, try_index_. |
| 588 } | 588 } |
| 589 return try_index_; | 589 return try_index_; |
| 590 } | 590 } |
| 591 | 591 |
| 592 | 592 |
| 593 intptr_t ActivationFrame::LineNumber() { | 593 intptr_t ActivationFrame::LineNumber() { |
| 594 // Compute line number lazily since it causes scanning of the script. | 594 // Compute line number lazily since it causes scanning of the script. |
| 595 if ((line_number_ < 0) && (TokenPos() >= 0)) { | 595 if ((line_number_ < 0) && Token::IsReal(TokenPos())) { |
| 596 const intptr_t token_pos = TokenPos(); |
| 596 const Script& script = Script::Handle(SourceScript()); | 597 const Script& script = Script::Handle(SourceScript()); |
| 597 script.GetTokenLocation(TokenPos(), &line_number_, NULL); | 598 script.GetTokenLocation(token_pos, &line_number_, NULL); |
| 598 } | 599 } |
| 599 return line_number_; | 600 return line_number_; |
| 600 } | 601 } |
| 601 | 602 |
| 602 | 603 |
| 603 intptr_t ActivationFrame::ColumnNumber() { | 604 intptr_t ActivationFrame::ColumnNumber() { |
| 604 // Compute column number lazily since it causes scanning of the script. | 605 // Compute column number lazily since it causes scanning of the script. |
| 605 if ((column_number_ < 0) && (TokenPos() >= 0)) { | 606 if ((column_number_ < 0) && Token::IsReal(TokenPos())) { |
| 607 const intptr_t token_pos = TokenPos(); |
| 606 const Script& script = Script::Handle(SourceScript()); | 608 const Script& script = Script::Handle(SourceScript()); |
| 607 if (script.HasSource()) { | 609 if (script.HasSource()) { |
| 608 script.GetTokenLocation(TokenPos(), &line_number_, &column_number_); | 610 script.GetTokenLocation(token_pos, &line_number_, &column_number_); |
| 609 } else { | 611 } else { |
| 610 column_number_ = -1; | 612 column_number_ = -1; |
| 611 } | 613 } |
| 612 } | 614 } |
| 613 return column_number_; | 615 return column_number_; |
| 614 } | 616 } |
| 615 | 617 |
| 616 | 618 |
| 617 void ActivationFrame::GetVarDescriptors() { | 619 void ActivationFrame::GetVarDescriptors() { |
| 618 if (var_descriptors_.IsNull()) { | 620 if (var_descriptors_.IsNull()) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 647 // for the code position of the frame? For now say we are at context | 649 // for the code position of the frame? For now say we are at context |
| 648 // level 0. | 650 // level 0. |
| 649 TokenPos(); | 651 TokenPos(); |
| 650 if (token_pos_ == -1) { | 652 if (token_pos_ == -1) { |
| 651 // No PcDescriptor. | 653 // No PcDescriptor. |
| 652 return context_level_; | 654 return context_level_; |
| 653 } | 655 } |
| 654 ASSERT(!pc_desc_.IsNull()); | 656 ASSERT(!pc_desc_.IsNull()); |
| 655 intptr_t innermost_begin_pos = 0; | 657 intptr_t innermost_begin_pos = 0; |
| 656 intptr_t activation_token_pos = TokenPos(); | 658 intptr_t activation_token_pos = TokenPos(); |
| 657 ASSERT(activation_token_pos >= 0); | 659 ASSERT(Token::IsReal(activation_token_pos)); |
| 658 GetVarDescriptors(); | 660 GetVarDescriptors(); |
| 659 intptr_t var_desc_len = var_descriptors_.Length(); | 661 intptr_t var_desc_len = var_descriptors_.Length(); |
| 660 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { | 662 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { |
| 661 RawLocalVarDescriptors::VarInfo var_info; | 663 RawLocalVarDescriptors::VarInfo var_info; |
| 662 var_descriptors_.GetInfo(cur_idx, &var_info); | 664 var_descriptors_.GetInfo(cur_idx, &var_info); |
| 663 const int8_t kind = var_info.kind(); | 665 const int8_t kind = var_info.kind(); |
| 664 if ((kind == RawLocalVarDescriptors::kContextLevel) && | 666 if ((kind == RawLocalVarDescriptors::kContextLevel) && |
| 665 (var_info.begin_pos <= activation_token_pos) && | 667 (var_info.begin_pos <= activation_token_pos) && |
| 666 (activation_token_pos < var_info.end_pos)) { | 668 (activation_token_pos < var_info.end_pos)) { |
| 667 // This var_descriptors_ entry is a context scope which is in scope | 669 // This var_descriptors_ entry is a context scope which is in scope |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 760 } | 762 } |
| 761 | 763 |
| 762 | 764 |
| 763 void ActivationFrame::GetDescIndices() { | 765 void ActivationFrame::GetDescIndices() { |
| 764 if (vars_initialized_) { | 766 if (vars_initialized_) { |
| 765 return; | 767 return; |
| 766 } | 768 } |
| 767 GetVarDescriptors(); | 769 GetVarDescriptors(); |
| 768 | 770 |
| 769 intptr_t activation_token_pos = TokenPos(); | 771 intptr_t activation_token_pos = TokenPos(); |
| 770 if (activation_token_pos < 0) { | 772 if (!Token::IsDebugPause(activation_token_pos)) { |
| 771 // We don't have a token position for this frame, so can't determine | 773 // We don't have a token position for this frame, so can't determine |
| 772 // which variables are visible. | 774 // which variables are visible. |
| 773 vars_initialized_ = true; | 775 vars_initialized_ = true; |
| 774 return; | 776 return; |
| 775 } | 777 } |
| 776 | 778 |
| 777 GrowableArray<String*> var_names(8); | 779 GrowableArray<String*> var_names(8); |
| 778 intptr_t var_desc_len = var_descriptors_.Length(); | 780 intptr_t var_desc_len = var_descriptors_.Length(); |
| 779 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { | 781 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { |
| 780 ASSERT(var_names.length() == desc_indices_.length()); | 782 ASSERT(var_names.length() == desc_indices_.length()); |
| (...skipping 952 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1733 ASSERT(!code.IsNull()); | 1735 ASSERT(!code.IsNull()); |
| 1734 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 1736 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
| 1735 | 1737 |
| 1736 // First pass: find the safe point which is closest to the beginning | 1738 // First pass: find the safe point which is closest to the beginning |
| 1737 // of the given token range. | 1739 // of the given token range. |
| 1738 intptr_t best_fit_pos = INT_MAX; | 1740 intptr_t best_fit_pos = INT_MAX; |
| 1739 intptr_t best_column = INT_MAX; | 1741 intptr_t best_column = INT_MAX; |
| 1740 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1742 PcDescriptors::Iterator iter(desc, kSafepointKind); |
| 1741 while (iter.MoveNext()) { | 1743 while (iter.MoveNext()) { |
| 1742 const intptr_t pos = iter.TokenPos(); | 1744 const intptr_t pos = iter.TokenPos(); |
| 1743 if ((pos < 0) || | 1745 if ((!Token::IsReal(pos)) || |
| 1744 (pos < requested_token_pos) || | 1746 (pos < requested_token_pos) || |
| 1745 (pos > last_token_pos)) { | 1747 (pos > last_token_pos)) { |
| 1746 // Token is not in the target range. | 1748 // Token is not in the target range. |
| 1747 continue; | 1749 continue; |
| 1748 } | 1750 } |
| 1749 | 1751 |
| 1750 intptr_t token_start_column = -1; | 1752 intptr_t token_start_column = -1; |
| 1751 if (requested_column >= 0) { | 1753 if (requested_column >= 0) { |
| 1752 intptr_t ignored = -1; | 1754 intptr_t ignored = -1; |
| 1753 intptr_t token_len = -1; | 1755 intptr_t token_len = -1; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1779 // was specified) and has the lowest code address. | 1781 // was specified) and has the lowest code address. |
| 1780 if (best_fit_pos != INT_MAX) { | 1782 if (best_fit_pos != INT_MAX) { |
| 1781 const Script& script = Script::Handle(func.script()); | 1783 const Script& script = Script::Handle(func.script()); |
| 1782 const TokenStream& tokens = TokenStream::Handle(script.tokens()); | 1784 const TokenStream& tokens = TokenStream::Handle(script.tokens()); |
| 1783 const intptr_t begin_pos = best_fit_pos; | 1785 const intptr_t begin_pos = best_fit_pos; |
| 1784 const intptr_t end_of_line_pos = LastTokenOnLine(tokens, begin_pos); | 1786 const intptr_t end_of_line_pos = LastTokenOnLine(tokens, begin_pos); |
| 1785 uword lowest_pc_offset = kUwordMax; | 1787 uword lowest_pc_offset = kUwordMax; |
| 1786 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1788 PcDescriptors::Iterator iter(desc, kSafepointKind); |
| 1787 while (iter.MoveNext()) { | 1789 while (iter.MoveNext()) { |
| 1788 const intptr_t pos = iter.TokenPos(); | 1790 const intptr_t pos = iter.TokenPos(); |
| 1789 if ((pos < 0) || | 1791 if ((!Token::IsReal(pos)) || |
| 1790 (pos < begin_pos) || | 1792 (pos < begin_pos) || |
| 1791 (pos > end_of_line_pos)) { | 1793 (pos > end_of_line_pos)) { |
| 1792 // Token is not on same line as best fit. | 1794 // Token is not on same line as best fit. |
| 1793 continue; | 1795 continue; |
| 1794 } | 1796 } |
| 1795 | 1797 |
| 1796 if (requested_column >= 0) { | 1798 if (requested_column >= 0) { |
| 1797 intptr_t ignored = -1; | 1799 intptr_t ignored = -1; |
| 1798 intptr_t token_start_column = -1; | 1800 intptr_t token_start_column = -1; |
| 1799 // We look for other tokens at the best column in case there | 1801 // We look for other tokens at the best column in case there |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1814 } | 1816 } |
| 1815 | 1817 |
| 1816 // We didn't find a safe point in the given token range. Try and | 1818 // We didn't find a safe point in the given token range. Try and |
| 1817 // find a safe point in the remaining source code of the function. | 1819 // find a safe point in the remaining source code of the function. |
| 1818 // Since we have moved to the next line of the function, we no | 1820 // Since we have moved to the next line of the function, we no |
| 1819 // longer are requesting a specific column number. | 1821 // longer are requesting a specific column number. |
| 1820 if (last_token_pos < func.end_token_pos()) { | 1822 if (last_token_pos < func.end_token_pos()) { |
| 1821 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos(), | 1823 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos(), |
| 1822 -1 /* no column */); | 1824 -1 /* no column */); |
| 1823 } | 1825 } |
| 1824 return -1; | 1826 return Token::kNoSourcePos; |
| 1825 } | 1827 } |
| 1826 | 1828 |
| 1827 | 1829 |
| 1828 void Debugger::MakeCodeBreakpointAt(const Function& func, | 1830 void Debugger::MakeCodeBreakpointAt(const Function& func, |
| 1829 BreakpointLocation* loc) { | 1831 BreakpointLocation* loc) { |
| 1830 ASSERT(loc->token_pos_ >= 0); | 1832 ASSERT(Token::IsReal(loc->token_pos_)); |
| 1831 ASSERT((loc != NULL) && loc->IsResolved()); | 1833 ASSERT((loc != NULL) && loc->IsResolved()); |
| 1832 ASSERT(!func.HasOptimizedCode()); | 1834 ASSERT(!func.HasOptimizedCode()); |
| 1833 Code& code = Code::Handle(func.unoptimized_code()); | 1835 Code& code = Code::Handle(func.unoptimized_code()); |
| 1834 ASSERT(!code.IsNull()); | 1836 ASSERT(!code.IsNull()); |
| 1835 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 1837 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
| 1836 uword lowest_pc_offset = kUwordMax; | 1838 uword lowest_pc_offset = kUwordMax; |
| 1837 RawPcDescriptors::Kind lowest_kind = RawPcDescriptors::kAnyKind; | 1839 RawPcDescriptors::Kind lowest_kind = RawPcDescriptors::kAnyKind; |
| 1838 // Find the safe point with the lowest compiled code address | 1840 // Find the safe point with the lowest compiled code address |
| 1839 // that maps to the token position of the source breakpoint. | 1841 // that maps to the token position of the source breakpoint. |
| 1840 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1842 PcDescriptors::Iterator iter(desc, kSafepointKind); |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2235 } | 2237 } |
| 2236 if (scripts.Length() > 1) { | 2238 if (scripts.Length() > 1) { |
| 2237 if (FLAG_verbose_debug) { | 2239 if (FLAG_verbose_debug) { |
| 2238 OS::Print("Multiple scripts match url '%s'\n", script_url.ToCString()); | 2240 OS::Print("Multiple scripts match url '%s'\n", script_url.ToCString()); |
| 2239 } | 2241 } |
| 2240 return NULL; | 2242 return NULL; |
| 2241 } | 2243 } |
| 2242 script ^= scripts.At(0); | 2244 script ^= scripts.At(0); |
| 2243 intptr_t first_token_idx, last_token_idx; | 2245 intptr_t first_token_idx, last_token_idx; |
| 2244 script.TokenRangeAtLine(line_number, &first_token_idx, &last_token_idx); | 2246 script.TokenRangeAtLine(line_number, &first_token_idx, &last_token_idx); |
| 2245 if (first_token_idx < 0) { | 2247 if (!Token::IsReal(first_token_idx)) { |
| 2246 // Script does not contain the given line number. | 2248 // Script does not contain the given line number. |
| 2247 if (FLAG_verbose_debug) { | 2249 if (FLAG_verbose_debug) { |
| 2248 OS::Print("Script '%s' does not contain line number %" Pd "\n", | 2250 OS::Print("Script '%s' does not contain line number %" Pd "\n", |
| 2249 script_url.ToCString(), line_number); | 2251 script_url.ToCString(), line_number); |
| 2250 } | 2252 } |
| 2251 return NULL; | 2253 return NULL; |
| 2252 } else if (last_token_idx < 0) { | 2254 } else if (!Token::IsReal(last_token_idx)) { |
| 2253 // Line does not contain any tokens. | 2255 // Line does not contain any tokens. |
| 2254 if (FLAG_verbose_debug) { | 2256 if (FLAG_verbose_debug) { |
| 2255 OS::Print("No executable code at line %" Pd " in '%s'\n", | 2257 OS::Print("No executable code at line %" Pd " in '%s'\n", |
| 2256 line_number, script_url.ToCString()); | 2258 line_number, script_url.ToCString()); |
| 2257 } | 2259 } |
| 2258 return NULL; | 2260 return NULL; |
| 2259 } | 2261 } |
| 2260 | 2262 |
| 2261 BreakpointLocation* bpt = NULL; | 2263 BreakpointLocation* bpt = NULL; |
| 2262 ASSERT(first_token_idx <= last_token_idx); | 2264 ASSERT(first_token_idx <= last_token_idx); |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2534 void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace) { | 2536 void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace) { |
| 2535 stepping_fp_ = 0; | 2537 stepping_fp_ = 0; |
| 2536 if (resume_action_ == kSingleStep) { | 2538 if (resume_action_ == kSingleStep) { |
| 2537 // When single stepping, we need to deoptimize because we might be | 2539 // When single stepping, we need to deoptimize because we might be |
| 2538 // stepping into optimized code. This happens in particular if | 2540 // stepping into optimized code. This happens in particular if |
| 2539 // the isolate has been interrupted, but can happen in other cases | 2541 // the isolate has been interrupted, but can happen in other cases |
| 2540 // as well. We need to deoptimize the world in case we are about | 2542 // as well. We need to deoptimize the world in case we are about |
| 2541 // to call an optimized function. | 2543 // to call an optimized function. |
| 2542 DeoptimizeWorld(); | 2544 DeoptimizeWorld(); |
| 2543 isolate_->set_single_step(true); | 2545 isolate_->set_single_step(true); |
| 2546 if (FLAG_verbose_debug) { |
| 2547 OS::Print("HandleSteppingRequest- kSingleStep\n"); |
| 2548 } |
| 2544 } else if (resume_action_ == kStepOver) { | 2549 } else if (resume_action_ == kStepOver) { |
| 2545 DeoptimizeWorld(); | 2550 DeoptimizeWorld(); |
| 2546 isolate_->set_single_step(true); | 2551 isolate_->set_single_step(true); |
| 2547 ASSERT(stack_trace->Length() > 0); | 2552 ASSERT(stack_trace->Length() > 0); |
| 2548 stepping_fp_ = stack_trace->FrameAt(0)->fp(); | 2553 stepping_fp_ = stack_trace->FrameAt(0)->fp(); |
| 2554 if (FLAG_verbose_debug) { |
| 2555 OS::Print("HandleSteppingRequest- kStepOver %" Px "\n", stepping_fp_); |
| 2556 } |
| 2549 } else if (resume_action_ == kStepOut) { | 2557 } else if (resume_action_ == kStepOut) { |
| 2550 DeoptimizeWorld(); | 2558 DeoptimizeWorld(); |
| 2551 isolate_->set_single_step(true); | 2559 isolate_->set_single_step(true); |
| 2552 // Find topmost caller that is debuggable. | 2560 // Find topmost caller that is debuggable. |
| 2553 for (intptr_t i = 1; i < stack_trace->Length(); i++) { | 2561 for (intptr_t i = 1; i < stack_trace->Length(); i++) { |
| 2554 ActivationFrame* frame = stack_trace->FrameAt(i); | 2562 ActivationFrame* frame = stack_trace->FrameAt(i); |
| 2555 if (frame->IsDebuggable()) { | 2563 if (frame->IsDebuggable()) { |
| 2556 stepping_fp_ = frame->fp(); | 2564 stepping_fp_ = frame->fp(); |
| 2557 break; | 2565 break; |
| 2558 } | 2566 } |
| 2559 } | 2567 } |
| 2568 if (FLAG_verbose_debug) { |
| 2569 OS::Print("HandleSteppingRequest- kStepOut %" Px "\n", stepping_fp_); |
| 2570 } |
| 2560 } | 2571 } |
| 2561 } | 2572 } |
| 2562 | 2573 |
| 2563 | 2574 |
| 2564 // static | 2575 // static |
| 2565 bool Debugger::IsDebuggable(const Function& func) { | 2576 bool Debugger::IsDebuggable(const Function& func) { |
| 2566 if (!func.is_debuggable()) { | 2577 if (!func.is_debuggable()) { |
| 2567 return false; | 2578 return false; |
| 2568 } | 2579 } |
| 2569 if (ServiceIsolate::IsRunning()) { | 2580 if (ServiceIsolate::IsRunning()) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2634 // We returned from the "interesting frame", there can be no more | 2645 // We returned from the "interesting frame", there can be no more |
| 2635 // stepping breaks for it. Pause at the next appropriate location | 2646 // stepping breaks for it. Pause at the next appropriate location |
| 2636 // and let the user set the "interesting" frame again. | 2647 // and let the user set the "interesting" frame again. |
| 2637 stepping_fp_ = 0; | 2648 stepping_fp_ = 0; |
| 2638 } | 2649 } |
| 2639 } | 2650 } |
| 2640 | 2651 |
| 2641 if (!frame->IsDebuggable()) { | 2652 if (!frame->IsDebuggable()) { |
| 2642 return Error::null(); | 2653 return Error::null(); |
| 2643 } | 2654 } |
| 2644 if (frame->TokenPos() < 0) { | 2655 if (!Token::IsDebugPause(frame->TokenPos())) { |
| 2645 return Error::null(); | 2656 return Error::null(); |
| 2646 } | 2657 } |
| 2647 | 2658 |
| 2648 // Don't pause for a single step if there is a breakpoint set | 2659 // Don't pause for a single step if there is a breakpoint set |
| 2649 // at this location. | 2660 // at this location. |
| 2650 if (HasActiveBreakpoint(frame->pc())) { | 2661 if (HasActiveBreakpoint(frame->pc())) { |
| 2651 return Error::null(); | 2662 return Error::null(); |
| 2652 } | 2663 } |
| 2653 | 2664 |
| 2654 if (FLAG_verbose_debug) { | 2665 if (FLAG_verbose_debug) { |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2879 ASSERT(!func.HasOptimizedCode()); | 2890 ASSERT(!func.HasOptimizedCode()); |
| 2880 | 2891 |
| 2881 // There is no local function within func that contains the | 2892 // There is no local function within func that contains the |
| 2882 // breakpoint token position. Resolve the breakpoint if necessary | 2893 // breakpoint token position. Resolve the breakpoint if necessary |
| 2883 // and set the code breakpoints. | 2894 // and set the code breakpoints. |
| 2884 if (!loc->IsResolved()) { | 2895 if (!loc->IsResolved()) { |
| 2885 // Resolve source breakpoint in the newly compiled function. | 2896 // Resolve source breakpoint in the newly compiled function. |
| 2886 intptr_t bp_pos = | 2897 intptr_t bp_pos = |
| 2887 ResolveBreakpointPos(func, loc->token_pos(), loc->end_token_pos(), | 2898 ResolveBreakpointPos(func, loc->token_pos(), loc->end_token_pos(), |
| 2888 loc->requested_column_number()); | 2899 loc->requested_column_number()); |
| 2889 if (bp_pos < 0) { | 2900 if (!Token::IsDebugPause(bp_pos)) { |
| 2890 if (FLAG_verbose_debug) { | 2901 if (FLAG_verbose_debug) { |
| 2891 OS::Print("Failed resolving breakpoint for function '%s'\n", | 2902 OS::Print("Failed resolving breakpoint for function '%s'\n", |
| 2892 String::Handle(func.name()).ToCString()); | 2903 String::Handle(func.name()).ToCString()); |
| 2893 } | 2904 } |
| 2894 continue; | 2905 continue; |
| 2895 } | 2906 } |
| 2896 intptr_t requested_pos = loc->token_pos(); | 2907 intptr_t requested_pos = loc->token_pos(); |
| 2897 intptr_t requested_end_pos = loc->end_token_pos(); | 2908 intptr_t requested_end_pos = loc->end_token_pos(); |
| 2898 loc->SetResolved(func, bp_pos); | 2909 loc->SetResolved(func, bp_pos); |
| 2899 Breakpoint* bpt = loc->breakpoints(); | 2910 Breakpoint* bpt = loc->breakpoints(); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2967 } else { | 2978 } else { |
| 2968 prev_loc->set_next(loc); | 2979 prev_loc->set_next(loc); |
| 2969 } | 2980 } |
| 2970 // Now find the token range at the requested line and make a | 2981 // Now find the token range at the requested line and make a |
| 2971 // new unresolved source breakpoint. | 2982 // new unresolved source breakpoint. |
| 2972 intptr_t line_number = matched_loc->requested_line_number(); | 2983 intptr_t line_number = matched_loc->requested_line_number(); |
| 2973 intptr_t column_number = matched_loc->requested_column_number(); | 2984 intptr_t column_number = matched_loc->requested_column_number(); |
| 2974 ASSERT(line_number >= 0); | 2985 ASSERT(line_number >= 0); |
| 2975 intptr_t first_token_pos, last_token_pos; | 2986 intptr_t first_token_pos, last_token_pos; |
| 2976 script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos); | 2987 script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos); |
| 2977 if ((first_token_pos < 0) || | 2988 if (!Token::IsDebugPause(first_token_pos) || |
| 2978 (last_token_pos < 0)) { | 2989 !Token::IsDebugPause(last_token_pos)) { |
| 2979 // Script does not contain the given line number or there are no | 2990 // Script does not contain the given line number or there are no |
| 2980 // tokens on the line. Drop the breakpoint silently. | 2991 // tokens on the line. Drop the breakpoint silently. |
| 2981 Breakpoint* bpt = matched_loc->breakpoints(); | 2992 Breakpoint* bpt = matched_loc->breakpoints(); |
| 2982 while (bpt != NULL) { | 2993 while (bpt != NULL) { |
| 2983 if (FLAG_verbose_debug) { | 2994 if (FLAG_verbose_debug) { |
| 2984 OS::Print("No code found at line %" Pd ": " | 2995 OS::Print("No code found at line %" Pd ": " |
| 2985 "dropping latent breakpoint %" Pd " in '%s'\n", | 2996 "dropping latent breakpoint %" Pd " in '%s'\n", |
| 2986 line_number, | 2997 line_number, |
| 2987 bpt->id(), | 2998 bpt->id(), |
| 2988 url.ToCString()); | 2999 url.ToCString()); |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3243 } | 3254 } |
| 3244 | 3255 |
| 3245 | 3256 |
| 3246 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 3257 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
| 3247 ASSERT(bpt->next() == NULL); | 3258 ASSERT(bpt->next() == NULL); |
| 3248 bpt->set_next(code_breakpoints_); | 3259 bpt->set_next(code_breakpoints_); |
| 3249 code_breakpoints_ = bpt; | 3260 code_breakpoints_ = bpt; |
| 3250 } | 3261 } |
| 3251 | 3262 |
| 3252 } // namespace dart | 3263 } // namespace dart |
| OLD | NEW |