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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
58 private: | 58 private: |
59 GrowableObjectArray* objs_; | 59 GrowableObjectArray* objs_; |
60 | 60 |
61 DISALLOW_COPY_AND_ASSIGN(RemoteObjectCache); | 61 DISALLOW_COPY_AND_ASSIGN(RemoteObjectCache); |
62 }; | 62 }; |
63 | 63 |
64 | 64 |
65 // Create an unresolved breakpoint in given token range and script. | 65 // Create an unresolved breakpoint in given token range and script. |
66 BreakpointLocation::BreakpointLocation(const Script& script, | 66 BreakpointLocation::BreakpointLocation(const Script& script, |
67 intptr_t token_pos, | 67 intptr_t token_pos, |
68 intptr_t end_token_pos) | 68 intptr_t end_token_pos, |
69 intptr_t requested_column_number) | |
69 : script_(script.raw()), | 70 : script_(script.raw()), |
70 url_(script.url()), | 71 url_(script.url()), |
71 token_pos_(token_pos), | 72 token_pos_(token_pos), |
72 end_token_pos_(end_token_pos), | 73 end_token_pos_(end_token_pos), |
73 is_resolved_(false), | 74 is_resolved_(false), |
74 next_(NULL), | 75 next_(NULL), |
75 conditions_(NULL), | 76 conditions_(NULL), |
77 requested_line_number_(-1), | |
78 requested_column_number_(requested_column_number), | |
76 function_(Function::null()), | 79 function_(Function::null()), |
77 line_number_(-1) { | 80 line_number_(-1), |
81 column_number_(-1) { | |
78 ASSERT(!script.IsNull()); | 82 ASSERT(!script.IsNull()); |
79 ASSERT(token_pos_ >= 0); | 83 ASSERT(token_pos_ >= 0); |
80 } | 84 } |
81 | 85 |
82 // Create a latent breakpoint at given url and line number. | 86 // Create a latent breakpoint at given url and line number. |
83 BreakpointLocation::BreakpointLocation(const String& url, | 87 BreakpointLocation::BreakpointLocation(const String& url, |
84 intptr_t line_number) | 88 intptr_t requested_line_number, |
89 intptr_t requested_column_number) | |
85 : script_(Script::null()), | 90 : script_(Script::null()), |
86 url_(url.raw()), | 91 url_(url.raw()), |
87 token_pos_(-1), | 92 token_pos_(-1), |
88 end_token_pos_(-1), | 93 end_token_pos_(-1), |
89 is_resolved_(false), | 94 is_resolved_(false), |
90 next_(NULL), | 95 next_(NULL), |
91 conditions_(NULL), | 96 conditions_(NULL), |
97 requested_line_number_(requested_line_number), | |
98 requested_column_number_(requested_column_number), | |
92 function_(Function::null()), | 99 function_(Function::null()), |
93 line_number_(line_number) { | 100 line_number_(-1), |
101 column_number_(-1) { | |
94 ASSERT(line_number_ >= 0); | 102 ASSERT(line_number_ >= 0); |
hausner
2015/09/03 00:37:50
This assert would fire right away, since the field
turnidge
2015/09/04 18:05:29
Thanks. I have added a set of tests for latent br
| |
95 } | 103 } |
96 | 104 |
97 | 105 |
98 BreakpointLocation::~BreakpointLocation() { | 106 BreakpointLocation::~BreakpointLocation() { |
99 Breakpoint* bpt = breakpoints(); | 107 Breakpoint* bpt = breakpoints(); |
100 while (bpt != NULL) { | 108 while (bpt != NULL) { |
101 Breakpoint* temp = bpt; | 109 Breakpoint* temp = bpt; |
102 bpt = bpt->next(); | 110 bpt = bpt->next(); |
103 delete temp; | 111 delete temp; |
104 } | 112 } |
105 } | 113 } |
106 | 114 |
107 | 115 |
108 bool BreakpointLocation::AnyEnabled() const { | 116 bool BreakpointLocation::AnyEnabled() const { |
109 return breakpoints() != NULL; | 117 return breakpoints() != NULL; |
110 } | 118 } |
111 | 119 |
112 | 120 |
113 void BreakpointLocation::SetResolved(const Function& func, intptr_t token_pos) { | 121 void BreakpointLocation::SetResolved(const Function& func, intptr_t token_pos) { |
114 ASSERT(!IsLatent()); | 122 ASSERT(!IsLatent()); |
115 ASSERT(func.script() == script_); | 123 ASSERT(func.script() == script_); |
116 ASSERT((func.token_pos() <= token_pos) && | 124 ASSERT((func.token_pos() <= token_pos) && |
117 (token_pos <= func.end_token_pos())); | 125 (token_pos <= func.end_token_pos())); |
118 ASSERT(func.is_debuggable()); | 126 ASSERT(func.is_debuggable()); |
119 function_ = func.raw(); | 127 function_ = func.raw(); |
120 token_pos_ = token_pos; | 128 token_pos_ = token_pos; |
121 end_token_pos_ = token_pos; | 129 end_token_pos_ = token_pos; |
122 line_number_ = -1; // Recalculate lazily. | |
hausner
2015/09/03 00:37:50
Why is it not necessary to recalculate the line nu
turnidge
2015/09/04 18:05:29
After my change, the line number before resolution
| |
123 is_resolved_ = true; | 130 is_resolved_ = true; |
124 } | 131 } |
125 | 132 |
126 | 133 |
127 // TODO(hausner): Get rid of library parameter. A source breakpoint location | 134 // TODO(hausner): Get rid of library parameter. A source breakpoint location |
128 // does not imply a library, since the same source code can be included | 135 // does not imply a library, since the same source code can be included |
129 // in more than one library, e.g. the text location of mixin functions. | 136 // in more than one library, e.g. the text location of mixin functions. |
130 void BreakpointLocation::GetCodeLocation(Library* lib, | 137 void BreakpointLocation::GetCodeLocation(Library* lib, |
131 Script* script, | 138 Script* script, |
132 intptr_t* pos) { | 139 intptr_t* pos) { |
(...skipping 10 matching lines...) Expand all Loading... | |
143 const Class& cls = Class::Handle(func.origin()); | 150 const Class& cls = Class::Handle(func.origin()); |
144 *lib = cls.library(); | 151 *lib = cls.library(); |
145 } else { | 152 } else { |
146 *lib = Library::null(); | 153 *lib = Library::null(); |
147 } | 154 } |
148 } | 155 } |
149 } | 156 } |
150 | 157 |
151 | 158 |
152 intptr_t BreakpointLocation::LineNumber() { | 159 intptr_t BreakpointLocation::LineNumber() { |
153 // Latent breakpoints must have a requested line number >= 0. | 160 ASSERT(IsResolved()); |
154 ASSERT(!IsLatent() || line_number_ >= 0); | |
155 // Compute line number lazily since it causes scanning of the script. | 161 // Compute line number lazily since it causes scanning of the script. |
156 if (line_number_ < 0) { | 162 if (line_number_ < 0) { |
157 const Script& script = Script::Handle(this->script()); | 163 const Script& script = Script::Handle(this->script()); |
158 script.GetTokenLocation(token_pos_, &line_number_, NULL); | 164 script.GetTokenLocation(token_pos_, &line_number_, NULL); |
159 } | 165 } |
160 return line_number_; | 166 return line_number_; |
161 } | 167 } |
162 | 168 |
163 | 169 |
170 intptr_t BreakpointLocation::ColumnNumber() { | |
171 ASSERT(IsResolved()); | |
172 // Compute column number lazily since it causes scanning of the script. | |
173 if (column_number_ < 0) { | |
174 const Script& script = Script::Handle(this->script()); | |
175 script.GetTokenLocation(token_pos_, &line_number_, &column_number_); | |
176 } | |
177 return column_number_; | |
178 } | |
179 | |
180 | |
164 void Breakpoint::set_bpt_location(BreakpointLocation* new_bpt_location) { | 181 void Breakpoint::set_bpt_location(BreakpointLocation* new_bpt_location) { |
165 ASSERT(bpt_location_->IsLatent()); // Only reason to move. | 182 ASSERT(bpt_location_->IsLatent()); // Only reason to move. |
166 bpt_location_ = new_bpt_location; | 183 bpt_location_ = new_bpt_location; |
167 } | 184 } |
168 | 185 |
169 | 186 |
170 void Breakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 187 void Breakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
171 visitor->VisitPointer(reinterpret_cast<RawObject**>(&closure_)); | 188 visitor->VisitPointer(reinterpret_cast<RawObject**>(&closure_)); |
172 } | 189 } |
173 | 190 |
(...skipping 1424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1598 last_pos = iter.CurrentPosition(); | 1615 last_pos = iter.CurrentPosition(); |
1599 iter.Advance(); | 1616 iter.Advance(); |
1600 } | 1617 } |
1601 return last_pos; | 1618 return last_pos; |
1602 } | 1619 } |
1603 | 1620 |
1604 | 1621 |
1605 // Given a function and a token range, return the best fit | 1622 // Given a function and a token range, return the best fit |
1606 // token position to set a breakpoint. The best fit is the safe point | 1623 // token position to set a breakpoint. The best fit is the safe point |
1607 // in the line closest to the beginning of the token range, and within | 1624 // in the line closest to the beginning of the token range, and within |
1608 // that line, the safe point with the lowest compiled code address. | 1625 // that line, the safe point with the lowest compiled code address. |
hausner
2015/09/03 00:37:50
Update the comment to describe how the requested c
turnidge
2015/09/04 18:05:29
I updated this comment. It turns out that, given
| |
1609 intptr_t Debugger::ResolveBreakpointPos(const Function& func, | 1626 intptr_t Debugger::ResolveBreakpointPos(const Function& func, |
1610 intptr_t requested_token_pos, | 1627 intptr_t requested_token_pos, |
1611 intptr_t last_token_pos) { | 1628 intptr_t last_token_pos, |
1629 intptr_t requested_column) { | |
1612 ASSERT(func.HasCode()); | 1630 ASSERT(func.HasCode()); |
1613 ASSERT(!func.HasOptimizedCode()); | 1631 ASSERT(!func.HasOptimizedCode()); |
1614 | 1632 |
1615 if (requested_token_pos < func.token_pos()) { | 1633 if (requested_token_pos < func.token_pos()) { |
1616 requested_token_pos = func.token_pos(); | 1634 requested_token_pos = func.token_pos(); |
1617 } | 1635 } |
1618 if (last_token_pos > func.end_token_pos()) { | 1636 if (last_token_pos > func.end_token_pos()) { |
1619 last_token_pos = func.end_token_pos(); | 1637 last_token_pos = func.end_token_pos(); |
1620 } | 1638 } |
1621 | 1639 |
1640 Script& script = Script::Handle(func.script()); | |
1622 Code& code = Code::Handle(func.unoptimized_code()); | 1641 Code& code = Code::Handle(func.unoptimized_code()); |
1623 ASSERT(!code.IsNull()); | 1642 ASSERT(!code.IsNull()); |
1624 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 1643 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
1625 | 1644 |
1626 // First pass: find the safe point which is closest to the beginning | 1645 // First pass: find the safe point which is closest to the beginning |
1627 // of the given token range. | 1646 // of the given token range. |
1628 intptr_t best_fit_pos = INT_MAX; | 1647 intptr_t best_fit_pos = INT_MAX; |
1648 intptr_t best_column = INT_MAX; | |
1629 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1649 PcDescriptors::Iterator iter(desc, kSafepointKind); |
1630 while (iter.MoveNext()) { | 1650 while (iter.MoveNext()) { |
1631 const intptr_t desc_token_pos = iter.TokenPos(); | 1651 const intptr_t pos = iter.TokenPos(); |
1632 if ((desc_token_pos != Scanner::kNoSourcePos) && | 1652 if ((pos == Scanner::kNoSourcePos) || |
1633 (desc_token_pos < best_fit_pos) && | 1653 (pos < requested_token_pos) || |
1634 (desc_token_pos >= requested_token_pos) && | 1654 (pos > last_token_pos)) { |
1635 (desc_token_pos <= last_token_pos)) { | 1655 // Token is not in the target range. |
1636 best_fit_pos = desc_token_pos; | 1656 continue; |
1657 } | |
1658 | |
1659 intptr_t token_start_column = -1; | |
1660 if (requested_column >= 0) { | |
hausner
2015/09/03 00:37:50
Do I understand this code right:
If the caller re
turnidge
2015/09/04 18:05:29
There is a kind of logic to the current implementa
| |
1661 intptr_t ignored = -1; | |
1662 intptr_t token_len = -1; | |
1663 script.GetTokenLocation(pos, &ignored, &token_start_column, &token_len); | |
hausner
2015/09/03 00:37:50
GetTokenLocation is a really expensive operation,
turnidge
2015/09/04 18:05:29
I agree. I have added a TODO/comment about this.
| |
1664 intptr_t token_end_column = token_start_column + token_len - 1; | |
1665 if ((token_end_column < requested_column) || | |
1666 (token_start_column > best_column)) { | |
1667 // Prefer the token with the lowest column number over the | |
1668 // requested column. | |
1669 continue; | |
1670 } | |
1671 } | |
1672 | |
1673 // Prefer the lowest (first) token pos. | |
1674 if (pos < best_fit_pos) { | |
1675 best_fit_pos = pos; | |
1676 best_column = token_start_column; | |
1637 } | 1677 } |
1638 } | 1678 } |
1679 | |
1639 // Second pass (if we found a safe point in the first pass): | 1680 // Second pass (if we found a safe point in the first pass): |
1640 // For all token positions on the same line, select the one | 1681 // For all token positions on the same line, select the one |
1641 // with the lowest compiled code address. E.g., in a line with | 1682 // with the lowest compiled code address. E.g., in a line with |
1642 // the nested function calls f(g(x)), the call g() will have a lower | 1683 // the nested function calls f(g(x)), the call g() will have a lower |
1643 // compiled code address but is not the lowest token position in the | 1684 // compiled code address but is not the lowest token position in the |
hausner
2015/09/03 00:37:50
Could you please update the comment to include the
turnidge
2015/09/04 18:05:29
Done.
| |
1644 // line. | 1685 // line. |
1645 if (best_fit_pos != INT_MAX) { | 1686 if (best_fit_pos != INT_MAX) { |
1646 const Script& script = Script::Handle(func.script()); | 1687 const Script& script = Script::Handle(func.script()); |
1647 const TokenStream& tokens = TokenStream::Handle(script.tokens()); | 1688 const TokenStream& tokens = TokenStream::Handle(script.tokens()); |
1648 const intptr_t begin_pos = best_fit_pos; | 1689 const intptr_t begin_pos = best_fit_pos; |
1649 const intptr_t end_of_line_pos = LastTokenOnLine(tokens, begin_pos); | 1690 const intptr_t end_of_line_pos = LastTokenOnLine(tokens, begin_pos); |
1650 uword lowest_pc_offset = kUwordMax; | 1691 uword lowest_pc_offset = kUwordMax; |
1651 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1692 PcDescriptors::Iterator iter(desc, kSafepointKind); |
1652 while (iter.MoveNext()) { | 1693 while (iter.MoveNext()) { |
1653 const intptr_t pos = iter.TokenPos(); | 1694 const intptr_t pos = iter.TokenPos(); |
1654 if ((pos != Scanner::kNoSourcePos) && | 1695 if ((pos == Scanner::kNoSourcePos) || |
1655 (begin_pos <= pos) && (pos <= end_of_line_pos) && | 1696 (pos < begin_pos) || |
1656 (iter.PcOffset() < lowest_pc_offset)) { | 1697 (pos > end_of_line_pos)) { |
1698 // Token is not on same line as best fit. | |
1699 continue; | |
1700 } | |
1701 | |
1702 if (requested_column >= 0) { | |
1703 intptr_t ignored = -1; | |
1704 intptr_t token_start_column = -1; | |
1705 script.GetTokenLocation(pos, &ignored, &token_start_column); | |
1706 if (token_start_column != best_column) { | |
hausner
2015/09/03 00:37:50
Maybe comment that there may be more than one toke
turnidge
2015/09/04 18:05:29
Done.
| |
1707 continue; | |
1708 } | |
1709 } | |
1710 | |
1711 // Prefer the lowest pc offset. | |
1712 if (iter.PcOffset() < lowest_pc_offset) { | |
1657 lowest_pc_offset = iter.PcOffset(); | 1713 lowest_pc_offset = iter.PcOffset(); |
1658 best_fit_pos = pos; | 1714 best_fit_pos = pos; |
1659 } | 1715 } |
1660 } | 1716 } |
1661 return best_fit_pos; | 1717 return best_fit_pos; |
1662 } | 1718 } |
1663 | 1719 |
1664 // We didn't find a safe point in the given token range. Try and find | 1720 // We didn't find a safe point in the given token range. Try and |
1665 // a safe point in the remaining source code of the function. | 1721 // find a safe point in the remaining source code of the function. |
1722 // Since we have moved to the next line of the function, we no | |
1723 // longer are requesting a specific column number. | |
1666 if (last_token_pos < func.end_token_pos()) { | 1724 if (last_token_pos < func.end_token_pos()) { |
1667 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos()); | 1725 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos(), |
1726 -1 /* no column */); | |
1668 } | 1727 } |
1669 return -1; | 1728 return -1; |
1670 } | 1729 } |
1671 | 1730 |
1672 | 1731 |
1673 void Debugger::MakeCodeBreakpointAt(const Function& func, | 1732 void Debugger::MakeCodeBreakpointAt(const Function& func, |
1674 BreakpointLocation* loc) { | 1733 BreakpointLocation* loc) { |
1675 ASSERT(loc->token_pos_ != Scanner::kNoSourcePos); | 1734 ASSERT(loc->token_pos_ != Scanner::kNoSourcePos); |
1676 ASSERT((loc != NULL) && loc->IsResolved()); | 1735 ASSERT((loc != NULL) && loc->IsResolved()); |
1677 ASSERT(!func.HasOptimizedCode()); | 1736 ASSERT(!func.HasOptimizedCode()); |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1850 } | 1909 } |
1851 } | 1910 } |
1852 } | 1911 } |
1853 } | 1912 } |
1854 return best_fit.raw(); | 1913 return best_fit.raw(); |
1855 } | 1914 } |
1856 | 1915 |
1857 | 1916 |
1858 BreakpointLocation* Debugger::SetBreakpoint(const Script& script, | 1917 BreakpointLocation* Debugger::SetBreakpoint(const Script& script, |
1859 intptr_t token_pos, | 1918 intptr_t token_pos, |
1860 intptr_t last_token_pos) { | 1919 intptr_t last_token_pos, |
1920 intptr_t requested_column) { | |
1861 Function& func = Function::Handle(isolate_); | 1921 Function& func = Function::Handle(isolate_); |
1862 func = FindBestFit(script, token_pos); | 1922 func = FindBestFit(script, token_pos); |
1863 if (func.IsNull()) { | 1923 if (func.IsNull()) { |
1864 return NULL; | 1924 return NULL; |
1865 } | 1925 } |
1866 // There may be more than one function object for a given function | 1926 // There may be more than one function object for a given function |
1867 // in source code. There may be implicit closure functions, and | 1927 // in source code. There may be implicit closure functions, and |
1868 // there may be copies of mixin functions. Collect all compiled | 1928 // there may be copies of mixin functions. Collect all compiled |
1869 // functions whose source code range matches exactly the best fit | 1929 // functions whose source code range matches exactly the best fit |
1870 // function we found. | 1930 // function we found. |
1871 GrowableObjectArray& functions = | 1931 GrowableObjectArray& functions = |
1872 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 1932 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
1873 FindCompiledFunctions(script, | 1933 FindCompiledFunctions(script, |
1874 func.token_pos(), | 1934 func.token_pos(), |
1875 func.end_token_pos(), | 1935 func.end_token_pos(), |
1876 &functions); | 1936 &functions); |
1877 | 1937 |
1878 if (functions.Length() > 0) { | 1938 if (functions.Length() > 0) { |
1879 // One or more function object containing this breakpoint location | 1939 // One or more function object containing this breakpoint location |
1880 // have already been compiled. We can resolve the breakpoint now. | 1940 // have already been compiled. We can resolve the breakpoint now. |
1881 DeoptimizeWorld(); | 1941 DeoptimizeWorld(); |
1882 func ^= functions.At(0); | 1942 func ^= functions.At(0); |
1883 intptr_t breakpoint_pos = | 1943 intptr_t breakpoint_pos = |
1884 ResolveBreakpointPos(func, token_pos, last_token_pos); | 1944 ResolveBreakpointPos(func, token_pos, last_token_pos, requested_column); |
1885 if (breakpoint_pos >= 0) { | 1945 if (breakpoint_pos >= 0) { |
1886 BreakpointLocation* bpt = GetBreakpointLocation(script, breakpoint_pos); | 1946 BreakpointLocation* bpt = |
1947 GetBreakpointLocation(script, breakpoint_pos, requested_column); | |
1887 if (bpt != NULL) { | 1948 if (bpt != NULL) { |
1888 // A source breakpoint for this location already exists. | 1949 // A source breakpoint for this location already exists. |
1889 return bpt; | 1950 return bpt; |
1890 } | 1951 } |
1891 bpt = new BreakpointLocation(script, token_pos, last_token_pos); | 1952 bpt = new BreakpointLocation(script, token_pos, last_token_pos, |
1953 requested_column); | |
1892 bpt->SetResolved(func, breakpoint_pos); | 1954 bpt->SetResolved(func, breakpoint_pos); |
1893 RegisterBreakpointLocation(bpt); | 1955 RegisterBreakpointLocation(bpt); |
1894 | 1956 |
1895 // Create code breakpoints for all compiled functions we found. | 1957 // Create code breakpoints for all compiled functions we found. |
1896 const intptr_t num_functions = functions.Length(); | 1958 const intptr_t num_functions = functions.Length(); |
1897 for (intptr_t i = 0; i < num_functions; i++) { | 1959 for (intptr_t i = 0; i < num_functions; i++) { |
1898 func ^= functions.At(i); | 1960 func ^= functions.At(i); |
1899 ASSERT(func.HasCode()); | 1961 ASSERT(func.HasCode()); |
1900 MakeCodeBreakpointAt(func, bpt); | 1962 MakeCodeBreakpointAt(func, bpt); |
1901 } | 1963 } |
1902 if (FLAG_verbose_debug) { | 1964 if (FLAG_verbose_debug) { |
1903 intptr_t line_number; | 1965 intptr_t line_number; |
1904 script.GetTokenLocation(breakpoint_pos, &line_number, NULL); | 1966 intptr_t column_number; |
1967 script.GetTokenLocation(breakpoint_pos, &line_number, &column_number); | |
1905 OS::Print("Resolved BP for " | 1968 OS::Print("Resolved BP for " |
1906 "function '%s' at line %" Pd "\n", | 1969 "function '%s' at line %" Pd " col %" Pd "\n", |
1907 func.ToFullyQualifiedCString(), | 1970 func.ToFullyQualifiedCString(), |
1908 line_number); | 1971 line_number, column_number); |
1909 } | 1972 } |
1910 return bpt; | 1973 return bpt; |
1911 } | 1974 } |
1912 } | 1975 } |
1913 // There is no compiled function at this token position. | 1976 // There is no compiled function at this token position. |
1914 // Register an unresolved breakpoint. | 1977 // Register an unresolved breakpoint. |
1915 if (FLAG_verbose_debug && !func.IsNull()) { | 1978 if (FLAG_verbose_debug && !func.IsNull()) { |
1916 intptr_t line_number; | 1979 intptr_t line_number; |
1917 script.GetTokenLocation(token_pos, &line_number, NULL); | 1980 intptr_t column_number; |
1981 script.GetTokenLocation(token_pos, &line_number, &column_number); | |
1918 OS::Print("Registering pending breakpoint for " | 1982 OS::Print("Registering pending breakpoint for " |
1919 "uncompiled function '%s' at line %" Pd "\n", | 1983 "uncompiled function '%s' at line %" Pd " col %" Pd "\n", |
1920 func.ToFullyQualifiedCString(), | 1984 func.ToFullyQualifiedCString(), |
1921 line_number); | 1985 line_number, column_number); |
1922 } | 1986 } |
1923 BreakpointLocation* bpt = GetBreakpointLocation(script, token_pos); | 1987 BreakpointLocation* bpt = |
1988 GetBreakpointLocation(script, token_pos, requested_column); | |
1924 if (bpt == NULL) { | 1989 if (bpt == NULL) { |
1925 bpt = new BreakpointLocation(script, token_pos, last_token_pos); | 1990 bpt = new BreakpointLocation(script, token_pos, last_token_pos, |
1991 requested_column); | |
1926 RegisterBreakpointLocation(bpt); | 1992 RegisterBreakpointLocation(bpt); |
1927 } | 1993 } |
1928 return bpt; | 1994 return bpt; |
1929 } | 1995 } |
1930 | 1996 |
1931 | 1997 |
1932 // Synchronize the enabled/disabled state of all code breakpoints | 1998 // Synchronize the enabled/disabled state of all code breakpoints |
1933 // associated with the breakpoint location loc. | 1999 // associated with the breakpoint location loc. |
1934 void Debugger::SyncBreakpointLocation(BreakpointLocation* loc) { | 2000 void Debugger::SyncBreakpointLocation(BreakpointLocation* loc) { |
1935 bool any_enabled = loc->AnyEnabled(); | 2001 bool any_enabled = loc->AnyEnabled(); |
(...skipping 26 matching lines...) Expand all Loading... | |
1962 Breakpoint* Debugger::SetBreakpointAtEntry(const Function& target_function, | 2028 Breakpoint* Debugger::SetBreakpointAtEntry(const Function& target_function, |
1963 bool single_shot) { | 2029 bool single_shot) { |
1964 ASSERT(!target_function.IsNull()); | 2030 ASSERT(!target_function.IsNull()); |
1965 if (!target_function.is_debuggable()) { | 2031 if (!target_function.is_debuggable()) { |
1966 return NULL; | 2032 return NULL; |
1967 } | 2033 } |
1968 const Script& script = Script::Handle(target_function.script()); | 2034 const Script& script = Script::Handle(target_function.script()); |
1969 BreakpointLocation* bpt_location = | 2035 BreakpointLocation* bpt_location = |
1970 SetBreakpoint(script, | 2036 SetBreakpoint(script, |
1971 target_function.token_pos(), | 2037 target_function.token_pos(), |
1972 target_function.end_token_pos()); | 2038 target_function.end_token_pos(), |
2039 -1 /* no column */); | |
1973 if (single_shot) { | 2040 if (single_shot) { |
1974 return bpt_location->AddSingleShot(this); | 2041 return bpt_location->AddSingleShot(this); |
1975 } else { | 2042 } else { |
1976 return bpt_location->AddRepeated(this); | 2043 return bpt_location->AddRepeated(this); |
1977 } | 2044 } |
1978 } | 2045 } |
1979 | 2046 |
1980 | 2047 |
1981 Breakpoint* Debugger::SetBreakpointAtActivation(const Instance& closure) { | 2048 Breakpoint* Debugger::SetBreakpointAtActivation(const Instance& closure) { |
1982 if (!closure.IsClosure()) { | 2049 if (!closure.IsClosure()) { |
1983 return NULL; | 2050 return NULL; |
1984 } | 2051 } |
1985 const Function& func = Function::Handle(Closure::function(closure)); | 2052 const Function& func = Function::Handle(Closure::function(closure)); |
1986 const Script& script = Script::Handle(func.script()); | 2053 const Script& script = Script::Handle(func.script()); |
1987 BreakpointLocation* bpt_location = SetBreakpoint(script, | 2054 BreakpointLocation* bpt_location = SetBreakpoint(script, |
1988 func.token_pos(), | 2055 func.token_pos(), |
1989 func.end_token_pos()); | 2056 func.end_token_pos(), |
2057 -1 /* no column */); | |
1990 return bpt_location->AddPerClosure(this, closure); | 2058 return bpt_location->AddPerClosure(this, closure); |
1991 } | 2059 } |
1992 | 2060 |
1993 | 2061 |
1994 Breakpoint* Debugger::BreakpointAtActivation(const Instance& closure) { | 2062 Breakpoint* Debugger::BreakpointAtActivation(const Instance& closure) { |
1995 if (!closure.IsClosure()) { | 2063 if (!closure.IsClosure()) { |
1996 return NULL; | 2064 return NULL; |
1997 } | 2065 } |
1998 | 2066 |
1999 BreakpointLocation* loc = breakpoint_locations_; | 2067 BreakpointLocation* loc = breakpoint_locations_; |
2000 while (loc != NULL) { | 2068 while (loc != NULL) { |
2001 Breakpoint* bpt = loc->breakpoints(); | 2069 Breakpoint* bpt = loc->breakpoints(); |
2002 while (bpt != NULL) { | 2070 while (bpt != NULL) { |
2003 if (bpt->IsPerClosure()) { | 2071 if (bpt->IsPerClosure()) { |
2004 if (closure.raw() == bpt->closure()) { | 2072 if (closure.raw() == bpt->closure()) { |
2005 return bpt; | 2073 return bpt; |
2006 } | 2074 } |
2007 } | 2075 } |
2008 bpt = bpt->next(); | 2076 bpt = bpt->next(); |
2009 } | 2077 } |
2010 loc = loc->next(); | 2078 loc = loc->next(); |
2011 } | 2079 } |
2012 | 2080 |
2013 return NULL; | 2081 return NULL; |
2014 } | 2082 } |
2015 | 2083 |
2016 | 2084 |
2017 Breakpoint* Debugger::SetBreakpointAtLine(const String& script_url, | 2085 Breakpoint* Debugger::SetBreakpointAtLine(const String& script_url, |
2018 intptr_t line_number) { | 2086 intptr_t line_number) { |
2019 BreakpointLocation* loc = BreakpointLocationAtLine(script_url, line_number); | 2087 BreakpointLocation* loc = |
2088 BreakpointLocationAtLineCol(script_url, line_number, -1 /* no column */); | |
2020 if (loc != NULL) { | 2089 if (loc != NULL) { |
2021 return loc->AddRepeated(this); | 2090 return loc->AddRepeated(this); |
2022 } | 2091 } |
2092 return NULL; | |
2093 } | |
2094 | |
2095 | |
2096 Breakpoint* Debugger::SetBreakpointAtLineCol(const String& script_url, | |
2097 intptr_t line_number, | |
2098 intptr_t column_number) { | |
2099 BreakpointLocation* loc = BreakpointLocationAtLineCol(script_url, | |
2100 line_number, | |
2101 column_number); | |
2102 if (loc != NULL) { | |
2103 return loc->AddRepeated(this); | |
2104 } | |
2023 return NULL; | 2105 return NULL; |
2024 } | 2106 } |
2025 | 2107 |
2026 | 2108 |
2027 BreakpointLocation* Debugger::BreakpointLocationAtLine(const String& script_url, | 2109 BreakpointLocation* Debugger::BreakpointLocationAtLineCol( |
2028 intptr_t line_number) { | 2110 const String& script_url, |
2111 intptr_t line_number, | |
2112 intptr_t column_number) { | |
2029 Library& lib = Library::Handle(isolate_); | 2113 Library& lib = Library::Handle(isolate_); |
2030 Script& script = Script::Handle(isolate_); | 2114 Script& script = Script::Handle(isolate_); |
2031 const GrowableObjectArray& libs = | 2115 const GrowableObjectArray& libs = |
2032 GrowableObjectArray::Handle(isolate_->object_store()->libraries()); | 2116 GrowableObjectArray::Handle(isolate_->object_store()->libraries()); |
2033 const GrowableObjectArray& scripts = | 2117 const GrowableObjectArray& scripts = |
2034 GrowableObjectArray::Handle(isolate_, GrowableObjectArray::New()); | 2118 GrowableObjectArray::Handle(isolate_, GrowableObjectArray::New()); |
2035 for (intptr_t i = 0; i < libs.Length(); i++) { | 2119 for (intptr_t i = 0; i < libs.Length(); i++) { |
2036 lib ^= libs.At(i); | 2120 lib ^= libs.At(i); |
2037 script = lib.LookupScript(script_url); | 2121 script = lib.LookupScript(script_url); |
2038 if (!script.IsNull()) { | 2122 if (!script.IsNull()) { |
2039 scripts.Add(script); | 2123 scripts.Add(script); |
2040 } | 2124 } |
2041 } | 2125 } |
2042 if (scripts.Length() == 0) { | 2126 if (scripts.Length() == 0) { |
2043 // No script found with given url. Create a latent breakpoint which | 2127 // No script found with given url. Create a latent breakpoint which |
2044 // will be set if the url is loaded later. | 2128 // will be set if the url is loaded later. |
2045 BreakpointLocation* latent_bpt = GetLatentBreakpoint(script_url, | 2129 BreakpointLocation* latent_bpt = GetLatentBreakpoint(script_url, |
2046 line_number); | 2130 line_number, |
2131 column_number); | |
2047 if (FLAG_verbose_debug) { | 2132 if (FLAG_verbose_debug) { |
2048 OS::Print("Set latent breakpoint in url '%s' at line %" Pd "\n", | 2133 OS::Print("Set latent breakpoint in url '%s' at " |
2134 "line %" Pd " col %" Pd "\n", | |
2049 script_url.ToCString(), | 2135 script_url.ToCString(), |
2050 line_number); | 2136 line_number, column_number); |
2051 } | 2137 } |
2052 return latent_bpt; | 2138 return latent_bpt; |
2053 } | 2139 } |
2054 if (scripts.Length() > 1) { | 2140 if (scripts.Length() > 1) { |
2055 if (FLAG_verbose_debug) { | 2141 if (FLAG_verbose_debug) { |
2056 OS::Print("Multiple scripts match url '%s'\n", script_url.ToCString()); | 2142 OS::Print("Multiple scripts match url '%s'\n", script_url.ToCString()); |
2057 } | 2143 } |
2058 return NULL; | 2144 return NULL; |
2059 } | 2145 } |
2060 script ^= scripts.At(0); | 2146 script ^= scripts.At(0); |
(...skipping 11 matching lines...) Expand all Loading... | |
2072 if (FLAG_verbose_debug) { | 2158 if (FLAG_verbose_debug) { |
2073 OS::Print("No executable code at line %" Pd " in '%s'\n", | 2159 OS::Print("No executable code at line %" Pd " in '%s'\n", |
2074 line_number, script_url.ToCString()); | 2160 line_number, script_url.ToCString()); |
2075 } | 2161 } |
2076 return NULL; | 2162 return NULL; |
2077 } | 2163 } |
2078 | 2164 |
2079 BreakpointLocation* bpt = NULL; | 2165 BreakpointLocation* bpt = NULL; |
2080 ASSERT(first_token_idx <= last_token_idx); | 2166 ASSERT(first_token_idx <= last_token_idx); |
2081 while ((bpt == NULL) && (first_token_idx <= last_token_idx)) { | 2167 while ((bpt == NULL) && (first_token_idx <= last_token_idx)) { |
2082 bpt = SetBreakpoint(script, first_token_idx, last_token_idx); | 2168 bpt = SetBreakpoint(script, first_token_idx, last_token_idx, column_number); |
2083 first_token_idx++; | 2169 first_token_idx++; |
2084 } | 2170 } |
2085 if ((bpt == NULL) && FLAG_verbose_debug) { | 2171 if ((bpt == NULL) && FLAG_verbose_debug) { |
2086 OS::Print("No executable code at line %" Pd " in '%s'\n", | 2172 OS::Print("No executable code at line %" Pd " in '%s'\n", |
2087 line_number, script_url.ToCString()); | 2173 line_number, script_url.ToCString()); |
2088 } | 2174 } |
2089 return bpt; | 2175 return bpt; |
2090 } | 2176 } |
2091 | 2177 |
2092 | 2178 |
(...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2673 // TODO(hausner): What should we do if function is optimized? | 2759 // TODO(hausner): What should we do if function is optimized? |
2674 // Can we deoptimize the function? | 2760 // Can we deoptimize the function? |
2675 ASSERT(!func.HasOptimizedCode()); | 2761 ASSERT(!func.HasOptimizedCode()); |
2676 | 2762 |
2677 // There is no local function within func that contains the | 2763 // There is no local function within func that contains the |
2678 // breakpoint token position. Resolve the breakpoint if necessary | 2764 // breakpoint token position. Resolve the breakpoint if necessary |
2679 // and set the code breakpoints. | 2765 // and set the code breakpoints. |
2680 if (!loc->IsResolved()) { | 2766 if (!loc->IsResolved()) { |
2681 // Resolve source breakpoint in the newly compiled function. | 2767 // Resolve source breakpoint in the newly compiled function. |
2682 intptr_t bp_pos = | 2768 intptr_t bp_pos = |
2683 ResolveBreakpointPos(func, loc->token_pos(), loc->end_token_pos()); | 2769 ResolveBreakpointPos(func, loc->token_pos(), loc->end_token_pos(), |
2770 loc->requested_column_number()); | |
2684 if (bp_pos < 0) { | 2771 if (bp_pos < 0) { |
2685 if (FLAG_verbose_debug) { | 2772 if (FLAG_verbose_debug) { |
2686 OS::Print("Failed resolving breakpoint for function '%s'\n", | 2773 OS::Print("Failed resolving breakpoint for function '%s'\n", |
2687 String::Handle(func.name()).ToCString()); | 2774 String::Handle(func.name()).ToCString()); |
2688 } | 2775 } |
2689 continue; | 2776 continue; |
2690 } | 2777 } |
2691 intptr_t requested_pos = loc->token_pos(); | 2778 intptr_t requested_pos = loc->token_pos(); |
2692 intptr_t requested_end_pos = loc->end_token_pos(); | 2779 intptr_t requested_end_pos = loc->end_token_pos(); |
2693 loc->SetResolved(func, bp_pos); | 2780 loc->SetResolved(func, bp_pos); |
2694 Breakpoint* bpt = loc->breakpoints(); | 2781 Breakpoint* bpt = loc->breakpoints(); |
2695 while (bpt != NULL) { | 2782 while (bpt != NULL) { |
2696 if (FLAG_verbose_debug) { | 2783 if (FLAG_verbose_debug) { |
2697 OS::Print("Resolved BP %" Pd " to pos %" Pd ", line %" Pd ", " | 2784 OS::Print("Resolved BP %" Pd " to pos %" Pd ", " |
2698 "function '%s' (requested range %" Pd "-%" Pd ")\n", | 2785 "line %" Pd " col %" Pd ", " |
2786 "function '%s' (requested range %" Pd "-%" Pd ", " | |
2787 "requested col %" Pd ")\n", | |
2699 bpt->id(), | 2788 bpt->id(), |
2700 loc->token_pos(), | 2789 loc->token_pos(), |
2701 loc->LineNumber(), | 2790 loc->LineNumber(), |
2791 loc->ColumnNumber(), | |
2702 func.ToFullyQualifiedCString(), | 2792 func.ToFullyQualifiedCString(), |
2703 requested_pos, | 2793 requested_pos, |
2704 requested_end_pos); | 2794 requested_end_pos, |
2795 loc->requested_column_number()); | |
2705 } | 2796 } |
2706 SignalBpResolved(bpt); | 2797 SignalBpResolved(bpt); |
2707 SendServiceBreakpointEvent(ServiceEvent::kBreakpointResolved, bpt); | 2798 SendServiceBreakpointEvent(ServiceEvent::kBreakpointResolved, bpt); |
2708 bpt = bpt->next(); | 2799 bpt = bpt->next(); |
2709 } | 2800 } |
2710 } | 2801 } |
2711 ASSERT(loc->IsResolved()); | 2802 ASSERT(loc->IsResolved()); |
2712 if (FLAG_verbose_debug) { | 2803 if (FLAG_verbose_debug) { |
2713 Breakpoint* bpt = loc->breakpoints(); | 2804 Breakpoint* bpt = loc->breakpoints(); |
2714 while (bpt != NULL) { | 2805 while (bpt != NULL) { |
2715 OS::Print("Setting breakpoint %" Pd " at line %" Pd " for %s '%s'\n", | 2806 OS::Print("Setting breakpoint %" Pd " at line %" Pd " col %" Pd "" |
2807 " for %s '%s'\n", | |
2716 bpt->id(), | 2808 bpt->id(), |
2717 loc->LineNumber(), | 2809 loc->LineNumber(), |
2810 loc->ColumnNumber(), | |
2718 func.IsClosureFunction() ? "closure" : "function", | 2811 func.IsClosureFunction() ? "closure" : "function", |
2719 String::Handle(func.name()).ToCString()); | 2812 String::Handle(func.name()).ToCString()); |
2720 bpt = bpt->next(); | 2813 bpt = bpt->next(); |
2721 } | 2814 } |
2722 } | 2815 } |
2723 MakeCodeBreakpointAt(func, loc); | 2816 MakeCodeBreakpointAt(func, loc); |
2724 } | 2817 } |
2725 } | 2818 } |
2726 } | 2819 } |
2727 | 2820 |
(...skipping 22 matching lines...) Expand all Loading... | |
2750 found_match = true; | 2843 found_match = true; |
2751 BreakpointLocation* matched_loc = loc; | 2844 BreakpointLocation* matched_loc = loc; |
2752 loc = loc->next(); | 2845 loc = loc->next(); |
2753 if (prev_loc == NULL) { | 2846 if (prev_loc == NULL) { |
2754 latent_locations_ = loc; | 2847 latent_locations_ = loc; |
2755 } else { | 2848 } else { |
2756 prev_loc->set_next(loc); | 2849 prev_loc->set_next(loc); |
2757 } | 2850 } |
2758 // Now find the token range at the requested line and make a | 2851 // Now find the token range at the requested line and make a |
2759 // new unresolved source breakpoint. | 2852 // new unresolved source breakpoint. |
2760 intptr_t line_number = matched_loc->LineNumber(); | 2853 intptr_t line_number = matched_loc->requested_line_number(); |
2854 intptr_t column_number = matched_loc->requested_column_number(); | |
2761 ASSERT(line_number >= 0); | 2855 ASSERT(line_number >= 0); |
2762 intptr_t first_token_pos, last_token_pos; | 2856 intptr_t first_token_pos, last_token_pos; |
2763 script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos); | 2857 script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos); |
2764 if ((first_token_pos < 0) || | 2858 if ((first_token_pos < 0) || |
2765 (last_token_pos < 0)) { | 2859 (last_token_pos < 0)) { |
2766 // Script does not contain the given line number or there are no | 2860 // Script does not contain the given line number or there are no |
2767 // tokens on the line. Drop the breakpoint silently. | 2861 // tokens on the line. Drop the breakpoint silently. |
2768 Breakpoint* bpt = matched_loc->breakpoints(); | 2862 Breakpoint* bpt = matched_loc->breakpoints(); |
2769 while (bpt != NULL) { | 2863 while (bpt != NULL) { |
2770 if (FLAG_verbose_debug) { | 2864 if (FLAG_verbose_debug) { |
2771 OS::Print("No code found at line %" Pd ": " | 2865 OS::Print("No code found at line %" Pd ": " |
2772 "dropping latent breakpoint %" Pd " in '%s'\n", | 2866 "dropping latent breakpoint %" Pd " in '%s'\n", |
2773 line_number, | 2867 line_number, |
2774 bpt->id(), | 2868 bpt->id(), |
2775 url.ToCString()); | 2869 url.ToCString()); |
2776 } | 2870 } |
2777 Breakpoint* prev = bpt; | 2871 Breakpoint* prev = bpt; |
2778 bpt = bpt->next(); | 2872 bpt = bpt->next(); |
2779 delete prev; | 2873 delete prev; |
2780 } | 2874 } |
2781 delete matched_loc; | 2875 delete matched_loc; |
2782 } else { | 2876 } else { |
2783 // We don't expect to already have a breakpoint for this location. | 2877 // We don't expect to already have a breakpoint for this location. |
2784 // If there is one, assert in debug build but silently drop | 2878 // If there is one, assert in debug build but silently drop |
2785 // the latent breakpoint in release build. | 2879 // the latent breakpoint in release build. |
2786 BreakpointLocation* existing_loc = | 2880 BreakpointLocation* existing_loc = |
2787 GetBreakpointLocation(script, first_token_pos); | 2881 GetBreakpointLocation(script, first_token_pos, column_number); |
2788 ASSERT(existing_loc == NULL); | 2882 ASSERT(existing_loc == NULL); |
2789 if (existing_loc == NULL) { | 2883 if (existing_loc == NULL) { |
2790 // Create and register a new source breakpoint for the | 2884 // Create and register a new source breakpoint for the |
2791 // latent breakpoint. | 2885 // latent breakpoint. |
2792 BreakpointLocation* unresolved_loc = | 2886 BreakpointLocation* unresolved_loc = |
2793 new BreakpointLocation(script, | 2887 new BreakpointLocation(script, |
2794 first_token_pos, | 2888 first_token_pos, |
2795 last_token_pos); | 2889 last_token_pos, |
2890 column_number); | |
2796 RegisterBreakpointLocation(unresolved_loc); | 2891 RegisterBreakpointLocation(unresolved_loc); |
2797 | 2892 |
2798 // Move breakpoints over. | 2893 // Move breakpoints over. |
2799 Breakpoint* bpt = matched_loc->breakpoints(); | 2894 Breakpoint* bpt = matched_loc->breakpoints(); |
2800 unresolved_loc->set_breakpoints(bpt); | 2895 unresolved_loc->set_breakpoints(bpt); |
2801 matched_loc->set_breakpoints(NULL); | 2896 matched_loc->set_breakpoints(NULL); |
2802 while (bpt != NULL) { | 2897 while (bpt != NULL) { |
2803 bpt->set_bpt_location(unresolved_loc); | 2898 bpt->set_bpt_location(unresolved_loc); |
2804 if (FLAG_verbose_debug) { | 2899 if (FLAG_verbose_debug) { |
2805 OS::Print("Converted latent breakpoint " | 2900 OS::Print("Converted latent breakpoint " |
2806 "%" Pd " in '%s' at line %" Pd "\n", | 2901 "%" Pd " in '%s' at line %" Pd " col %" Pd "\n", |
2807 bpt->id(), | 2902 bpt->id(), |
2808 url.ToCString(), | 2903 url.ToCString(), |
2809 line_number); | 2904 line_number, column_number); |
2810 } | 2905 } |
2811 bpt = bpt->next(); | 2906 bpt = bpt->next(); |
2812 } | 2907 } |
2813 SyncBreakpointLocation(unresolved_loc); | 2908 SyncBreakpointLocation(unresolved_loc); |
2814 } | 2909 } |
2815 delete matched_loc; | 2910 delete matched_loc; |
2816 // Break out of the iteration over loaded libraries. If the | 2911 // Break out of the iteration over loaded libraries. If the |
2817 // same url has been loaded into more than one library, we | 2912 // same url has been loaded into more than one library, we |
2818 // only set a breakpoint in the first one. | 2913 // only set a breakpoint in the first one. |
2819 // TODO(hausner): There is one possible pitfall here. | 2914 // TODO(hausner): There is one possible pitfall here. |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2963 delete temp_bpt; | 3058 delete temp_bpt; |
2964 } else { | 3059 } else { |
2965 prev_bpt = curr_bpt; | 3060 prev_bpt = curr_bpt; |
2966 curr_bpt = curr_bpt->next(); | 3061 curr_bpt = curr_bpt->next(); |
2967 } | 3062 } |
2968 } | 3063 } |
2969 } | 3064 } |
2970 | 3065 |
2971 | 3066 |
2972 BreakpointLocation* Debugger::GetBreakpointLocation(const Script& script, | 3067 BreakpointLocation* Debugger::GetBreakpointLocation(const Script& script, |
2973 intptr_t token_pos) { | 3068 intptr_t token_pos, |
3069 intptr_t requested_column) { | |
2974 BreakpointLocation* bpt = breakpoint_locations_; | 3070 BreakpointLocation* bpt = breakpoint_locations_; |
2975 while (bpt != NULL) { | 3071 while (bpt != NULL) { |
2976 if ((bpt->script_ == script.raw()) && (bpt->token_pos_ == token_pos)) { | 3072 if ((bpt->script_ == script.raw()) && |
3073 (bpt->token_pos_ == token_pos) && | |
3074 (bpt->requested_column_number_ == requested_column)) { | |
2977 return bpt; | 3075 return bpt; |
2978 } | 3076 } |
2979 bpt = bpt->next(); | 3077 bpt = bpt->next(); |
2980 } | 3078 } |
2981 return NULL; | 3079 return NULL; |
2982 } | 3080 } |
2983 | 3081 |
2984 | 3082 |
2985 Breakpoint* Debugger::GetBreakpointById(intptr_t id) { | 3083 Breakpoint* Debugger::GetBreakpointById(intptr_t id) { |
2986 BreakpointLocation* loc = breakpoint_locations_; | 3084 BreakpointLocation* loc = breakpoint_locations_; |
2987 while (loc != NULL) { | 3085 while (loc != NULL) { |
2988 Breakpoint* bpt = loc->breakpoints(); | 3086 Breakpoint* bpt = loc->breakpoints(); |
2989 while (bpt != NULL) { | 3087 while (bpt != NULL) { |
2990 if (bpt->id() == id) { | 3088 if (bpt->id() == id) { |
2991 return bpt; | 3089 return bpt; |
2992 } | 3090 } |
2993 bpt = bpt->next(); | 3091 bpt = bpt->next(); |
2994 } | 3092 } |
2995 loc = loc->next(); | 3093 loc = loc->next(); |
2996 } | 3094 } |
2997 return NULL; | 3095 return NULL; |
2998 } | 3096 } |
2999 | 3097 |
3000 | 3098 |
3001 BreakpointLocation* Debugger::GetLatentBreakpoint(const String& url, | 3099 BreakpointLocation* Debugger::GetLatentBreakpoint(const String& url, |
3002 intptr_t line) { | 3100 intptr_t line, |
3101 intptr_t column) { | |
3003 BreakpointLocation* bpt = latent_locations_; | 3102 BreakpointLocation* bpt = latent_locations_; |
3004 String& bpt_url = String::Handle(isolate_); | 3103 String& bpt_url = String::Handle(isolate_); |
3005 while (bpt != NULL) { | 3104 while (bpt != NULL) { |
3006 bpt_url = bpt->url(); | 3105 bpt_url = bpt->url(); |
3007 if (bpt_url.Equals(url) && (bpt->LineNumber() == line)) { | 3106 if (bpt_url.Equals(url) && |
3107 (bpt->requested_line_number() == line) && | |
3108 (bpt->requested_column_number() == column)) { | |
3008 return bpt; | 3109 return bpt; |
3009 } | 3110 } |
3010 bpt = bpt->next(); | 3111 bpt = bpt->next(); |
3011 } | 3112 } |
3012 // No breakpint for this url and line requested. Allocate new one. | 3113 // No breakpoint for this location requested. Allocate new one. |
3013 bpt = new BreakpointLocation(url, line); | 3114 bpt = new BreakpointLocation(url, line, column); |
3014 bpt->set_next(latent_locations_); | 3115 bpt->set_next(latent_locations_); |
3015 latent_locations_ = bpt; | 3116 latent_locations_ = bpt; |
3016 return bpt; | 3117 return bpt; |
3017 } | 3118 } |
3018 | 3119 |
3019 | 3120 |
3020 void Debugger::RegisterBreakpointLocation(BreakpointLocation* bpt) { | 3121 void Debugger::RegisterBreakpointLocation(BreakpointLocation* bpt) { |
3021 ASSERT(bpt->next() == NULL); | 3122 ASSERT(bpt->next() == NULL); |
3022 bpt->set_next(breakpoint_locations_); | 3123 bpt->set_next(breakpoint_locations_); |
3023 breakpoint_locations_ = bpt; | 3124 breakpoint_locations_ = bpt; |
3024 } | 3125 } |
3025 | 3126 |
3026 | 3127 |
3027 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 3128 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
3028 ASSERT(bpt->next() == NULL); | 3129 ASSERT(bpt->next() == NULL); |
3029 bpt->set_next(code_breakpoints_); | 3130 bpt->set_next(code_breakpoints_); |
3030 code_breakpoints_ = bpt; | 3131 code_breakpoints_ = bpt; |
3031 } | 3132 } |
3032 | 3133 |
3033 } // namespace dart | 3134 } // namespace dart |
OLD | NEW |