| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/debugger.h" | 5 #include "vm/debugger.h" |
| 6 | 6 |
| 7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
| 8 | 8 |
| 9 #include "platform/address_sanitizer.h" | 9 #include "platform/address_sanitizer.h" |
| 10 | 10 |
| (...skipping 1753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1764 Zone* zone = Thread::Current()->zone(); | 1764 Zone* zone = Thread::Current()->zone(); |
| 1765 Script& script = Script::Handle(zone, func.script()); | 1765 Script& script = Script::Handle(zone, func.script()); |
| 1766 Code& code = Code::Handle(zone, func.unoptimized_code()); | 1766 Code& code = Code::Handle(zone, func.unoptimized_code()); |
| 1767 ASSERT(!code.IsNull()); | 1767 ASSERT(!code.IsNull()); |
| 1768 PcDescriptors& desc = PcDescriptors::Handle(zone, code.pc_descriptors()); | 1768 PcDescriptors& desc = PcDescriptors::Handle(zone, code.pc_descriptors()); |
| 1769 | 1769 |
| 1770 // First pass: find the safe point which is closest to the beginning | 1770 // First pass: find the safe point which is closest to the beginning |
| 1771 // of the given token range. | 1771 // of the given token range. |
| 1772 TokenPosition best_fit_pos = TokenPosition::kMaxSource; | 1772 TokenPosition best_fit_pos = TokenPosition::kMaxSource; |
| 1773 intptr_t best_column = INT_MAX; | 1773 intptr_t best_column = INT_MAX; |
| 1774 intptr_t best_line = INT_MAX; |
| 1774 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1775 PcDescriptors::Iterator iter(desc, kSafepointKind); |
| 1775 while (iter.MoveNext()) { | 1776 while (iter.MoveNext()) { |
| 1776 const TokenPosition pos = iter.TokenPos(); | 1777 const TokenPosition pos = iter.TokenPos(); |
| 1777 if ((!pos.IsReal()) || (pos < requested_token_pos) || | 1778 if ((!pos.IsReal()) || (pos < requested_token_pos) || |
| 1778 (pos > last_token_pos)) { | 1779 (pos > last_token_pos)) { |
| 1779 // Token is not in the target range. | 1780 // Token is not in the target range. |
| 1780 continue; | 1781 continue; |
| 1781 } | 1782 } |
| 1782 | 1783 |
| 1783 intptr_t token_start_column = -1; | 1784 intptr_t token_start_column = -1; |
| 1785 intptr_t token_line = -1; |
| 1784 if (requested_column >= 0) { | 1786 if (requested_column >= 0) { |
| 1785 intptr_t ignored = -1; | |
| 1786 intptr_t token_len = -1; | 1787 intptr_t token_len = -1; |
| 1787 // TODO(turnidge): GetTokenLocation is a very expensive | 1788 // TODO(turnidge): GetTokenLocation is a very expensive |
| 1788 // operation, and this code will blow up when we are setting | 1789 // operation, and this code will blow up when we are setting |
| 1789 // column breakpoints on, for example, a large, single-line | 1790 // column breakpoints on, for example, a large, single-line |
| 1790 // program. Consider rewriting this code so that it only scans | 1791 // program. Consider rewriting this code so that it only scans |
| 1791 // the program code once and caches the token positions and | 1792 // the program code once and caches the token positions and |
| 1792 // lengths. | 1793 // lengths. |
| 1793 script.GetTokenLocation(pos, &ignored, &token_start_column, &token_len); | 1794 script.GetTokenLocation(pos, &token_line, &token_start_column, |
| 1795 &token_len); |
| 1794 intptr_t token_end_column = token_start_column + token_len - 1; | 1796 intptr_t token_end_column = token_start_column + token_len - 1; |
| 1795 if ((token_end_column < requested_column) || | 1797 if ((token_end_column < requested_column) || |
| 1796 (token_start_column > best_column)) { | 1798 (token_start_column > best_column)) { |
| 1797 // Prefer the token with the lowest column number compatible | 1799 // Prefer the token with the lowest column number compatible |
| 1798 // with the requested column. | 1800 // with the requested column. |
| 1799 continue; | 1801 continue; |
| 1800 } | 1802 } |
| 1801 } | 1803 } |
| 1802 | 1804 |
| 1803 // Prefer the lowest (first) token pos. | 1805 // Prefer the lowest (first) token pos. |
| 1804 if (pos < best_fit_pos) { | 1806 if (pos < best_fit_pos) { |
| 1805 best_fit_pos = pos; | 1807 best_fit_pos = pos; |
| 1808 best_line = token_line; |
| 1806 best_column = token_start_column; | 1809 best_column = token_start_column; |
| 1807 } | 1810 } |
| 1808 } | 1811 } |
| 1809 | 1812 |
| 1810 // Second pass (if we found a safe point in the first pass). Find | 1813 // Second pass (if we found a safe point in the first pass). Find |
| 1811 // the token on the line which is at the best fit column (if column | 1814 // the token on the line which is at the best fit column (if column |
| 1812 // was specified) and has the lowest code address. | 1815 // was specified) and has the lowest code address. |
| 1813 if (best_fit_pos != TokenPosition::kMaxSource) { | 1816 if (best_fit_pos != TokenPosition::kMaxSource) { |
| 1814 const Script& script = Script::Handle(zone, func.script()); | 1817 const Script& script = Script::Handle(zone, func.script()); |
| 1815 const TokenStream& tokens = TokenStream::Handle(zone, script.tokens()); | |
| 1816 const TokenPosition begin_pos = best_fit_pos; | 1818 const TokenPosition begin_pos = best_fit_pos; |
| 1817 const TokenPosition end_of_line_pos = | 1819 |
| 1818 LastTokenOnLine(zone, tokens, begin_pos); | 1820 TokenPosition end_of_line_pos; |
| 1821 if (script.kind() == RawScript::kKernelTag) { |
| 1822 if (best_line == -1) { |
| 1823 script.GetTokenLocation(begin_pos, &best_line, NULL); |
| 1824 } |
| 1825 ASSERT(best_line > 0); |
| 1826 TokenPosition ignored; |
| 1827 script.TokenRangeAtLine(best_line, &ignored, &end_of_line_pos); |
| 1828 if (end_of_line_pos < begin_pos) { |
| 1829 end_of_line_pos = begin_pos; |
| 1830 } |
| 1831 } else { |
| 1832 const TokenStream& tokens = TokenStream::Handle(zone, script.tokens()); |
| 1833 end_of_line_pos = LastTokenOnLine(zone, tokens, begin_pos); |
| 1834 } |
| 1835 |
| 1819 uword lowest_pc_offset = kUwordMax; | 1836 uword lowest_pc_offset = kUwordMax; |
| 1820 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1837 PcDescriptors::Iterator iter(desc, kSafepointKind); |
| 1821 while (iter.MoveNext()) { | 1838 while (iter.MoveNext()) { |
| 1822 const TokenPosition pos = iter.TokenPos(); | 1839 const TokenPosition pos = iter.TokenPos(); |
| 1823 if (!pos.IsReal() || (pos < begin_pos) || (pos > end_of_line_pos)) { | 1840 if (!pos.IsReal() || (pos < begin_pos) || (pos > end_of_line_pos)) { |
| 1824 // Token is not on same line as best fit. | 1841 // Token is not on same line as best fit. |
| 1825 continue; | 1842 continue; |
| 1826 } | 1843 } |
| 1827 | 1844 |
| 1828 if (requested_column >= 0) { | 1845 if (requested_column >= 0) { |
| (...skipping 1075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2904 | 2921 |
| 2905 | 2922 |
| 2906 bool Debugger::IsAtAsyncJump(ActivationFrame* top_frame) { | 2923 bool Debugger::IsAtAsyncJump(ActivationFrame* top_frame) { |
| 2907 Zone* zone = Thread::Current()->zone(); | 2924 Zone* zone = Thread::Current()->zone(); |
| 2908 Object& closure_or_null = | 2925 Object& closure_or_null = |
| 2909 Object::Handle(zone, top_frame->GetAsyncOperation()); | 2926 Object::Handle(zone, top_frame->GetAsyncOperation()); |
| 2910 if (!closure_or_null.IsNull()) { | 2927 if (!closure_or_null.IsNull()) { |
| 2911 ASSERT(closure_or_null.IsInstance()); | 2928 ASSERT(closure_or_null.IsInstance()); |
| 2912 ASSERT(Instance::Cast(closure_or_null).IsClosure()); | 2929 ASSERT(Instance::Cast(closure_or_null).IsClosure()); |
| 2913 const Script& script = Script::Handle(zone, top_frame->SourceScript()); | 2930 const Script& script = Script::Handle(zone, top_frame->SourceScript()); |
| 2931 if (script.kind() == RawScript::kKernelTag) { |
| 2932 return false; |
| 2933 } |
| 2914 const TokenStream& tokens = TokenStream::Handle(zone, script.tokens()); | 2934 const TokenStream& tokens = TokenStream::Handle(zone, script.tokens()); |
| 2915 TokenStream::Iterator iter(zone, tokens, top_frame->TokenPos()); | 2935 TokenStream::Iterator iter(zone, tokens, top_frame->TokenPos()); |
| 2916 if ((iter.CurrentTokenKind() == Token::kIDENT) && | 2936 if ((iter.CurrentTokenKind() == Token::kIDENT) && |
| 2917 ((iter.CurrentLiteral() == Symbols::Await().raw()) || | 2937 ((iter.CurrentLiteral() == Symbols::Await().raw()) || |
| 2918 (iter.CurrentLiteral() == Symbols::YieldKw().raw()))) { | 2938 (iter.CurrentLiteral() == Symbols::YieldKw().raw()))) { |
| 2919 return true; | 2939 return true; |
| 2920 } | 2940 } |
| 2921 } | 2941 } |
| 2922 return false; | 2942 return false; |
| 2923 } | 2943 } |
| (...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3579 | 3599 |
| 3580 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 3600 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
| 3581 ASSERT(bpt->next() == NULL); | 3601 ASSERT(bpt->next() == NULL); |
| 3582 bpt->set_next(code_breakpoints_); | 3602 bpt->set_next(code_breakpoints_); |
| 3583 code_breakpoints_ = bpt; | 3603 code_breakpoints_ = bpt; |
| 3584 } | 3604 } |
| 3585 | 3605 |
| 3586 #endif // !PRODUCT | 3606 #endif // !PRODUCT |
| 3587 | 3607 |
| 3588 } // namespace dart | 3608 } // namespace dart |
| OLD | NEW |