Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Side by Side Diff: runtime/vm/debugger.cc

Issue 1312763010: Support column-based breakpoints in the VM and Observatory. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: hausner review Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/debugger_api_impl.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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_line_number,
70 intptr_t requested_column_number)
69 : script_(script.raw()), 71 : script_(script.raw()),
70 url_(script.url()), 72 url_(script.url()),
71 token_pos_(token_pos), 73 token_pos_(token_pos),
72 end_token_pos_(end_token_pos), 74 end_token_pos_(end_token_pos),
73 is_resolved_(false), 75 is_resolved_(false),
74 next_(NULL), 76 next_(NULL),
75 conditions_(NULL), 77 conditions_(NULL),
78 requested_line_number_(requested_line_number),
79 requested_column_number_(requested_column_number),
76 function_(Function::null()), 80 function_(Function::null()),
77 line_number_(-1) { 81 line_number_(-1),
82 column_number_(-1) {
78 ASSERT(!script.IsNull()); 83 ASSERT(!script.IsNull());
79 ASSERT(token_pos_ >= 0); 84 ASSERT(token_pos_ >= 0);
80 } 85 }
81 86
82 // Create a latent breakpoint at given url and line number. 87 // Create a latent breakpoint at given url and line number.
83 BreakpointLocation::BreakpointLocation(const String& url, 88 BreakpointLocation::BreakpointLocation(const String& url,
84 intptr_t line_number) 89 intptr_t requested_line_number,
90 intptr_t requested_column_number)
85 : script_(Script::null()), 91 : script_(Script::null()),
86 url_(url.raw()), 92 url_(url.raw()),
87 token_pos_(-1), 93 token_pos_(-1),
88 end_token_pos_(-1), 94 end_token_pos_(-1),
89 is_resolved_(false), 95 is_resolved_(false),
90 next_(NULL), 96 next_(NULL),
91 conditions_(NULL), 97 conditions_(NULL),
98 requested_line_number_(requested_line_number),
99 requested_column_number_(requested_column_number),
92 function_(Function::null()), 100 function_(Function::null()),
93 line_number_(line_number) { 101 line_number_(-1),
94 ASSERT(line_number_ >= 0); 102 column_number_(-1) {
103 ASSERT(requested_line_number_ >= 0);
95 } 104 }
96 105
97 106
98 BreakpointLocation::~BreakpointLocation() { 107 BreakpointLocation::~BreakpointLocation() {
99 Breakpoint* bpt = breakpoints(); 108 Breakpoint* bpt = breakpoints();
100 while (bpt != NULL) { 109 while (bpt != NULL) {
101 Breakpoint* temp = bpt; 110 Breakpoint* temp = bpt;
102 bpt = bpt->next(); 111 bpt = bpt->next();
103 delete temp; 112 delete temp;
104 } 113 }
105 } 114 }
106 115
107 116
108 bool BreakpointLocation::AnyEnabled() const { 117 bool BreakpointLocation::AnyEnabled() const {
109 return breakpoints() != NULL; 118 return breakpoints() != NULL;
110 } 119 }
111 120
112 121
113 void BreakpointLocation::SetResolved(const Function& func, intptr_t token_pos) { 122 void BreakpointLocation::SetResolved(const Function& func, intptr_t token_pos) {
114 ASSERT(!IsLatent()); 123 ASSERT(!IsLatent());
115 ASSERT(func.script() == script_); 124 ASSERT(func.script() == script_);
116 ASSERT((func.token_pos() <= token_pos) && 125 ASSERT((func.token_pos() <= token_pos) &&
117 (token_pos <= func.end_token_pos())); 126 (token_pos <= func.end_token_pos()));
118 ASSERT(func.is_debuggable()); 127 ASSERT(func.is_debuggable());
119 function_ = func.raw(); 128 function_ = func.raw();
120 token_pos_ = token_pos; 129 token_pos_ = token_pos;
121 end_token_pos_ = token_pos; 130 end_token_pos_ = token_pos;
122 line_number_ = -1; // Recalculate lazily.
123 is_resolved_ = true; 131 is_resolved_ = true;
124 } 132 }
125 133
126 134
127 // TODO(hausner): Get rid of library parameter. A source breakpoint location 135 // 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 136 // 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. 137 // in more than one library, e.g. the text location of mixin functions.
130 void BreakpointLocation::GetCodeLocation(Library* lib, 138 void BreakpointLocation::GetCodeLocation(Library* lib,
131 Script* script, 139 Script* script,
132 intptr_t* pos) { 140 intptr_t* pos) const {
133 if (IsLatent()) { 141 if (IsLatent()) {
134 *lib = Library::null(); 142 *lib = Library::null();
135 *script = Script::null(); 143 *script = Script::null();
136 *pos = -1; 144 *pos = -1;
137 } else { 145 } else {
138 *script = this->script(); 146 *script = this->script();
139 *pos = token_pos_; 147 *pos = token_pos_;
140 if (IsResolved()) { 148 if (IsResolved()) {
141 const Function& func = Function::Handle(function_); 149 const Function& func = Function::Handle(function_);
142 ASSERT(!func.IsNull()); 150 ASSERT(!func.IsNull());
143 const Class& cls = Class::Handle(func.origin()); 151 const Class& cls = Class::Handle(func.origin());
144 *lib = cls.library(); 152 *lib = cls.library();
145 } else { 153 } else {
146 *lib = Library::null(); 154 *lib = Library::null();
147 } 155 }
148 } 156 }
149 } 157 }
150 158
151 159
152 intptr_t BreakpointLocation::LineNumber() { 160 intptr_t BreakpointLocation::LineNumber() {
153 // Latent breakpoints must have a requested line number >= 0. 161 ASSERT(IsResolved());
154 ASSERT(!IsLatent() || line_number_ >= 0);
155 // Compute line number lazily since it causes scanning of the script. 162 // Compute line number lazily since it causes scanning of the script.
156 if (line_number_ < 0) { 163 if (line_number_ < 0) {
157 const Script& script = Script::Handle(this->script()); 164 const Script& script = Script::Handle(this->script());
158 script.GetTokenLocation(token_pos_, &line_number_, NULL); 165 script.GetTokenLocation(token_pos_, &line_number_, NULL);
159 } 166 }
160 return line_number_; 167 return line_number_;
161 } 168 }
162 169
163 170
171 intptr_t BreakpointLocation::ColumnNumber() {
172 ASSERT(IsResolved());
173 // Compute column number lazily since it causes scanning of the script.
174 if (column_number_ < 0) {
175 const Script& script = Script::Handle(this->script());
176 script.GetTokenLocation(token_pos_, &line_number_, &column_number_);
177 }
178 return column_number_;
179 }
180
181
164 void Breakpoint::set_bpt_location(BreakpointLocation* new_bpt_location) { 182 void Breakpoint::set_bpt_location(BreakpointLocation* new_bpt_location) {
165 ASSERT(bpt_location_->IsLatent()); // Only reason to move. 183 ASSERT(bpt_location_->IsLatent()); // Only reason to move.
166 bpt_location_ = new_bpt_location; 184 bpt_location_ = new_bpt_location;
167 } 185 }
168 186
169 187
170 void Breakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { 188 void Breakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
171 visitor->VisitPointer(reinterpret_cast<RawObject**>(&closure_)); 189 visitor->VisitPointer(reinterpret_cast<RawObject**>(&closure_));
172 } 190 }
173 191
174 192
175 void BreakpointLocation::VisitObjectPointers(ObjectPointerVisitor* visitor) { 193 void BreakpointLocation::VisitObjectPointers(ObjectPointerVisitor* visitor) {
176 visitor->VisitPointer(reinterpret_cast<RawObject**>(&script_)); 194 visitor->VisitPointer(reinterpret_cast<RawObject**>(&script_));
177 visitor->VisitPointer(reinterpret_cast<RawObject**>(&url_)); 195 visitor->VisitPointer(reinterpret_cast<RawObject**>(&url_));
178 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_)); 196 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_));
179 197
180 Breakpoint* bpt = conditions_; 198 Breakpoint* bpt = conditions_;
181 while (bpt != NULL) { 199 while (bpt != NULL) {
182 bpt -> VisitObjectPointers(visitor); 200 bpt -> VisitObjectPointers(visitor);
183 bpt = bpt->next(); 201 bpt = bpt->next();
184 } 202 }
185 } 203 }
186 204
187 205
188 void Breakpoint::PrintJSON(JSONStream* stream) { 206 void Breakpoint::PrintJSON(JSONStream* stream) {
189 Isolate* isolate = Isolate::Current();
190
191 JSONObject jsobj(stream); 207 JSONObject jsobj(stream);
192 jsobj.AddProperty("type", "Breakpoint"); 208 jsobj.AddProperty("type", "Breakpoint");
193 209
194 jsobj.AddFixedServiceId("breakpoints/%" Pd "", id()); 210 jsobj.AddFixedServiceId("breakpoints/%" Pd "", id());
195 jsobj.AddProperty("breakpointNumber", id()); 211 jsobj.AddProperty("breakpointNumber", id());
196 jsobj.AddProperty("resolved", bpt_location_->IsResolved()); 212 jsobj.AddProperty("resolved", bpt_location_->IsResolved());
197 213 if (bpt_location_->IsResolved()) {
198 Library& library = Library::Handle(isolate); 214 jsobj.AddLocation(bpt_location_);
199 Script& script = Script::Handle(isolate); 215 } else {
200 intptr_t token_pos; 216 jsobj.AddUnresolvedLocation(bpt_location_);
201 bpt_location_->GetCodeLocation(&library, &script, &token_pos); 217 }
202 jsobj.AddLocation(script, token_pos);
203 } 218 }
204 219
205 220
206 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { 221 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
207 visitor->VisitPointer(reinterpret_cast<RawObject**>(&code_)); 222 visitor->VisitPointer(reinterpret_cast<RawObject**>(&code_));
208 } 223 }
209 224
210 225
211 ActivationFrame::ActivationFrame( 226 ActivationFrame::ActivationFrame(
212 uword pc, 227 uword pc,
(...skipping 1382 matching lines...) Expand 10 before | Expand all | Expand 10 after
1595 intptr_t last_pos = pos; 1610 intptr_t last_pos = pos;
1596 while ((iter.CurrentTokenKind() != Token::kNEWLINE) && 1611 while ((iter.CurrentTokenKind() != Token::kNEWLINE) &&
1597 (iter.CurrentTokenKind() != Token::kEOS)) { 1612 (iter.CurrentTokenKind() != Token::kEOS)) {
1598 last_pos = iter.CurrentPosition(); 1613 last_pos = iter.CurrentPosition();
1599 iter.Advance(); 1614 iter.Advance();
1600 } 1615 }
1601 return last_pos; 1616 return last_pos;
1602 } 1617 }
1603 1618
1604 1619
1605 // Given a function and a token range, return the best fit 1620 // Returns the best fit token position for a breakpoint.
1606 // token position to set a breakpoint. The best fit is the safe point 1621 //
1607 // in the line closest to the beginning of the token range, and within 1622 // Takes a range of tokens [requested_token_pos, last_token_pos] and
1608 // that line, the safe point with the lowest compiled code address. 1623 // an optional column (requested_column). The range of tokens usually
1624 // represents one line of the program text, but can represent a larger
1625 // range on recursive calls.
1626 //
1627 // The best fit is found in two passes.
1628 //
1629 // The first pass finds a candidate token which:
1630 //
1631 // - is a safepoint,
1632 // - has the lowest column number compatible with the requested column
1633 // if a column has been specified,
1634 // and:
1635 // - has the lowest token position number which satisfies the above.
1636 //
1637 // When we consider a column number, we look for the closed token
1638 // which intersects the desired column. For example:
1639 //
1640 // 1 2 3
1641 // 12345678901234567890 0
1642 //
1643 // var x = function(function(y));
1644 // ^
1645 //
1646 // If we request a breakpoint at column 14, the lowest column number
1647 // compatible with that would for column 11 (beginning of the
1648 // 'function' token) in the example above.
1649 //
1650 // Once this candidate token from the first pass is found, we then
1651 // have a second pass which considers only those tokens on the same
1652 // line as the candidate token.
1653 //
1654 // The second pass finds a best fit token which:
1655 //
1656 // - is a safepoint,
1657 // - has the same column number as the candidate token (perhaps
1658 // more than one token has the same column number),
1659 // and:
1660 // - has the lowest code address in the generated code.
1661 //
1662 // We prefer the lowest compiled code address, because this tends to
1663 // select the first subexpression on a line. For example in a line
1664 // with nested function calls f(g(x)), the call to g() will have a
1665 // lower compiled code address than the call to f().
1666 //
1667 // If no best fit token can be found, the search is expanded,
1668 // searching through the rest of the current function by calling this
1669 // function recursively.
1670 //
1671 // TODO(turnidge): Given that we usually call this function with a
1672 // token range restricted to a single line, this could be a one-pass
1673 // algorithm, which would be simpler. I believe that it only needs
1674 // two passes to support the recursive try-the-whole-function case.
1675 // Rewrite this later, once there are more tests in place.
1609 intptr_t Debugger::ResolveBreakpointPos(const Function& func, 1676 intptr_t Debugger::ResolveBreakpointPos(const Function& func,
1610 intptr_t requested_token_pos, 1677 intptr_t requested_token_pos,
1611 intptr_t last_token_pos) { 1678 intptr_t last_token_pos,
1679 intptr_t requested_column) {
1612 ASSERT(func.HasCode()); 1680 ASSERT(func.HasCode());
1613 ASSERT(!func.HasOptimizedCode()); 1681 ASSERT(!func.HasOptimizedCode());
1614 1682
1615 if (requested_token_pos < func.token_pos()) { 1683 if (requested_token_pos < func.token_pos()) {
1616 requested_token_pos = func.token_pos(); 1684 requested_token_pos = func.token_pos();
1617 } 1685 }
1618 if (last_token_pos > func.end_token_pos()) { 1686 if (last_token_pos > func.end_token_pos()) {
1619 last_token_pos = func.end_token_pos(); 1687 last_token_pos = func.end_token_pos();
1620 } 1688 }
1621 1689
1690 Script& script = Script::Handle(func.script());
1622 Code& code = Code::Handle(func.unoptimized_code()); 1691 Code& code = Code::Handle(func.unoptimized_code());
1623 ASSERT(!code.IsNull()); 1692 ASSERT(!code.IsNull());
1624 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); 1693 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
1625 1694
1626 // First pass: find the safe point which is closest to the beginning 1695 // First pass: find the safe point which is closest to the beginning
1627 // of the given token range. 1696 // of the given token range.
1628 intptr_t best_fit_pos = INT_MAX; 1697 intptr_t best_fit_pos = INT_MAX;
1698 intptr_t best_column = INT_MAX;
1629 PcDescriptors::Iterator iter(desc, kSafepointKind); 1699 PcDescriptors::Iterator iter(desc, kSafepointKind);
1630 while (iter.MoveNext()) { 1700 while (iter.MoveNext()) {
1631 const intptr_t desc_token_pos = iter.TokenPos(); 1701 const intptr_t pos = iter.TokenPos();
1632 if ((desc_token_pos != Scanner::kNoSourcePos) && 1702 if ((pos == Scanner::kNoSourcePos) ||
1633 (desc_token_pos < best_fit_pos) && 1703 (pos < requested_token_pos) ||
1634 (desc_token_pos >= requested_token_pos) && 1704 (pos > last_token_pos)) {
1635 (desc_token_pos <= last_token_pos)) { 1705 // Token is not in the target range.
1636 best_fit_pos = desc_token_pos; 1706 continue;
1707 }
1708
1709 intptr_t token_start_column = -1;
1710 if (requested_column >= 0) {
1711 intptr_t ignored = -1;
1712 intptr_t token_len = -1;
1713 // TODO(turnidge): GetTokenLocation is a very expensive
1714 // operation, and this code will blow up when we are setting
1715 // column breakpoints on, for example, a large, single-line
1716 // program. Consider rewriting this code so that it only scans
1717 // the program code once and caches the token positions and
1718 // lengths.
1719 script.GetTokenLocation(pos, &ignored, &token_start_column, &token_len);
1720 intptr_t token_end_column = token_start_column + token_len - 1;
1721 if ((token_end_column < requested_column) ||
1722 (token_start_column > best_column)) {
1723 // Prefer the token with the lowest column number compatible
1724 // with the requested column.
1725 continue;
1726 }
1727 }
1728
1729 // Prefer the lowest (first) token pos.
1730 if (pos < best_fit_pos) {
1731 best_fit_pos = pos;
1732 best_column = token_start_column;
1637 } 1733 }
1638 } 1734 }
1639 // Second pass (if we found a safe point in the first pass): 1735
1640 // For all token positions on the same line, select the one 1736 // Second pass (if we found a safe point in the first pass). Find
1641 // with the lowest compiled code address. E.g., in a line with 1737 // the token on the line which is at the best fit column (if column
1642 // the nested function calls f(g(x)), the call g() will have a lower 1738 // was specified) and has the lowest code address.
1643 // compiled code address but is not the lowest token position in the
1644 // line.
1645 if (best_fit_pos != INT_MAX) { 1739 if (best_fit_pos != INT_MAX) {
1646 const Script& script = Script::Handle(func.script()); 1740 const Script& script = Script::Handle(func.script());
1647 const TokenStream& tokens = TokenStream::Handle(script.tokens()); 1741 const TokenStream& tokens = TokenStream::Handle(script.tokens());
1648 const intptr_t begin_pos = best_fit_pos; 1742 const intptr_t begin_pos = best_fit_pos;
1649 const intptr_t end_of_line_pos = LastTokenOnLine(tokens, begin_pos); 1743 const intptr_t end_of_line_pos = LastTokenOnLine(tokens, begin_pos);
1650 uword lowest_pc_offset = kUwordMax; 1744 uword lowest_pc_offset = kUwordMax;
1651 PcDescriptors::Iterator iter(desc, kSafepointKind); 1745 PcDescriptors::Iterator iter(desc, kSafepointKind);
1652 while (iter.MoveNext()) { 1746 while (iter.MoveNext()) {
1653 const intptr_t pos = iter.TokenPos(); 1747 const intptr_t pos = iter.TokenPos();
1654 if ((pos != Scanner::kNoSourcePos) && 1748 if ((pos == Scanner::kNoSourcePos) ||
1655 (begin_pos <= pos) && (pos <= end_of_line_pos) && 1749 (pos < begin_pos) ||
1656 (iter.PcOffset() < lowest_pc_offset)) { 1750 (pos > end_of_line_pos)) {
1751 // Token is not on same line as best fit.
1752 continue;
1753 }
1754
1755 if (requested_column >= 0) {
1756 intptr_t ignored = -1;
1757 intptr_t token_start_column = -1;
1758 // We look for other tokens at the best column in case there
1759 // is more than one token at the same column offset.
1760 script.GetTokenLocation(pos, &ignored, &token_start_column);
1761 if (token_start_column != best_column) {
1762 continue;
1763 }
1764 }
1765
1766 // Prefer the lowest pc offset.
1767 if (iter.PcOffset() < lowest_pc_offset) {
1657 lowest_pc_offset = iter.PcOffset(); 1768 lowest_pc_offset = iter.PcOffset();
1658 best_fit_pos = pos; 1769 best_fit_pos = pos;
1659 } 1770 }
1660 } 1771 }
1661 return best_fit_pos; 1772 return best_fit_pos;
1662 } 1773 }
1663 1774
1664 // We didn't find a safe point in the given token range. Try and find 1775 // 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. 1776 // find a safe point in the remaining source code of the function.
1777 // Since we have moved to the next line of the function, we no
1778 // longer are requesting a specific column number.
1666 if (last_token_pos < func.end_token_pos()) { 1779 if (last_token_pos < func.end_token_pos()) {
1667 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos()); 1780 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos(),
1781 -1 /* no column */);
1668 } 1782 }
1669 return -1; 1783 return -1;
1670 } 1784 }
1671 1785
1672 1786
1673 void Debugger::MakeCodeBreakpointAt(const Function& func, 1787 void Debugger::MakeCodeBreakpointAt(const Function& func,
1674 BreakpointLocation* loc) { 1788 BreakpointLocation* loc) {
1675 ASSERT(loc->token_pos_ != Scanner::kNoSourcePos); 1789 ASSERT(loc->token_pos_ != Scanner::kNoSourcePos);
1676 ASSERT((loc != NULL) && loc->IsResolved()); 1790 ASSERT((loc != NULL) && loc->IsResolved());
1677 ASSERT(!func.HasOptimizedCode()); 1791 ASSERT(!func.HasOptimizedCode());
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
1850 } 1964 }
1851 } 1965 }
1852 } 1966 }
1853 } 1967 }
1854 return best_fit.raw(); 1968 return best_fit.raw();
1855 } 1969 }
1856 1970
1857 1971
1858 BreakpointLocation* Debugger::SetBreakpoint(const Script& script, 1972 BreakpointLocation* Debugger::SetBreakpoint(const Script& script,
1859 intptr_t token_pos, 1973 intptr_t token_pos,
1860 intptr_t last_token_pos) { 1974 intptr_t last_token_pos,
1975 intptr_t requested_line,
1976 intptr_t requested_column) {
1861 Function& func = Function::Handle(isolate_); 1977 Function& func = Function::Handle(isolate_);
1862 func = FindBestFit(script, token_pos); 1978 func = FindBestFit(script, token_pos);
1863 if (func.IsNull()) { 1979 if (func.IsNull()) {
1864 return NULL; 1980 return NULL;
1865 } 1981 }
1866 // There may be more than one function object for a given function 1982 // There may be more than one function object for a given function
1867 // in source code. There may be implicit closure functions, and 1983 // in source code. There may be implicit closure functions, and
1868 // there may be copies of mixin functions. Collect all compiled 1984 // there may be copies of mixin functions. Collect all compiled
1869 // functions whose source code range matches exactly the best fit 1985 // functions whose source code range matches exactly the best fit
1870 // function we found. 1986 // function we found.
1871 GrowableObjectArray& functions = 1987 GrowableObjectArray& functions =
1872 GrowableObjectArray::Handle(GrowableObjectArray::New()); 1988 GrowableObjectArray::Handle(GrowableObjectArray::New());
1873 FindCompiledFunctions(script, 1989 FindCompiledFunctions(script,
1874 func.token_pos(), 1990 func.token_pos(),
1875 func.end_token_pos(), 1991 func.end_token_pos(),
1876 &functions); 1992 &functions);
1877 1993
1878 if (functions.Length() > 0) { 1994 if (functions.Length() > 0) {
1879 // One or more function object containing this breakpoint location 1995 // One or more function object containing this breakpoint location
1880 // have already been compiled. We can resolve the breakpoint now. 1996 // have already been compiled. We can resolve the breakpoint now.
1881 DeoptimizeWorld(); 1997 DeoptimizeWorld();
1882 func ^= functions.At(0); 1998 func ^= functions.At(0);
1883 intptr_t breakpoint_pos = 1999 intptr_t breakpoint_pos =
1884 ResolveBreakpointPos(func, token_pos, last_token_pos); 2000 ResolveBreakpointPos(func, token_pos, last_token_pos, requested_column);
1885 if (breakpoint_pos >= 0) { 2001 if (breakpoint_pos >= 0) {
1886 BreakpointLocation* bpt = GetBreakpointLocation(script, breakpoint_pos); 2002 BreakpointLocation* bpt =
2003 GetBreakpointLocation(script, breakpoint_pos, requested_column);
1887 if (bpt != NULL) { 2004 if (bpt != NULL) {
1888 // A source breakpoint for this location already exists. 2005 // A source breakpoint for this location already exists.
1889 return bpt; 2006 return bpt;
1890 } 2007 }
1891 bpt = new BreakpointLocation(script, token_pos, last_token_pos); 2008 bpt = new BreakpointLocation(script, token_pos, last_token_pos,
2009 requested_line, requested_column);
1892 bpt->SetResolved(func, breakpoint_pos); 2010 bpt->SetResolved(func, breakpoint_pos);
1893 RegisterBreakpointLocation(bpt); 2011 RegisterBreakpointLocation(bpt);
1894 2012
1895 // Create code breakpoints for all compiled functions we found. 2013 // Create code breakpoints for all compiled functions we found.
1896 const intptr_t num_functions = functions.Length(); 2014 const intptr_t num_functions = functions.Length();
1897 for (intptr_t i = 0; i < num_functions; i++) { 2015 for (intptr_t i = 0; i < num_functions; i++) {
1898 func ^= functions.At(i); 2016 func ^= functions.At(i);
1899 ASSERT(func.HasCode()); 2017 ASSERT(func.HasCode());
1900 MakeCodeBreakpointAt(func, bpt); 2018 MakeCodeBreakpointAt(func, bpt);
1901 } 2019 }
1902 if (FLAG_verbose_debug) { 2020 if (FLAG_verbose_debug) {
1903 intptr_t line_number; 2021 intptr_t line_number;
1904 script.GetTokenLocation(breakpoint_pos, &line_number, NULL); 2022 intptr_t column_number;
2023 script.GetTokenLocation(breakpoint_pos, &line_number, &column_number);
1905 OS::Print("Resolved BP for " 2024 OS::Print("Resolved BP for "
1906 "function '%s' at line %" Pd "\n", 2025 "function '%s' at line %" Pd " col %" Pd "\n",
1907 func.ToFullyQualifiedCString(), 2026 func.ToFullyQualifiedCString(),
1908 line_number); 2027 line_number, column_number);
1909 } 2028 }
1910 return bpt; 2029 return bpt;
1911 } 2030 }
1912 } 2031 }
1913 // There is no compiled function at this token position. 2032 // There is no compiled function at this token position.
1914 // Register an unresolved breakpoint. 2033 // Register an unresolved breakpoint.
1915 if (FLAG_verbose_debug && !func.IsNull()) { 2034 if (FLAG_verbose_debug && !func.IsNull()) {
1916 intptr_t line_number; 2035 intptr_t line_number;
1917 script.GetTokenLocation(token_pos, &line_number, NULL); 2036 intptr_t column_number;
2037 script.GetTokenLocation(token_pos, &line_number, &column_number);
1918 OS::Print("Registering pending breakpoint for " 2038 OS::Print("Registering pending breakpoint for "
1919 "uncompiled function '%s' at line %" Pd "\n", 2039 "uncompiled function '%s' at line %" Pd " col %" Pd "\n",
1920 func.ToFullyQualifiedCString(), 2040 func.ToFullyQualifiedCString(),
1921 line_number); 2041 line_number, column_number);
1922 } 2042 }
1923 BreakpointLocation* bpt = GetBreakpointLocation(script, token_pos); 2043 BreakpointLocation* bpt =
2044 GetBreakpointLocation(script, token_pos, requested_column);
1924 if (bpt == NULL) { 2045 if (bpt == NULL) {
1925 bpt = new BreakpointLocation(script, token_pos, last_token_pos); 2046 bpt = new BreakpointLocation(script, token_pos, last_token_pos,
2047 requested_line, requested_column);
1926 RegisterBreakpointLocation(bpt); 2048 RegisterBreakpointLocation(bpt);
1927 } 2049 }
1928 return bpt; 2050 return bpt;
1929 } 2051 }
1930 2052
1931 2053
1932 // Synchronize the enabled/disabled state of all code breakpoints 2054 // Synchronize the enabled/disabled state of all code breakpoints
1933 // associated with the breakpoint location loc. 2055 // associated with the breakpoint location loc.
1934 void Debugger::SyncBreakpointLocation(BreakpointLocation* loc) { 2056 void Debugger::SyncBreakpointLocation(BreakpointLocation* loc) {
1935 bool any_enabled = loc->AnyEnabled(); 2057 bool any_enabled = loc->AnyEnabled();
(...skipping 26 matching lines...) Expand all
1962 Breakpoint* Debugger::SetBreakpointAtEntry(const Function& target_function, 2084 Breakpoint* Debugger::SetBreakpointAtEntry(const Function& target_function,
1963 bool single_shot) { 2085 bool single_shot) {
1964 ASSERT(!target_function.IsNull()); 2086 ASSERT(!target_function.IsNull());
1965 if (!target_function.is_debuggable()) { 2087 if (!target_function.is_debuggable()) {
1966 return NULL; 2088 return NULL;
1967 } 2089 }
1968 const Script& script = Script::Handle(target_function.script()); 2090 const Script& script = Script::Handle(target_function.script());
1969 BreakpointLocation* bpt_location = 2091 BreakpointLocation* bpt_location =
1970 SetBreakpoint(script, 2092 SetBreakpoint(script,
1971 target_function.token_pos(), 2093 target_function.token_pos(),
1972 target_function.end_token_pos()); 2094 target_function.end_token_pos(),
2095 -1, -1 /* no requested line/col */);
1973 if (single_shot) { 2096 if (single_shot) {
1974 return bpt_location->AddSingleShot(this); 2097 return bpt_location->AddSingleShot(this);
1975 } else { 2098 } else {
1976 return bpt_location->AddRepeated(this); 2099 return bpt_location->AddRepeated(this);
1977 } 2100 }
1978 } 2101 }
1979 2102
1980 2103
1981 Breakpoint* Debugger::SetBreakpointAtActivation(const Instance& closure) { 2104 Breakpoint* Debugger::SetBreakpointAtActivation(const Instance& closure) {
1982 if (!closure.IsClosure()) { 2105 if (!closure.IsClosure()) {
1983 return NULL; 2106 return NULL;
1984 } 2107 }
1985 const Function& func = Function::Handle(Closure::function(closure)); 2108 const Function& func = Function::Handle(Closure::function(closure));
1986 const Script& script = Script::Handle(func.script()); 2109 const Script& script = Script::Handle(func.script());
1987 BreakpointLocation* bpt_location = SetBreakpoint(script, 2110 BreakpointLocation* bpt_location = SetBreakpoint(script,
1988 func.token_pos(), 2111 func.token_pos(),
1989 func.end_token_pos()); 2112 func.end_token_pos(),
2113 -1, -1 /* no line/col */);
1990 return bpt_location->AddPerClosure(this, closure); 2114 return bpt_location->AddPerClosure(this, closure);
1991 } 2115 }
1992 2116
1993 2117
1994 Breakpoint* Debugger::BreakpointAtActivation(const Instance& closure) { 2118 Breakpoint* Debugger::BreakpointAtActivation(const Instance& closure) {
1995 if (!closure.IsClosure()) { 2119 if (!closure.IsClosure()) {
1996 return NULL; 2120 return NULL;
1997 } 2121 }
1998 2122
1999 BreakpointLocation* loc = breakpoint_locations_; 2123 BreakpointLocation* loc = breakpoint_locations_;
2000 while (loc != NULL) { 2124 while (loc != NULL) {
2001 Breakpoint* bpt = loc->breakpoints(); 2125 Breakpoint* bpt = loc->breakpoints();
2002 while (bpt != NULL) { 2126 while (bpt != NULL) {
2003 if (bpt->IsPerClosure()) { 2127 if (bpt->IsPerClosure()) {
2004 if (closure.raw() == bpt->closure()) { 2128 if (closure.raw() == bpt->closure()) {
2005 return bpt; 2129 return bpt;
2006 } 2130 }
2007 } 2131 }
2008 bpt = bpt->next(); 2132 bpt = bpt->next();
2009 } 2133 }
2010 loc = loc->next(); 2134 loc = loc->next();
2011 } 2135 }
2012 2136
2013 return NULL; 2137 return NULL;
2014 } 2138 }
2015 2139
2016 2140
2017 Breakpoint* Debugger::SetBreakpointAtLine(const String& script_url, 2141 Breakpoint* Debugger::SetBreakpointAtLine(const String& script_url,
2018 intptr_t line_number) { 2142 intptr_t line_number) {
2019 BreakpointLocation* loc = BreakpointLocationAtLine(script_url, line_number); 2143 BreakpointLocation* loc =
2144 BreakpointLocationAtLineCol(script_url, line_number, -1 /* no column */);
2020 if (loc != NULL) { 2145 if (loc != NULL) {
2021 return loc->AddRepeated(this); 2146 return loc->AddRepeated(this);
2022 } 2147 }
2148 return NULL;
2149 }
2150
2151
2152 Breakpoint* Debugger::SetBreakpointAtLineCol(const String& script_url,
2153 intptr_t line_number,
2154 intptr_t column_number) {
2155 BreakpointLocation* loc = BreakpointLocationAtLineCol(script_url,
2156 line_number,
2157 column_number);
2158 if (loc != NULL) {
2159 return loc->AddRepeated(this);
2160 }
2023 return NULL; 2161 return NULL;
2024 } 2162 }
2025 2163
2026 2164
2027 BreakpointLocation* Debugger::BreakpointLocationAtLine(const String& script_url, 2165 BreakpointLocation* Debugger::BreakpointLocationAtLineCol(
2028 intptr_t line_number) { 2166 const String& script_url,
2167 intptr_t line_number,
2168 intptr_t column_number) {
2029 Library& lib = Library::Handle(isolate_); 2169 Library& lib = Library::Handle(isolate_);
2030 Script& script = Script::Handle(isolate_); 2170 Script& script = Script::Handle(isolate_);
2031 const GrowableObjectArray& libs = 2171 const GrowableObjectArray& libs =
2032 GrowableObjectArray::Handle(isolate_->object_store()->libraries()); 2172 GrowableObjectArray::Handle(isolate_->object_store()->libraries());
2033 const GrowableObjectArray& scripts = 2173 const GrowableObjectArray& scripts =
2034 GrowableObjectArray::Handle(isolate_, GrowableObjectArray::New()); 2174 GrowableObjectArray::Handle(isolate_, GrowableObjectArray::New());
2035 for (intptr_t i = 0; i < libs.Length(); i++) { 2175 for (intptr_t i = 0; i < libs.Length(); i++) {
2036 lib ^= libs.At(i); 2176 lib ^= libs.At(i);
2037 script = lib.LookupScript(script_url); 2177 script = lib.LookupScript(script_url);
2038 if (!script.IsNull()) { 2178 if (!script.IsNull()) {
2039 scripts.Add(script); 2179 scripts.Add(script);
2040 } 2180 }
2041 } 2181 }
2042 if (scripts.Length() == 0) { 2182 if (scripts.Length() == 0) {
2043 // No script found with given url. Create a latent breakpoint which 2183 // No script found with given url. Create a latent breakpoint which
2044 // will be set if the url is loaded later. 2184 // will be set if the url is loaded later.
2045 BreakpointLocation* latent_bpt = GetLatentBreakpoint(script_url, 2185 BreakpointLocation* latent_bpt = GetLatentBreakpoint(script_url,
2046 line_number); 2186 line_number,
2187 column_number);
2047 if (FLAG_verbose_debug) { 2188 if (FLAG_verbose_debug) {
2048 OS::Print("Set latent breakpoint in url '%s' at line %" Pd "\n", 2189 OS::Print("Set latent breakpoint in url '%s' at "
2190 "line %" Pd " col %" Pd "\n",
2049 script_url.ToCString(), 2191 script_url.ToCString(),
2050 line_number); 2192 line_number, column_number);
2051 } 2193 }
2052 return latent_bpt; 2194 return latent_bpt;
2053 } 2195 }
2054 if (scripts.Length() > 1) { 2196 if (scripts.Length() > 1) {
2055 if (FLAG_verbose_debug) { 2197 if (FLAG_verbose_debug) {
2056 OS::Print("Multiple scripts match url '%s'\n", script_url.ToCString()); 2198 OS::Print("Multiple scripts match url '%s'\n", script_url.ToCString());
2057 } 2199 }
2058 return NULL; 2200 return NULL;
2059 } 2201 }
2060 script ^= scripts.At(0); 2202 script ^= scripts.At(0);
(...skipping 11 matching lines...) Expand all
2072 if (FLAG_verbose_debug) { 2214 if (FLAG_verbose_debug) {
2073 OS::Print("No executable code at line %" Pd " in '%s'\n", 2215 OS::Print("No executable code at line %" Pd " in '%s'\n",
2074 line_number, script_url.ToCString()); 2216 line_number, script_url.ToCString());
2075 } 2217 }
2076 return NULL; 2218 return NULL;
2077 } 2219 }
2078 2220
2079 BreakpointLocation* bpt = NULL; 2221 BreakpointLocation* bpt = NULL;
2080 ASSERT(first_token_idx <= last_token_idx); 2222 ASSERT(first_token_idx <= last_token_idx);
2081 while ((bpt == NULL) && (first_token_idx <= last_token_idx)) { 2223 while ((bpt == NULL) && (first_token_idx <= last_token_idx)) {
2082 bpt = SetBreakpoint(script, first_token_idx, last_token_idx); 2224 bpt = SetBreakpoint(script, first_token_idx, last_token_idx,
2225 line_number, column_number);
2083 first_token_idx++; 2226 first_token_idx++;
2084 } 2227 }
2085 if ((bpt == NULL) && FLAG_verbose_debug) { 2228 if ((bpt == NULL) && FLAG_verbose_debug) {
2086 OS::Print("No executable code at line %" Pd " in '%s'\n", 2229 OS::Print("No executable code at line %" Pd " in '%s'\n",
2087 line_number, script_url.ToCString()); 2230 line_number, script_url.ToCString());
2088 } 2231 }
2089 return bpt; 2232 return bpt;
2090 } 2233 }
2091 2234
2092 2235
(...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after
2673 // TODO(hausner): What should we do if function is optimized? 2816 // TODO(hausner): What should we do if function is optimized?
2674 // Can we deoptimize the function? 2817 // Can we deoptimize the function?
2675 ASSERT(!func.HasOptimizedCode()); 2818 ASSERT(!func.HasOptimizedCode());
2676 2819
2677 // There is no local function within func that contains the 2820 // There is no local function within func that contains the
2678 // breakpoint token position. Resolve the breakpoint if necessary 2821 // breakpoint token position. Resolve the breakpoint if necessary
2679 // and set the code breakpoints. 2822 // and set the code breakpoints.
2680 if (!loc->IsResolved()) { 2823 if (!loc->IsResolved()) {
2681 // Resolve source breakpoint in the newly compiled function. 2824 // Resolve source breakpoint in the newly compiled function.
2682 intptr_t bp_pos = 2825 intptr_t bp_pos =
2683 ResolveBreakpointPos(func, loc->token_pos(), loc->end_token_pos()); 2826 ResolveBreakpointPos(func, loc->token_pos(), loc->end_token_pos(),
2827 loc->requested_column_number());
2684 if (bp_pos < 0) { 2828 if (bp_pos < 0) {
2685 if (FLAG_verbose_debug) { 2829 if (FLAG_verbose_debug) {
2686 OS::Print("Failed resolving breakpoint for function '%s'\n", 2830 OS::Print("Failed resolving breakpoint for function '%s'\n",
2687 String::Handle(func.name()).ToCString()); 2831 String::Handle(func.name()).ToCString());
2688 } 2832 }
2689 continue; 2833 continue;
2690 } 2834 }
2691 intptr_t requested_pos = loc->token_pos(); 2835 intptr_t requested_pos = loc->token_pos();
2692 intptr_t requested_end_pos = loc->end_token_pos(); 2836 intptr_t requested_end_pos = loc->end_token_pos();
2693 loc->SetResolved(func, bp_pos); 2837 loc->SetResolved(func, bp_pos);
2694 Breakpoint* bpt = loc->breakpoints(); 2838 Breakpoint* bpt = loc->breakpoints();
2695 while (bpt != NULL) { 2839 while (bpt != NULL) {
2696 if (FLAG_verbose_debug) { 2840 if (FLAG_verbose_debug) {
2697 OS::Print("Resolved BP %" Pd " to pos %" Pd ", line %" Pd ", " 2841 OS::Print("Resolved BP %" Pd " to pos %" Pd ", "
2698 "function '%s' (requested range %" Pd "-%" Pd ")\n", 2842 "line %" Pd " col %" Pd ", "
2843 "function '%s' (requested range %" Pd "-%" Pd ", "
2844 "requested col %" Pd ")\n",
2699 bpt->id(), 2845 bpt->id(),
2700 loc->token_pos(), 2846 loc->token_pos(),
2701 loc->LineNumber(), 2847 loc->LineNumber(),
2848 loc->ColumnNumber(),
2702 func.ToFullyQualifiedCString(), 2849 func.ToFullyQualifiedCString(),
2703 requested_pos, 2850 requested_pos,
2704 requested_end_pos); 2851 requested_end_pos,
2852 loc->requested_column_number());
2705 } 2853 }
2706 SignalBpResolved(bpt); 2854 SignalBpResolved(bpt);
2707 SendServiceBreakpointEvent(ServiceEvent::kBreakpointResolved, bpt); 2855 SendServiceBreakpointEvent(ServiceEvent::kBreakpointResolved, bpt);
2708 bpt = bpt->next(); 2856 bpt = bpt->next();
2709 } 2857 }
2710 } 2858 }
2711 ASSERT(loc->IsResolved()); 2859 ASSERT(loc->IsResolved());
2712 if (FLAG_verbose_debug) { 2860 if (FLAG_verbose_debug) {
2713 Breakpoint* bpt = loc->breakpoints(); 2861 Breakpoint* bpt = loc->breakpoints();
2714 while (bpt != NULL) { 2862 while (bpt != NULL) {
2715 OS::Print("Setting breakpoint %" Pd " at line %" Pd " for %s '%s'\n", 2863 OS::Print("Setting breakpoint %" Pd " at line %" Pd " col %" Pd ""
2864 " for %s '%s'\n",
2716 bpt->id(), 2865 bpt->id(),
2717 loc->LineNumber(), 2866 loc->LineNumber(),
2867 loc->ColumnNumber(),
2718 func.IsClosureFunction() ? "closure" : "function", 2868 func.IsClosureFunction() ? "closure" : "function",
2719 String::Handle(func.name()).ToCString()); 2869 String::Handle(func.name()).ToCString());
2720 bpt = bpt->next(); 2870 bpt = bpt->next();
2721 } 2871 }
2722 } 2872 }
2723 MakeCodeBreakpointAt(func, loc); 2873 MakeCodeBreakpointAt(func, loc);
2724 } 2874 }
2725 } 2875 }
2726 } 2876 }
2727 2877
(...skipping 22 matching lines...) Expand all
2750 found_match = true; 2900 found_match = true;
2751 BreakpointLocation* matched_loc = loc; 2901 BreakpointLocation* matched_loc = loc;
2752 loc = loc->next(); 2902 loc = loc->next();
2753 if (prev_loc == NULL) { 2903 if (prev_loc == NULL) {
2754 latent_locations_ = loc; 2904 latent_locations_ = loc;
2755 } else { 2905 } else {
2756 prev_loc->set_next(loc); 2906 prev_loc->set_next(loc);
2757 } 2907 }
2758 // Now find the token range at the requested line and make a 2908 // Now find the token range at the requested line and make a
2759 // new unresolved source breakpoint. 2909 // new unresolved source breakpoint.
2760 intptr_t line_number = matched_loc->LineNumber(); 2910 intptr_t line_number = matched_loc->requested_line_number();
2911 intptr_t column_number = matched_loc->requested_column_number();
2761 ASSERT(line_number >= 0); 2912 ASSERT(line_number >= 0);
2762 intptr_t first_token_pos, last_token_pos; 2913 intptr_t first_token_pos, last_token_pos;
2763 script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos); 2914 script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos);
2764 if ((first_token_pos < 0) || 2915 if ((first_token_pos < 0) ||
2765 (last_token_pos < 0)) { 2916 (last_token_pos < 0)) {
2766 // Script does not contain the given line number or there are no 2917 // Script does not contain the given line number or there are no
2767 // tokens on the line. Drop the breakpoint silently. 2918 // tokens on the line. Drop the breakpoint silently.
2768 Breakpoint* bpt = matched_loc->breakpoints(); 2919 Breakpoint* bpt = matched_loc->breakpoints();
2769 while (bpt != NULL) { 2920 while (bpt != NULL) {
2770 if (FLAG_verbose_debug) { 2921 if (FLAG_verbose_debug) {
2771 OS::Print("No code found at line %" Pd ": " 2922 OS::Print("No code found at line %" Pd ": "
2772 "dropping latent breakpoint %" Pd " in '%s'\n", 2923 "dropping latent breakpoint %" Pd " in '%s'\n",
2773 line_number, 2924 line_number,
2774 bpt->id(), 2925 bpt->id(),
2775 url.ToCString()); 2926 url.ToCString());
2776 } 2927 }
2777 Breakpoint* prev = bpt; 2928 Breakpoint* prev = bpt;
2778 bpt = bpt->next(); 2929 bpt = bpt->next();
2779 delete prev; 2930 delete prev;
2780 } 2931 }
2781 delete matched_loc; 2932 delete matched_loc;
2782 } else { 2933 } else {
2783 // We don't expect to already have a breakpoint for this location. 2934 // We don't expect to already have a breakpoint for this location.
2784 // If there is one, assert in debug build but silently drop 2935 // If there is one, assert in debug build but silently drop
2785 // the latent breakpoint in release build. 2936 // the latent breakpoint in release build.
2786 BreakpointLocation* existing_loc = 2937 BreakpointLocation* existing_loc =
2787 GetBreakpointLocation(script, first_token_pos); 2938 GetBreakpointLocation(script, first_token_pos, column_number);
2788 ASSERT(existing_loc == NULL); 2939 ASSERT(existing_loc == NULL);
2789 if (existing_loc == NULL) { 2940 if (existing_loc == NULL) {
2790 // Create and register a new source breakpoint for the 2941 // Create and register a new source breakpoint for the
2791 // latent breakpoint. 2942 // latent breakpoint.
2792 BreakpointLocation* unresolved_loc = 2943 BreakpointLocation* unresolved_loc =
2793 new BreakpointLocation(script, 2944 new BreakpointLocation(script,
2794 first_token_pos, 2945 first_token_pos, last_token_pos,
2795 last_token_pos); 2946 line_number, column_number);
2796 RegisterBreakpointLocation(unresolved_loc); 2947 RegisterBreakpointLocation(unresolved_loc);
2797 2948
2798 // Move breakpoints over. 2949 // Move breakpoints over.
2799 Breakpoint* bpt = matched_loc->breakpoints(); 2950 Breakpoint* bpt = matched_loc->breakpoints();
2800 unresolved_loc->set_breakpoints(bpt); 2951 unresolved_loc->set_breakpoints(bpt);
2801 matched_loc->set_breakpoints(NULL); 2952 matched_loc->set_breakpoints(NULL);
2802 while (bpt != NULL) { 2953 while (bpt != NULL) {
2803 bpt->set_bpt_location(unresolved_loc); 2954 bpt->set_bpt_location(unresolved_loc);
2804 if (FLAG_verbose_debug) { 2955 if (FLAG_verbose_debug) {
2805 OS::Print("Converted latent breakpoint " 2956 OS::Print("Converted latent breakpoint "
2806 "%" Pd " in '%s' at line %" Pd "\n", 2957 "%" Pd " in '%s' at line %" Pd " col %" Pd "\n",
2807 bpt->id(), 2958 bpt->id(),
2808 url.ToCString(), 2959 url.ToCString(),
2809 line_number); 2960 line_number, column_number);
2810 } 2961 }
2811 bpt = bpt->next(); 2962 bpt = bpt->next();
2812 } 2963 }
2813 SyncBreakpointLocation(unresolved_loc); 2964 SyncBreakpointLocation(unresolved_loc);
2814 } 2965 }
2815 delete matched_loc; 2966 delete matched_loc;
2816 // Break out of the iteration over loaded libraries. If the 2967 // Break out of the iteration over loaded libraries. If the
2817 // same url has been loaded into more than one library, we 2968 // same url has been loaded into more than one library, we
2818 // only set a breakpoint in the first one. 2969 // only set a breakpoint in the first one.
2819 // TODO(hausner): There is one possible pitfall here. 2970 // TODO(hausner): There is one possible pitfall here.
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
2963 delete temp_bpt; 3114 delete temp_bpt;
2964 } else { 3115 } else {
2965 prev_bpt = curr_bpt; 3116 prev_bpt = curr_bpt;
2966 curr_bpt = curr_bpt->next(); 3117 curr_bpt = curr_bpt->next();
2967 } 3118 }
2968 } 3119 }
2969 } 3120 }
2970 3121
2971 3122
2972 BreakpointLocation* Debugger::GetBreakpointLocation(const Script& script, 3123 BreakpointLocation* Debugger::GetBreakpointLocation(const Script& script,
2973 intptr_t token_pos) { 3124 intptr_t token_pos,
3125 intptr_t requested_column) {
2974 BreakpointLocation* bpt = breakpoint_locations_; 3126 BreakpointLocation* bpt = breakpoint_locations_;
2975 while (bpt != NULL) { 3127 while (bpt != NULL) {
2976 if ((bpt->script_ == script.raw()) && (bpt->token_pos_ == token_pos)) { 3128 if ((bpt->script_ == script.raw()) &&
3129 (bpt->token_pos_ == token_pos) &&
3130 (bpt->requested_column_number_ == requested_column)) {
2977 return bpt; 3131 return bpt;
2978 } 3132 }
2979 bpt = bpt->next(); 3133 bpt = bpt->next();
2980 } 3134 }
2981 return NULL; 3135 return NULL;
2982 } 3136 }
2983 3137
2984 3138
2985 Breakpoint* Debugger::GetBreakpointById(intptr_t id) { 3139 Breakpoint* Debugger::GetBreakpointById(intptr_t id) {
2986 BreakpointLocation* loc = breakpoint_locations_; 3140 BreakpointLocation* loc = breakpoint_locations_;
2987 while (loc != NULL) { 3141 while (loc != NULL) {
2988 Breakpoint* bpt = loc->breakpoints(); 3142 Breakpoint* bpt = loc->breakpoints();
2989 while (bpt != NULL) { 3143 while (bpt != NULL) {
2990 if (bpt->id() == id) { 3144 if (bpt->id() == id) {
2991 return bpt; 3145 return bpt;
2992 } 3146 }
2993 bpt = bpt->next(); 3147 bpt = bpt->next();
2994 } 3148 }
2995 loc = loc->next(); 3149 loc = loc->next();
2996 } 3150 }
2997 return NULL; 3151 return NULL;
2998 } 3152 }
2999 3153
3000 3154
3001 BreakpointLocation* Debugger::GetLatentBreakpoint(const String& url, 3155 BreakpointLocation* Debugger::GetLatentBreakpoint(const String& url,
3002 intptr_t line) { 3156 intptr_t line,
3157 intptr_t column) {
3003 BreakpointLocation* bpt = latent_locations_; 3158 BreakpointLocation* bpt = latent_locations_;
3004 String& bpt_url = String::Handle(isolate_); 3159 String& bpt_url = String::Handle(isolate_);
3005 while (bpt != NULL) { 3160 while (bpt != NULL) {
3006 bpt_url = bpt->url(); 3161 bpt_url = bpt->url();
3007 if (bpt_url.Equals(url) && (bpt->LineNumber() == line)) { 3162 if (bpt_url.Equals(url) &&
3163 (bpt->requested_line_number() == line) &&
3164 (bpt->requested_column_number() == column)) {
3008 return bpt; 3165 return bpt;
3009 } 3166 }
3010 bpt = bpt->next(); 3167 bpt = bpt->next();
3011 } 3168 }
3012 // No breakpint for this url and line requested. Allocate new one. 3169 // No breakpoint for this location requested. Allocate new one.
3013 bpt = new BreakpointLocation(url, line); 3170 bpt = new BreakpointLocation(url, line, column);
3014 bpt->set_next(latent_locations_); 3171 bpt->set_next(latent_locations_);
3015 latent_locations_ = bpt; 3172 latent_locations_ = bpt;
3016 return bpt; 3173 return bpt;
3017 } 3174 }
3018 3175
3019 3176
3020 void Debugger::RegisterBreakpointLocation(BreakpointLocation* bpt) { 3177 void Debugger::RegisterBreakpointLocation(BreakpointLocation* bpt) {
3021 ASSERT(bpt->next() == NULL); 3178 ASSERT(bpt->next() == NULL);
3022 bpt->set_next(breakpoint_locations_); 3179 bpt->set_next(breakpoint_locations_);
3023 breakpoint_locations_ = bpt; 3180 breakpoint_locations_ = bpt;
3024 } 3181 }
3025 3182
3026 3183
3027 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 3184 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
3028 ASSERT(bpt->next() == NULL); 3185 ASSERT(bpt->next() == NULL);
3029 bpt->set_next(code_breakpoints_); 3186 bpt->set_next(code_breakpoints_);
3030 code_breakpoints_ = bpt; 3187 code_breakpoints_ = bpt;
3031 } 3188 }
3032 3189
3033 } // namespace dart 3190 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/debugger_api_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698