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

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

Issue 1146173003: Per-closure breakpoints; restructure breakpoint implementation to keep a list of conditions. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 7 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
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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 } 55 }
56 56
57 private: 57 private:
58 GrowableObjectArray* objs_; 58 GrowableObjectArray* objs_;
59 59
60 DISALLOW_COPY_AND_ASSIGN(RemoteObjectCache); 60 DISALLOW_COPY_AND_ASSIGN(RemoteObjectCache);
61 }; 61 };
62 62
63 63
64 // Create an unresolved breakpoint in given token range and script. 64 // Create an unresolved breakpoint in given token range and script.
65 SourceBreakpoint::SourceBreakpoint(intptr_t id, 65 SourceBreakpoint::SourceBreakpoint(const Script& script,
66 const Script& script,
67 intptr_t token_pos, 66 intptr_t token_pos,
68 intptr_t end_token_pos) 67 intptr_t end_token_pos)
69 : id_(id), 68 : script_(script.raw()),
70 script_(script.raw()),
71 url_(script.url()), 69 url_(script.url()),
72 token_pos_(token_pos), 70 token_pos_(token_pos),
73 end_token_pos_(end_token_pos), 71 end_token_pos_(end_token_pos),
74 is_resolved_(false), 72 is_resolved_(false),
75 is_enabled_(false), 73 is_enabled_(false),
76 is_one_shot_(false),
77 next_(NULL), 74 next_(NULL),
75 conditions_(NULL),
78 function_(Function::null()), 76 function_(Function::null()),
79 line_number_(-1) { 77 line_number_(-1) {
80 ASSERT(id_ > 0);
81 ASSERT(!script.IsNull()); 78 ASSERT(!script.IsNull());
82 ASSERT(token_pos_ >= 0); 79 ASSERT(token_pos_ >= 0);
83 } 80 }
84 81
85 // Create a latent breakpoint at given url and line number. 82 // Create a latent breakpoint at given url and line number.
86 SourceBreakpoint::SourceBreakpoint(intptr_t id, 83 SourceBreakpoint::SourceBreakpoint(const String& url,
87 const String& url,
88 intptr_t line_number) 84 intptr_t line_number)
89 : id_(id), 85 : script_(Script::null()),
90 script_(Script::null()),
91 url_(url.raw()), 86 url_(url.raw()),
92 token_pos_(-1), 87 token_pos_(-1),
93 end_token_pos_(-1), 88 end_token_pos_(-1),
94 is_resolved_(false), 89 is_resolved_(false),
95 is_enabled_(false), 90 is_enabled_(false),
96 is_one_shot_(false),
97 next_(NULL), 91 next_(NULL),
92 conditions_(NULL),
98 function_(Function::null()), 93 function_(Function::null()),
99 line_number_(line_number) { 94 line_number_(line_number) {
100 ASSERT(id >= 0);
101 ASSERT(line_number_ >= 0); 95 ASSERT(line_number_ >= 0);
102 } 96 }
103 97
104 void SourceBreakpoint::Enable() { 98 void SourceBreakpoint::Enable() {
105 is_enabled_ = true; 99 is_enabled_ = true;
106 Isolate::Current()->debugger()->SyncBreakpoint(this); 100 Isolate::Current()->debugger()->SyncBreakpoint(this);
107 } 101 }
108 102
109 103
110 void SourceBreakpoint::Disable() { 104 void SourceBreakpoint::Disable() {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 ASSERT(!IsLatent() || line_number_ >= 0); 151 ASSERT(!IsLatent() || line_number_ >= 0);
158 // Compute line number lazily since it causes scanning of the script. 152 // Compute line number lazily since it causes scanning of the script.
159 if (line_number_ < 0) { 153 if (line_number_ < 0) {
160 const Script& script = Script::Handle(this->script()); 154 const Script& script = Script::Handle(this->script());
161 script.GetTokenLocation(token_pos_, &line_number_, NULL); 155 script.GetTokenLocation(token_pos_, &line_number_, NULL);
162 } 156 }
163 return line_number_; 157 return line_number_;
164 } 158 }
165 159
166 160
161 void BreakpointCondition::set_src_bpt(SourceBreakpoint* new_src_bpt) {
162 ASSERT(src_bpt_->IsLatent()); // Only reason to move.
163 src_bpt_ = new_src_bpt;
164 }
165
166
167 void BreakpointCondition::VisitObjectPointers(ObjectPointerVisitor* visitor) {
168 visitor->VisitPointer(reinterpret_cast<RawObject**>(&closure_));
169 }
170
171
167 void SourceBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { 172 void SourceBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
168 visitor->VisitPointer(reinterpret_cast<RawObject**>(&script_)); 173 visitor->VisitPointer(reinterpret_cast<RawObject**>(&script_));
169 visitor->VisitPointer(reinterpret_cast<RawObject**>(&url_)); 174 visitor->VisitPointer(reinterpret_cast<RawObject**>(&url_));
170 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_)); 175 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_));
176
177 BreakpointCondition* cond = conditions_;
178 while (cond != NULL) {
179 cond -> VisitObjectPointers(visitor);
180 cond = cond->next();
181 }
171 } 182 }
172 183
173 184
174 void SourceBreakpoint::PrintJSON(JSONStream* stream) { 185 void BreakpointCondition::PrintJSON(JSONStream* stream) {
175 Isolate* isolate = Isolate::Current(); 186 Isolate* isolate = Isolate::Current();
176 187
177 JSONObject jsobj(stream); 188 JSONObject jsobj(stream);
178 jsobj.AddProperty("type", "Breakpoint"); 189 jsobj.AddProperty("type", "Breakpoint");
179 190
180 jsobj.AddPropertyF("id", "breakpoints/%" Pd "", id()); 191 jsobj.AddPropertyF("id", "breakpoints/%" Pd "", id());
181 jsobj.AddProperty("breakpointNumber", id()); 192 jsobj.AddProperty("breakpointNumber", id());
182 jsobj.AddProperty("resolved", IsResolved()); 193 jsobj.AddProperty("resolved", src_bpt_->IsResolved());
183 194
184 Library& library = Library::Handle(isolate); 195 Library& library = Library::Handle(isolate);
185 Script& script = Script::Handle(isolate); 196 Script& script = Script::Handle(isolate);
186 intptr_t token_pos; 197 intptr_t token_pos;
187 GetCodeLocation(&library, &script, &token_pos); 198 src_bpt_->GetCodeLocation(&library, &script, &token_pos);
188 { 199 {
189 JSONObject location(&jsobj, "location"); 200 JSONObject location(&jsobj, "location");
190 location.AddProperty("type", "Location"); 201 location.AddProperty("type", "Location");
191 location.AddProperty("script", script); 202 location.AddProperty("script", script);
192 location.AddProperty("tokenPos", token_pos); 203 location.AddProperty("tokenPos", token_pos);
193 } 204 }
194 } 205 }
195 206
196 207
197 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { 208 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 Debugger* debugger = Isolate::Current()->debugger(); 297 Debugger* debugger = Isolate::Current()->debugger();
287 ASSERT(debugger != NULL); 298 ASSERT(debugger != NULL);
288 debugger->SignalIsolateEvent(DebuggerEvent::kIsolateInterrupted); 299 debugger->SignalIsolateEvent(DebuggerEvent::kIsolateInterrupted);
289 } 300 }
290 } 301 }
291 302
292 303
293 // The vm service handles breakpoint notifications in a different way 304 // The vm service handles breakpoint notifications in a different way
294 // than the regular debugger breakpoint notifications. 305 // than the regular debugger breakpoint notifications.
295 static void SendServiceBreakpointEvent(ServiceEvent::EventType type, 306 static void SendServiceBreakpointEvent(ServiceEvent::EventType type,
296 SourceBreakpoint* bpt) { 307 BreakpointCondition* bpt) {
297 if (Service::NeedsEvents()) { 308 if (Service::NeedsEvents()) {
298 ServiceEvent service_event(Isolate::Current(), type); 309 ServiceEvent service_event(Isolate::Current(), type);
299 service_event.set_breakpoint(bpt); 310 service_event.set_breakpoint(bpt);
300 Service::HandleEvent(&service_event); 311 Service::HandleEvent(&service_event);
301 } 312 }
302 } 313 }
303 314
304 315
316 BreakpointCondition* SourceBreakpoint::AddRepeated(Debugger* dbg) {
317 BreakpointCondition* cond = conditions();
318 while (cond != NULL) {
319 if (cond->IsRepeated()) break;
320 cond = cond->next();
321 }
322 if (cond == NULL) {
323 cond = new BreakpointCondition(dbg->nextId(), this);
324 cond->SetIsRepeated();
325 cond->set_next(conditions());
326 set_conditions(cond);
327
328 if (IsResolved()) {
329 dbg->SignalBpResolved(cond);
330 }
331 SendServiceBreakpointEvent(ServiceEvent::kBreakpointAdded, cond);
332 }
333 return cond;
334 }
335
336
337 BreakpointCondition* SourceBreakpoint::AddSingleShot(Debugger* dbg) {
338 BreakpointCondition* cond = conditions();
339 while (cond != NULL) {
340 if (cond->IsSingleShot()) break;
341 cond = cond->next();
342 }
343 if (cond == NULL) {
344 cond = new BreakpointCondition(dbg->nextId(), this);
345 cond->SetIsSingleShot();
346 cond->set_next(conditions());
347 set_conditions(cond);
348
349 if (IsResolved()) {
350 dbg->SignalBpResolved(cond);
351 }
352 SendServiceBreakpointEvent(ServiceEvent::kBreakpointAdded, cond);
353 }
354 return cond;
355 }
356
357
358 BreakpointCondition* SourceBreakpoint::AddPerClosure(Debugger* dbg,
359 const Instance& closure) {
360 BreakpointCondition* cond = conditions();
361 while (cond != NULL) {
362 if (cond->IsPerClosure() && cond->closure() == closure.raw()) break;
363 cond = cond->next();
364 }
365 if (cond == NULL) {
366 cond = new BreakpointCondition(dbg->nextId(), this);
367 cond->SetIsPerClosure(closure);
368 cond->set_next(conditions());
369 set_conditions(cond);
370
371 if (IsResolved()) {
372 dbg->SignalBpResolved(cond);
373 }
374 SendServiceBreakpointEvent(ServiceEvent::kBreakpointAdded, cond);
375 }
376 return cond;
377 }
378
379
305 const char* Debugger::QualifiedFunctionName(const Function& func) { 380 const char* Debugger::QualifiedFunctionName(const Function& func) {
306 const String& func_name = String::Handle(func.name()); 381 const String& func_name = String::Handle(func.name());
307 Class& func_class = Class::Handle(func.Owner()); 382 Class& func_class = Class::Handle(func.Owner());
308 String& class_name = String::Handle(func_class.Name()); 383 String& class_name = String::Handle(func_class.Name());
309 384
310 const char* kFormat = "%s%s%s"; 385 const char* kFormat = "%s%s%s";
311 intptr_t len = OS::SNPrint(NULL, 0, kFormat, 386 intptr_t len = OS::SNPrint(NULL, 0, kFormat,
312 func_class.IsTopLevel() ? "" : class_name.ToCString(), 387 func_class.IsTopLevel() ? "" : class_name.ToCString(),
313 func_class.IsTopLevel() ? "" : ".", 388 func_class.IsTopLevel() ? "" : ".",
314 func_name.ToCString()); 389 func_name.ToCString());
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 } 446 }
372 cbpt = cbpt->next_; 447 cbpt = cbpt->next_;
373 } 448 }
374 return false; 449 return false;
375 } 450 }
376 451
377 452
378 void Debugger::PrintBreakpointsToJSONArray(JSONArray* jsarr) const { 453 void Debugger::PrintBreakpointsToJSONArray(JSONArray* jsarr) const {
379 SourceBreakpoint* sbpt = src_breakpoints_; 454 SourceBreakpoint* sbpt = src_breakpoints_;
380 while (sbpt != NULL) { 455 while (sbpt != NULL) {
381 jsarr->AddValue(sbpt); 456 BreakpointCondition* cond = sbpt->conditions();
457 while (cond != NULL) {
458 jsarr->AddValue(cond);
459 cond = cond->next();
460 }
382 sbpt = sbpt->next_; 461 sbpt = sbpt->next_;
383 } 462 }
384 } 463 }
385 464
386 465
387 RawString* ActivationFrame::QualifiedFunctionName() { 466 RawString* ActivationFrame::QualifiedFunctionName() {
388 return String::New(Debugger::QualifiedFunctionName(function())); 467 return String::New(Debugger::QualifiedFunctionName(function()));
389 } 468 }
390 469
391 470
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
668 vars_initialized_ = true; 747 vars_initialized_ = true;
669 } 748 }
670 749
671 750
672 intptr_t ActivationFrame::NumLocalVariables() { 751 intptr_t ActivationFrame::NumLocalVariables() {
673 GetDescIndices(); 752 GetDescIndices();
674 return desc_indices_.length(); 753 return desc_indices_.length();
675 } 754 }
676 755
677 756
757 RawObject* ActivationFrame::GetParameter(intptr_t index) {
758 intptr_t num_parameters = function().num_fixed_parameters();
759 ASSERT(0 <= index && index < num_parameters);
760 intptr_t reverse_index = num_parameters - index;
761
762 if (function().NumOptionalParameters() > 0) {
763 // If the function has optional parameters, the first positional parameter
764 // can be in a number of places in the caller's frame depending on how many
765 // were actually supplied at the call site, but they are copied to a fixed
766 // place in the callee's frame.
767 uword var_address = fp() + ((kFirstLocalSlotFromFp - index) * kWordSize);
768 return reinterpret_cast<RawObject*>(
769 *reinterpret_cast<uword*>(var_address));
770 } else {
771 uword var_address = fp() + (kParamEndSlotFromFp * kWordSize)
772 + (reverse_index * kWordSize);
773 return reinterpret_cast<RawObject*>(
774 *reinterpret_cast<uword*>(var_address));
775 }
776 }
777
778
779 RawObject* ActivationFrame::GetClosure() {
780 ASSERT(function().IsClosureFunction());
781 return GetParameter(0);
782 }
783
784
678 RawObject* ActivationFrame::GetLocalVar(intptr_t slot_index) { 785 RawObject* ActivationFrame::GetLocalVar(intptr_t slot_index) {
679 if (deopt_frame_.IsNull()) { 786 if (deopt_frame_.IsNull()) {
680 uword var_address = fp() + slot_index * kWordSize; 787 uword var_address = fp() + slot_index * kWordSize;
681 return reinterpret_cast<RawObject*>( 788 return reinterpret_cast<RawObject*>(
682 *reinterpret_cast<uword*>(var_address)); 789 *reinterpret_cast<uword*>(var_address));
683 } else { 790 } else {
684 return deopt_frame_.At(deopt_frame_offset_ + slot_index); 791 return deopt_frame_.At(deopt_frame_offset_ + slot_index);
685 } 792 }
686 } 793 }
687 794
(...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after
1185 if (function.HasOptimizedCode()) { 1292 if (function.HasOptimizedCode()) {
1186 function.SwitchToUnoptimizedCode(); 1293 function.SwitchToUnoptimizedCode();
1187 } 1294 }
1188 } 1295 }
1189 } 1296 }
1190 } 1297 }
1191 } 1298 }
1192 } 1299 }
1193 1300
1194 1301
1195 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { 1302 void Debugger::SignalBpResolved(BreakpointCondition* cond) {
1196 if (HasEventHandler() && !bpt->IsOneShot()) { 1303 if (HasEventHandler()) {
1197 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointResolved); 1304 if (!cond->IsSingleShot()) {
1198 event.set_breakpoint(bpt); 1305 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointResolved);
1199 InvokeEventHandler(&event); 1306 event.set_breakpoint(cond);
1307 InvokeEventHandler(&event);
1308 }
1200 } 1309 }
1201 } 1310 }
1202 1311
1203 1312
1204 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate, 1313 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate,
1205 uword pc, 1314 uword pc,
1206 StackFrame* frame, 1315 StackFrame* frame,
1207 const Code& code, 1316 const Code& code,
1208 const Array& deopt_frame, 1317 const Array& deopt_frame,
1209 intptr_t deopt_frame_offset) { 1318 intptr_t deopt_frame_offset) {
(...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after
1721 DeoptimizeWorld(); 1830 DeoptimizeWorld();
1722 func ^= functions.At(0); 1831 func ^= functions.At(0);
1723 intptr_t breakpoint_pos = 1832 intptr_t breakpoint_pos =
1724 ResolveBreakpointPos(func, token_pos, last_token_pos); 1833 ResolveBreakpointPos(func, token_pos, last_token_pos);
1725 if (breakpoint_pos >= 0) { 1834 if (breakpoint_pos >= 0) {
1726 SourceBreakpoint* bpt = GetSourceBreakpoint(script, breakpoint_pos); 1835 SourceBreakpoint* bpt = GetSourceBreakpoint(script, breakpoint_pos);
1727 if (bpt != NULL) { 1836 if (bpt != NULL) {
1728 // A source breakpoint for this location already exists. 1837 // A source breakpoint for this location already exists.
1729 return bpt; 1838 return bpt;
1730 } 1839 }
1731 bpt = new SourceBreakpoint(nextId(), script, token_pos, last_token_pos); 1840 bpt = new SourceBreakpoint(script, token_pos, last_token_pos);
1732 bpt->SetResolved(func, breakpoint_pos); 1841 bpt->SetResolved(func, breakpoint_pos);
1733 RegisterSourceBreakpoint(bpt); 1842 RegisterSourceBreakpoint(bpt);
1734 1843
1735 // Create code breakpoints for all compiled functions we found. 1844 // Create code breakpoints for all compiled functions we found.
1736 const intptr_t num_functions = functions.Length(); 1845 const intptr_t num_functions = functions.Length();
1737 for (intptr_t i = 0; i < num_functions; i++) { 1846 for (intptr_t i = 0; i < num_functions; i++) {
1738 func ^= functions.At(i); 1847 func ^= functions.At(i);
1739 ASSERT(func.HasCode()); 1848 ASSERT(func.HasCode());
1740 MakeCodeBreakpointAt(func, bpt); 1849 MakeCodeBreakpointAt(func, bpt);
1741 } 1850 }
1742 bpt->Enable(); 1851 bpt->Enable();
1743 if (FLAG_verbose_debug) { 1852 if (FLAG_verbose_debug) {
1744 intptr_t line_number; 1853 intptr_t line_number;
1745 script.GetTokenLocation(breakpoint_pos, &line_number, NULL); 1854 script.GetTokenLocation(breakpoint_pos, &line_number, NULL);
1746 OS::Print("Resolved BP for " 1855 OS::Print("Resolved BP for "
1747 "function '%s' at line %" Pd "\n", 1856 "function '%s' at line %" Pd "\n",
1748 func.ToFullyQualifiedCString(), 1857 func.ToFullyQualifiedCString(),
1749 line_number); 1858 line_number);
1750 } 1859 }
1751 SignalBpResolved(bpt);
1752 SendServiceBreakpointEvent(ServiceEvent::kBreakpointAdded, bpt);
1753 return bpt; 1860 return bpt;
1754 } 1861 }
1755 } 1862 }
1756 // There is no compiled function at this token position. 1863 // There is no compiled function at this token position.
1757 // Register an unresolved breakpoint. 1864 // Register an unresolved breakpoint.
1758 if (FLAG_verbose_debug && !func.IsNull()) { 1865 if (FLAG_verbose_debug && !func.IsNull()) {
1759 intptr_t line_number; 1866 intptr_t line_number;
1760 script.GetTokenLocation(token_pos, &line_number, NULL); 1867 script.GetTokenLocation(token_pos, &line_number, NULL);
1761 OS::Print("Registering pending breakpoint for " 1868 OS::Print("Registering pending breakpoint for "
1762 "uncompiled function '%s' at line %" Pd "\n", 1869 "uncompiled function '%s' at line %" Pd "\n",
1763 func.ToFullyQualifiedCString(), 1870 func.ToFullyQualifiedCString(),
1764 line_number); 1871 line_number);
1765 } 1872 }
1766 SourceBreakpoint* bpt = GetSourceBreakpoint(script, token_pos); 1873 SourceBreakpoint* bpt = GetSourceBreakpoint(script, token_pos);
1767 if (bpt == NULL) { 1874 if (bpt == NULL) {
1768 bpt = new SourceBreakpoint(nextId(), script, token_pos, last_token_pos); 1875 bpt = new SourceBreakpoint(script, token_pos, last_token_pos);
1769 RegisterSourceBreakpoint(bpt); 1876 RegisterSourceBreakpoint(bpt);
1770 SendServiceBreakpointEvent(ServiceEvent::kBreakpointAdded, bpt);
1771 } 1877 }
1772 bpt->Enable(); 1878 bpt->Enable();
1773 return bpt; 1879 return bpt;
1774 } 1880 }
1775 1881
1776 1882
1777 // Synchronize the enabled/disabled state of all code breakpoints 1883 // Synchronize the enabled/disabled state of all code breakpoints
1778 // associated with the source breakpoint bpt. 1884 // associated with the source breakpoint bpt.
1779 void Debugger::SyncBreakpoint(SourceBreakpoint* bpt) { 1885 void Debugger::SyncBreakpoint(SourceBreakpoint* bpt) {
1780 CodeBreakpoint* cbpt = code_breakpoints_; 1886 CodeBreakpoint* cbpt = code_breakpoints_;
1781 while (cbpt != NULL) { 1887 while (cbpt != NULL) {
1782 if (bpt == cbpt->src_bpt()) { 1888 if (bpt == cbpt->src_bpt()) {
1783 if (bpt->IsEnabled()) { 1889 if (bpt->IsEnabled()) {
1784 cbpt->Enable(); 1890 cbpt->Enable();
1785 } else { 1891 } else {
1786 cbpt->Disable(); 1892 cbpt->Disable();
1787 } 1893 }
1788 } 1894 }
1789 cbpt = cbpt->next(); 1895 cbpt = cbpt->next();
1790 } 1896 }
1791 } 1897 }
1792 1898
1793 1899
1794 RawError* Debugger::OneTimeBreakAtEntry(const Function& target_function) { 1900 RawError* Debugger::OneTimeBreakAtEntry(const Function& target_function) {
1795 LongJumpScope jump; 1901 LongJumpScope jump;
1796 if (setjmp(*jump.Set()) == 0) { 1902 if (setjmp(*jump.Set()) == 0) {
1797 SourceBreakpoint* bpt = SetBreakpointAtEntry(target_function); 1903 SetBreakpointAtEntry(target_function, true);
1798 if (bpt != NULL) {
1799 bpt->SetIsOneShot();
1800 }
1801 return Error::null(); 1904 return Error::null();
1802 } else { 1905 } else {
1803 return isolate_->object_store()->sticky_error(); 1906 return isolate_->object_store()->sticky_error();
1804 } 1907 }
1805 } 1908 }
1806 1909
1807 1910
1808 SourceBreakpoint* Debugger::SetBreakpointAtEntry( 1911 BreakpointCondition* Debugger::SetBreakpointAtEntry(
1809 const Function& target_function) { 1912 const Function& target_function,
1913 bool single_shot) {
1810 ASSERT(!target_function.IsNull()); 1914 ASSERT(!target_function.IsNull());
1811 if (!target_function.is_debuggable()) { 1915 if (!target_function.is_debuggable()) {
1812 return NULL; 1916 return NULL;
1813 } 1917 }
1814 const Script& script = Script::Handle(target_function.script()); 1918 const Script& script = Script::Handle(target_function.script());
1815 return SetBreakpoint(script, 1919 SourceBreakpoint* src_bpt = SetBreakpoint(script,
1816 target_function.token_pos(), 1920 target_function.token_pos(),
1817 target_function.end_token_pos()); 1921 target_function.end_token_pos());
1922 if (single_shot) {
1923 return src_bpt->AddSingleShot(this);
1924 } else {
1925 return src_bpt->AddRepeated(this);
1926 }
1818 } 1927 }
1819 1928
1820 1929
1821 SourceBreakpoint* Debugger::SetBreakpointAtLine(const String& script_url, 1930 BreakpointCondition* Debugger::SetBreakpointAtActivation(
1822 intptr_t line_number) { 1931 const Instance& closure) {
1932 if (!closure.IsClosure()) {
1933 return NULL;
1934 }
1935 const Function& func = Function::Handle(Closure::function(closure));
1936 const Script& script = Script::Handle(func.script());
1937 SourceBreakpoint* bpt = SetBreakpoint(script,
1938 func.token_pos(),
1939 func.end_token_pos());
1940 return bpt->AddPerClosure(this, closure);
1941 }
1942
1943
1944 BreakpointCondition* Debugger::SetBreakpointAtLine(const String& script_url,
1945 intptr_t line_number) {
1946 SourceBreakpoint* bpt = SourceBreakpointAtLine(script_url, line_number);
1947 return bpt->AddRepeated(this);
1948 }
1949
1950
1951 SourceBreakpoint* Debugger::SourceBreakpointAtLine(const String& script_url,
1952 intptr_t line_number) {
1823 Library& lib = Library::Handle(isolate_); 1953 Library& lib = Library::Handle(isolate_);
1824 Script& script = Script::Handle(isolate_); 1954 Script& script = Script::Handle(isolate_);
1825 const GrowableObjectArray& libs = 1955 const GrowableObjectArray& libs =
1826 GrowableObjectArray::Handle(isolate_->object_store()->libraries()); 1956 GrowableObjectArray::Handle(isolate_->object_store()->libraries());
1827 const GrowableObjectArray& scripts = 1957 const GrowableObjectArray& scripts =
1828 GrowableObjectArray::Handle(isolate_, GrowableObjectArray::New()); 1958 GrowableObjectArray::Handle(isolate_, GrowableObjectArray::New());
1829 for (intptr_t i = 0; i < libs.Length(); i++) { 1959 for (intptr_t i = 0; i < libs.Length(); i++) {
1830 lib ^= libs.At(i); 1960 lib ^= libs.At(i);
1831 script = lib.LookupScript(script_url); 1961 script = lib.LookupScript(script_url);
1832 if (!script.IsNull()) { 1962 if (!script.IsNull()) {
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
2159 if (ServiceIsolate::IsRunning()) { 2289 if (ServiceIsolate::IsRunning()) {
2160 return true; 2290 return true;
2161 } 2291 }
2162 const Class& cls = Class::Handle(func.Owner()); 2292 const Class& cls = Class::Handle(func.Owner());
2163 const Library& lib = Library::Handle(cls.library()); 2293 const Library& lib = Library::Handle(cls.library());
2164 return lib.IsDebuggable(); 2294 return lib.IsDebuggable();
2165 } 2295 }
2166 2296
2167 2297
2168 void Debugger::SignalPausedEvent(ActivationFrame* top_frame, 2298 void Debugger::SignalPausedEvent(ActivationFrame* top_frame,
2169 SourceBreakpoint* bpt) { 2299 BreakpointCondition* bpt) {
2170 resume_action_ = kContinue; 2300 resume_action_ = kContinue;
2171 stepping_fp_ = 0; 2301 stepping_fp_ = 0;
2172 isolate_->set_single_step(false); 2302 isolate_->set_single_step(false);
2173 ASSERT(!IsPaused()); 2303 ASSERT(!IsPaused());
2174 ASSERT(obj_cache_ == NULL); 2304 ASSERT(obj_cache_ == NULL);
2175 if ((bpt != NULL) && bpt->IsOneShot()) { 2305 if ((bpt != NULL) && bpt->IsSingleShot()) {
2176 RemoveBreakpoint(bpt->id()); 2306 RemoveBreakpoint(bpt->id());
2177 bpt = NULL; 2307 bpt = NULL;
2178 } 2308 }
2179 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointReached); 2309 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointReached);
2180 event.set_top_frame(top_frame); 2310 event.set_top_frame(top_frame);
2181 event.set_breakpoint(bpt); 2311 event.set_breakpoint(bpt);
2182 Pause(&event); 2312 Pause(&event);
2183 } 2313 }
2184 2314
2185 2315
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
2250 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) { 2380 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) {
2251 return; 2381 return;
2252 } 2382 }
2253 DebuggerStackTrace* stack_trace = CollectStackTrace(); 2383 DebuggerStackTrace* stack_trace = CollectStackTrace();
2254 ASSERT(stack_trace->Length() > 0); 2384 ASSERT(stack_trace->Length() > 0);
2255 ActivationFrame* top_frame = stack_trace->FrameAt(0); 2385 ActivationFrame* top_frame = stack_trace->FrameAt(0);
2256 ASSERT(top_frame != NULL); 2386 ASSERT(top_frame != NULL);
2257 CodeBreakpoint* bpt = GetCodeBreakpoint(top_frame->pc()); 2387 CodeBreakpoint* bpt = GetCodeBreakpoint(top_frame->pc());
2258 ASSERT(bpt != NULL); 2388 ASSERT(bpt != NULL);
2259 2389
2390 SourceBreakpoint* src_bpt = bpt->src_bpt_;
2391 BreakpointCondition* condition_met = NULL;
2392 if (src_bpt != NULL) {
2393 BreakpointCondition* cond = src_bpt->conditions();
2394 while (cond != NULL) {
2395 if (cond->IsPerClosure()) {
2396 Object& closure = Object::Handle(top_frame->GetClosure());
2397 ASSERT(closure.IsInstance());
2398 ASSERT(Instance::Cast(closure).IsClosure());
2399 if (closure.raw() == cond->closure()) {
2400 condition_met = cond;
2401 break;
2402 }
2403 } else {
2404 condition_met = cond;
hausner 2015/05/21 18:23:55 This is subtly wrong. If you have a one-shot break
rmacnak 2015/05/21 21:59:35 As discussed, we should not send a series of break
2405 break;
2406 }
2407 cond = cond->next();
2408 }
2409 }
2410 if (condition_met == NULL) {
2411 return;
2412 }
2413
2414
2260 if (FLAG_verbose_debug) { 2415 if (FLAG_verbose_debug) {
2261 OS::Print(">>> hit %s breakpoint at %s:%" Pd " " 2416 OS::Print(">>> hit %s breakpoint at %s:%" Pd " "
2262 "(token %" Pd ") (address %#" Px ")\n", 2417 "(token %" Pd ") (address %#" Px ")\n",
2263 bpt->IsInternal() ? "internal" : "user", 2418 bpt->IsInternal() ? "internal" : "user",
2264 String::Handle(bpt->SourceUrl()).ToCString(), 2419 String::Handle(bpt->SourceUrl()).ToCString(),
2265 bpt->LineNumber(), 2420 bpt->LineNumber(),
2266 bpt->token_pos(), 2421 bpt->token_pos(),
2267 top_frame->pc()); 2422 top_frame->pc());
2268 } 2423 }
2269 2424
2270 ASSERT(stack_trace_ == NULL); 2425 ASSERT(stack_trace_ == NULL);
2271 stack_trace_ = stack_trace; 2426 stack_trace_ = stack_trace;
2272 SignalPausedEvent(top_frame, bpt->src_bpt_); 2427 SignalPausedEvent(top_frame, condition_met);
2273 HandleSteppingRequest(stack_trace_); 2428 HandleSteppingRequest(stack_trace_);
2274 stack_trace_ = NULL; 2429 stack_trace_ = NULL;
2275 if (bpt->IsInternal()) { 2430 if (bpt->IsInternal()) {
2276 RemoveInternalBreakpoints(); 2431 RemoveInternalBreakpoints();
2277 } 2432 }
2278 } 2433 }
2279 2434
2280 2435
2281 void Debugger::BreakHere(const String& msg) { 2436 void Debugger::BreakHere(const String& msg) {
2282 // We ignore this breakpoint when the VM is executing code invoked 2437 // We ignore this breakpoint when the VM is executing code invoked
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
2403 if (bp_pos < 0) { 2558 if (bp_pos < 0) {
2404 if (FLAG_verbose_debug) { 2559 if (FLAG_verbose_debug) {
2405 OS::Print("Failed resolving breakpoint for function '%s'\n", 2560 OS::Print("Failed resolving breakpoint for function '%s'\n",
2406 String::Handle(func.name()).ToCString()); 2561 String::Handle(func.name()).ToCString());
2407 } 2562 }
2408 continue; 2563 continue;
2409 } 2564 }
2410 intptr_t requested_pos = bpt->token_pos(); 2565 intptr_t requested_pos = bpt->token_pos();
2411 intptr_t requested_end_pos = bpt->end_token_pos(); 2566 intptr_t requested_end_pos = bpt->end_token_pos();
2412 bpt->SetResolved(func, bp_pos); 2567 bpt->SetResolved(func, bp_pos);
2413 if (FLAG_verbose_debug) { 2568 BreakpointCondition* cond = bpt->conditions();
2414 OS::Print("Resolved BP %" Pd " to pos %" Pd ", line %" Pd ", " 2569 while (cond != NULL) {
2415 "function '%s' (requested range %" Pd "-%" Pd ")\n", 2570 if (FLAG_verbose_debug) {
2416 bpt->id(), 2571 OS::Print("Resolved BP %" Pd " to pos %" Pd ", line %" Pd ", "
2417 bpt->token_pos(), 2572 "function '%s' (requested range %" Pd "-%" Pd ")\n",
2418 bpt->LineNumber(), 2573 cond->id(),
2419 func.ToFullyQualifiedCString(), 2574 bpt->token_pos(),
2420 requested_pos, 2575 bpt->LineNumber(),
2421 requested_end_pos); 2576 func.ToFullyQualifiedCString(),
2577 requested_pos,
2578 requested_end_pos);
2579 }
2580 SignalBpResolved(cond);
2581 SendServiceBreakpointEvent(ServiceEvent::kBreakpointResolved, cond);
2582 cond = cond->next();
2422 } 2583 }
2423 SignalBpResolved(bpt);
2424 SendServiceBreakpointEvent(ServiceEvent::kBreakpointResolved, bpt);
2425 } 2584 }
2426 ASSERT(bpt->IsResolved()); 2585 ASSERT(bpt->IsResolved());
2427 if (FLAG_verbose_debug) { 2586 if (FLAG_verbose_debug) {
2428 OS::Print("Setting breakpoint %" Pd " at line %" Pd " for %s '%s'\n", 2587 BreakpointCondition* cond = bpt->conditions();
2429 bpt->id(), 2588 while (cond != NULL) {
2430 bpt->LineNumber(), 2589 OS::Print("Setting breakpoint %" Pd " at line %" Pd " for %s '%s'\n",
2431 func.IsClosureFunction() ? "closure" : "function", 2590 cond->id(),
2432 String::Handle(func.name()).ToCString()); 2591 bpt->LineNumber(),
2592 func.IsClosureFunction() ? "closure" : "function",
2593 String::Handle(func.name()).ToCString());
2594 cond = cond->next();
2595 }
2433 } 2596 }
2434 MakeCodeBreakpointAt(func, bpt); 2597 MakeCodeBreakpointAt(func, bpt);
2435 } 2598 }
2436 } 2599 }
2437 } 2600 }
2438 2601
2439 2602
2440 void Debugger::NotifyDoneLoading() { 2603 void Debugger::NotifyDoneLoading() {
2441 if (latent_breakpoints_ == NULL) { 2604 if (latent_breakpoints_ == NULL) {
2442 // Common, fast path. 2605 // Common, fast path.
(...skipping 26 matching lines...) Expand all
2469 // Now find the token range at the requested line and make a 2632 // Now find the token range at the requested line and make a
2470 // new unresolved source breakpoint. 2633 // new unresolved source breakpoint.
2471 intptr_t line_number = matched_bpt->LineNumber(); 2634 intptr_t line_number = matched_bpt->LineNumber();
2472 ASSERT(line_number >= 0); 2635 ASSERT(line_number >= 0);
2473 intptr_t first_token_pos, last_token_pos; 2636 intptr_t first_token_pos, last_token_pos;
2474 script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos); 2637 script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos);
2475 if ((first_token_pos < 0) || 2638 if ((first_token_pos < 0) ||
2476 (last_token_pos < 0)) { 2639 (last_token_pos < 0)) {
2477 // Script does not contain the given line number or there are no 2640 // Script does not contain the given line number or there are no
2478 // tokens on the line. Drop the breakpoint silently. 2641 // tokens on the line. Drop the breakpoint silently.
2479 if (FLAG_verbose_debug) { 2642 BreakpointCondition* cond = matched_bpt->conditions();
2480 OS::Print("No code found at line %" Pd ": " 2643 while (cond != NULL) {
2481 "dropping latent breakpoint %" Pd " in '%s'\n", 2644 if (FLAG_verbose_debug) {
2482 line_number, 2645 OS::Print("No code found at line %" Pd ": "
2483 matched_bpt->id(), 2646 "dropping latent breakpoint %" Pd " in '%s'\n",
2484 url.ToCString()); 2647 line_number,
2648 cond->id(),
2649 url.ToCString());
2650 }
2651 BreakpointCondition* prev = cond;
2652 cond = cond->next();
2653 delete prev;
2485 } 2654 }
2486 delete matched_bpt; 2655 delete matched_bpt;
2487 } else { 2656 } else {
2488 // We don't expect to already have a breakpoint for this location. 2657 // We don't expect to already have a breakpoint for this location.
2489 // If there is one, assert in debug build but silently drop 2658 // If there is one, assert in debug build but silently drop
2490 // the latent breakpoint in release build. 2659 // the latent breakpoint in release build.
2491 SourceBreakpoint* existing_bpt = 2660 SourceBreakpoint* existing_bpt =
2492 GetSourceBreakpoint(script, first_token_pos); 2661 GetSourceBreakpoint(script, first_token_pos);
2493 ASSERT(existing_bpt == NULL); 2662 ASSERT(existing_bpt == NULL);
2494 if (existing_bpt == NULL) { 2663 if (existing_bpt == NULL) {
2495 // Create and register a new source breakpoint for the 2664 // Create and register a new source breakpoint for the
2496 // latent breakpoint. 2665 // latent breakpoint.
2497 SourceBreakpoint* unresolved_bpt = 2666 SourceBreakpoint* unresolved_bpt =
2498 new SourceBreakpoint(matched_bpt->id(), 2667 new SourceBreakpoint(script,
2499 script,
2500 first_token_pos, 2668 first_token_pos,
2501 last_token_pos); 2669 last_token_pos);
2502 RegisterSourceBreakpoint(unresolved_bpt); 2670 RegisterSourceBreakpoint(unresolved_bpt);
2503 unresolved_bpt->Enable(); 2671 unresolved_bpt->Enable();
2504 if (FLAG_verbose_debug) { 2672
2505 OS::Print("Converted latent breakpoint " 2673 // Move conditions over.
2506 "%" Pd " in '%s' at line %" Pd "\n", 2674 BreakpointCondition* cond = existing_bpt->conditions();
2507 matched_bpt->id(), 2675 unresolved_bpt->set_conditions(cond);
2508 url.ToCString(), 2676 existing_bpt->set_conditions(NULL);
2509 line_number); 2677 while (cond != NULL) {
2678 cond->set_src_bpt(unresolved_bpt);
2679 if (FLAG_verbose_debug) {
2680 OS::Print("Converted latent breakpoint "
2681 "%" Pd " in '%s' at line %" Pd "\n",
2682 cond->id(),
2683 url.ToCString(),
2684 line_number);
2685 }
2686 cond = cond->next();
2510 } 2687 }
2511 } 2688 }
2512 delete matched_bpt; 2689 delete matched_bpt;
2513 // Break out of the iteration over loaded libraries. If the 2690 // Break out of the iteration over loaded libraries. If the
2514 // same url has been loaded into more than one library, we 2691 // same url has been loaded into more than one library, we
2515 // only set a breakpoint in the first one. 2692 // only set a breakpoint in the first one.
2516 // TODO(hausner): There is one possible pitfall here. 2693 // TODO(hausner): There is one possible pitfall here.
2517 // If the user sets a latent breakpoint using a partial url that 2694 // If the user sets a latent breakpoint using a partial url that
2518 // ends up matching more than one script, the breakpoint might 2695 // ends up matching more than one script, the breakpoint might
2519 // get set in the wrong script. 2696 // get set in the wrong script.
2520 // It would be better if we could warn the user if multiple 2697 // It would be better if we could warn the user if multiple
2521 // scripts are matching. 2698 // scripts are matching.
2522 break; 2699 break;
2523 } 2700 }
2524 } 2701 }
2525 } 2702 }
2526 if (!found_match) { 2703 if (!found_match) {
2527 // No matching url found in any of the libraries. 2704 // No matching url found in any of the libraries.
2528 if (FLAG_verbose_debug) { 2705 if (FLAG_verbose_debug) {
2529 OS::Print("No match found for latent breakpoint id " 2706 BreakpointCondition* cond = bpt->conditions();
2530 "%" Pd " with url '%s'\n", 2707 while (cond != NULL) {
2531 bpt->id(), 2708 OS::Print("No match found for latent breakpoint id "
2532 url.ToCString()); 2709 "%" Pd " with url '%s'\n",
2710 cond->id(),
2711 url.ToCString());
2712 cond = cond->next();
2713 }
2533 } 2714 }
2534 bpt = bpt->next(); 2715 bpt = bpt->next();
2535 } 2716 }
2536 } 2717 }
2537 } 2718 }
2538 2719
2539 2720
2540 // TODO(hausner): Could potentially make this faster by checking 2721 // TODO(hausner): Could potentially make this faster by checking
2541 // whether the call target at pc is a debugger stub. 2722 // whether the call target at pc is a debugger stub.
2542 bool Debugger::HasActiveBreakpoint(uword pc) { 2723 bool Debugger::HasActiveBreakpoint(uword pc) {
(...skipping 23 matching lines...) Expand all
2566 return 0L; 2747 return 0L;
2567 } 2748 }
2568 2749
2569 2750
2570 // Remove and delete the source breakpoint bpt and its associated 2751 // Remove and delete the source breakpoint bpt and its associated
2571 // code breakpoints. 2752 // code breakpoints.
2572 void Debugger::RemoveBreakpoint(intptr_t bp_id) { 2753 void Debugger::RemoveBreakpoint(intptr_t bp_id) {
2573 SourceBreakpoint* prev_bpt = NULL; 2754 SourceBreakpoint* prev_bpt = NULL;
2574 SourceBreakpoint* curr_bpt = src_breakpoints_; 2755 SourceBreakpoint* curr_bpt = src_breakpoints_;
2575 while (curr_bpt != NULL) { 2756 while (curr_bpt != NULL) {
2576 if (curr_bpt->id() == bp_id) { 2757 BreakpointCondition* prev_cond = NULL;
2758 BreakpointCondition* curr_cond = curr_bpt->conditions();
2759 while (curr_cond != NULL) {
2760 if (curr_cond->id() == bp_id) {
2761 if (prev_cond == NULL) {
2762 curr_bpt->set_conditions(curr_cond->next());
2763 } else {
2764 prev_cond->set_next(curr_cond->next());
2765 }
2766 SendServiceBreakpointEvent(ServiceEvent::kBreakpointRemoved, curr_cond);
2767
2768 // Remove references from the current debugger pause event.
2769 if (pause_event_ != NULL &&
2770 pause_event_->type() == DebuggerEvent::kBreakpointReached &&
2771 pause_event_->breakpoint() == curr_cond) {
2772 pause_event_->set_breakpoint(NULL);
2773 }
2774 return;
2775 }
2776
2777 prev_cond = curr_cond;
2778 curr_cond = curr_cond->next();
2779 }
2780
2781 if (curr_bpt->conditions() == NULL) {
2577 if (prev_bpt == NULL) { 2782 if (prev_bpt == NULL) {
2578 src_breakpoints_ = src_breakpoints_->next(); 2783 src_breakpoints_ = src_breakpoints_->next();
2579 } else { 2784 } else {
2580 prev_bpt->set_next(curr_bpt->next()); 2785 prev_bpt->set_next(curr_bpt->next());
2581 } 2786 }
2582 SendServiceBreakpointEvent(ServiceEvent::kBreakpointRemoved, curr_bpt);
2583 2787
2584 // Remove references from code breakpoints to this source breakpoint, 2788 // Remove references from code breakpoints to this source breakpoint,
2585 // and disable the code breakpoints. 2789 // and disable the code breakpoints.
2586 UnlinkCodeBreakpoints(curr_bpt); 2790 UnlinkCodeBreakpoints(curr_bpt);
2587 delete curr_bpt; 2791 delete curr_bpt;
2792 }
2588 2793
2589 // Remove references from the current debugger pause event.
2590 if (pause_event_ != NULL &&
2591 pause_event_->type() == DebuggerEvent::kBreakpointReached &&
2592 pause_event_->breakpoint() == curr_bpt) {
2593 pause_event_->set_breakpoint(NULL);
2594 }
2595 return;
2596 }
2597 prev_bpt = curr_bpt; 2794 prev_bpt = curr_bpt;
2598 curr_bpt = curr_bpt->next(); 2795 curr_bpt = curr_bpt->next();
2599 } 2796 }
2600 // bpt is not a registered breakpoint, nothing to do. 2797 // bpt is not a registered breakpoint, nothing to do.
2601 } 2798 }
2602 2799
2603 2800
2604 // Turn code breakpoints associated with the given source breakpoint into 2801 // Turn code breakpoints associated with the given source breakpoint into
2605 // internal breakpoints. They will later be deleted when control 2802 // internal breakpoints. They will later be deleted when control
2606 // returns from the user-defined breakpoint callback. Also, disable the 2803 // returns from the user-defined breakpoint callback. Also, disable the
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2649 while (bpt != NULL) { 2846 while (bpt != NULL) {
2650 if ((bpt->script_ == script.raw()) && (bpt->token_pos_ == token_pos)) { 2847 if ((bpt->script_ == script.raw()) && (bpt->token_pos_ == token_pos)) {
2651 return bpt; 2848 return bpt;
2652 } 2849 }
2653 bpt = bpt->next(); 2850 bpt = bpt->next();
2654 } 2851 }
2655 return NULL; 2852 return NULL;
2656 } 2853 }
2657 2854
2658 2855
2659 SourceBreakpoint* Debugger::GetBreakpointById(intptr_t id) { 2856 BreakpointCondition* Debugger::GetBreakpointById(intptr_t id) {
2660 SourceBreakpoint* bpt = src_breakpoints_; 2857 SourceBreakpoint* bpt = src_breakpoints_;
2661 while (bpt != NULL) { 2858 while (bpt != NULL) {
2662 if (bpt->id() == id) { 2859 BreakpointCondition* cond = bpt->conditions();
2663 return bpt; 2860 while (cond != NULL) {
2861 if (cond->id() == id) {
2862 return cond;
2863 }
2864 cond = cond->next();
2664 } 2865 }
2665 bpt = bpt->next(); 2866 bpt = bpt->next();
2666 } 2867 }
2667 return NULL; 2868 return NULL;
2668 } 2869 }
2669 2870
2670 2871
2671 SourceBreakpoint* Debugger::GetLatentBreakpoint(const String& url, 2872 SourceBreakpoint* Debugger::GetLatentBreakpoint(const String& url,
2672 intptr_t line) { 2873 intptr_t line) {
2673 SourceBreakpoint* bpt = latent_breakpoints_; 2874 SourceBreakpoint* bpt = latent_breakpoints_;
2674 String& bpt_url = String::Handle(isolate_); 2875 String& bpt_url = String::Handle(isolate_);
2675 while (bpt != NULL) { 2876 while (bpt != NULL) {
2676 bpt_url = bpt->url(); 2877 bpt_url = bpt->url();
2677 if (bpt_url.Equals(url) && (bpt->LineNumber() == line)) { 2878 if (bpt_url.Equals(url) && (bpt->LineNumber() == line)) {
2678 return bpt; 2879 return bpt;
2679 } 2880 }
2680 bpt = bpt->next(); 2881 bpt = bpt->next();
2681 } 2882 }
2682 // No breakpint for this url and line requested. Allocate new one. 2883 // No breakpint for this url and line requested. Allocate new one.
2683 bpt = new SourceBreakpoint(nextId(), url, line); 2884 bpt = new SourceBreakpoint(url, line);
2684 bpt->set_next(latent_breakpoints_); 2885 bpt->set_next(latent_breakpoints_);
2685 latent_breakpoints_ = bpt; 2886 latent_breakpoints_ = bpt;
2686 return bpt; 2887 return bpt;
2687 } 2888 }
2688 2889
2689 2890
2690 void Debugger::RegisterSourceBreakpoint(SourceBreakpoint* bpt) { 2891 void Debugger::RegisterSourceBreakpoint(SourceBreakpoint* bpt) {
2691 ASSERT(bpt->next() == NULL); 2892 ASSERT(bpt->next() == NULL);
2692 bpt->set_next(src_breakpoints_); 2893 bpt->set_next(src_breakpoints_);
2693 src_breakpoints_ = bpt; 2894 src_breakpoints_ = bpt;
2694 } 2895 }
2695 2896
2696 2897
2697 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 2898 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
2698 ASSERT(bpt->next() == NULL); 2899 ASSERT(bpt->next() == NULL);
2699 bpt->set_next(code_breakpoints_); 2900 bpt->set_next(code_breakpoints_);
2700 code_breakpoints_ = bpt; 2901 code_breakpoints_ = bpt;
2701 } 2902 }
2702 2903
2703 } // namespace dart 2904 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698