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

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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 } 56 }
57 57
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 SourceBreakpoint::SourceBreakpoint(intptr_t id, 66 BreakpointLocation::BreakpointLocation(const Script& script,
67 const Script& script, 67 intptr_t token_pos,
68 intptr_t token_pos, 68 intptr_t end_token_pos)
69 intptr_t end_token_pos) 69 : script_(script.raw()),
70 : id_(id),
71 script_(script.raw()),
72 url_(script.url()), 70 url_(script.url()),
73 token_pos_(token_pos), 71 token_pos_(token_pos),
74 end_token_pos_(end_token_pos), 72 end_token_pos_(end_token_pos),
75 is_resolved_(false), 73 is_resolved_(false),
76 is_enabled_(false),
77 is_one_shot_(false),
78 next_(NULL), 74 next_(NULL),
75 conditions_(NULL),
79 function_(Function::null()), 76 function_(Function::null()),
80 line_number_(-1) { 77 line_number_(-1) {
81 ASSERT(id_ > 0);
82 ASSERT(!script.IsNull()); 78 ASSERT(!script.IsNull());
83 ASSERT(token_pos_ >= 0); 79 ASSERT(token_pos_ >= 0);
84 } 80 }
85 81
86 // Create a latent breakpoint at given url and line number. 82 // Create a latent breakpoint at given url and line number.
87 SourceBreakpoint::SourceBreakpoint(intptr_t id, 83 BreakpointLocation::BreakpointLocation(const String& url,
88 const String& url, 84 intptr_t line_number)
89 intptr_t line_number) 85 : script_(Script::null()),
90 : id_(id),
91 script_(Script::null()),
92 url_(url.raw()), 86 url_(url.raw()),
93 token_pos_(-1), 87 token_pos_(-1),
94 end_token_pos_(-1), 88 end_token_pos_(-1),
95 is_resolved_(false), 89 is_resolved_(false),
96 is_enabled_(false),
97 is_one_shot_(false),
98 next_(NULL), 90 next_(NULL),
91 conditions_(NULL),
99 function_(Function::null()), 92 function_(Function::null()),
100 line_number_(line_number) { 93 line_number_(line_number) {
101 ASSERT(id >= 0);
102 ASSERT(line_number_ >= 0); 94 ASSERT(line_number_ >= 0);
103 } 95 }
104 96
105 void SourceBreakpoint::Enable() { 97
106 is_enabled_ = true; 98 BreakpointLocation::~BreakpointLocation() {
107 Isolate::Current()->debugger()->SyncBreakpoint(this); 99 Breakpoint* bpt = breakpoints();
100 while (bpt != NULL) {
101 Breakpoint* temp = bpt;
102 bpt = bpt->next();
103 delete temp;
104 }
108 } 105 }
109 106
110 107
111 void SourceBreakpoint::Disable() { 108 bool BreakpointLocation::AnyEnabled() const {
112 is_enabled_ = false; 109 return breakpoints() != NULL;
113 Isolate::Current()->debugger()->SyncBreakpoint(this);
114 } 110 }
115 111
116 112
117 void SourceBreakpoint::SetResolved(const Function& func, intptr_t token_pos) { 113 void BreakpointLocation::SetResolved(const Function& func, intptr_t token_pos) {
118 ASSERT(!IsLatent()); 114 ASSERT(!IsLatent());
119 ASSERT(func.script() == script_); 115 ASSERT(func.script() == script_);
120 ASSERT((func.token_pos() <= token_pos) && 116 ASSERT((func.token_pos() <= token_pos) &&
121 (token_pos <= func.end_token_pos())); 117 (token_pos <= func.end_token_pos()));
122 ASSERT(func.is_debuggable()); 118 ASSERT(func.is_debuggable());
123 function_ = func.raw(); 119 function_ = func.raw();
124 token_pos_ = token_pos; 120 token_pos_ = token_pos;
125 end_token_pos_ = token_pos; 121 end_token_pos_ = token_pos;
126 line_number_ = -1; // Recalculate lazily. 122 line_number_ = -1; // Recalculate lazily.
127 is_resolved_ = true; 123 is_resolved_ = true;
128 } 124 }
129 125
130 126
131 // TODO(hausner): Get rid of library parameter. A source breakpoint location 127 // TODO(hausner): Get rid of library parameter. A source breakpoint location
132 // does not imply a library, since the same source code can be included 128 // does not imply a library, since the same source code can be included
133 // in more than one library, e.g. the text location of mixin functions. 129 // in more than one library, e.g. the text location of mixin functions.
134 void SourceBreakpoint::GetCodeLocation(Library* lib, 130 void BreakpointLocation::GetCodeLocation(Library* lib,
135 Script* script, 131 Script* script,
136 intptr_t* pos) { 132 intptr_t* pos) {
137 if (IsLatent()) { 133 if (IsLatent()) {
138 *lib = Library::null(); 134 *lib = Library::null();
139 *script = Script::null(); 135 *script = Script::null();
140 *pos = -1; 136 *pos = -1;
141 } else { 137 } else {
142 *script = this->script(); 138 *script = this->script();
143 *pos = token_pos_; 139 *pos = token_pos_;
144 if (IsResolved()) { 140 if (IsResolved()) {
145 const Function& func = Function::Handle(function_); 141 const Function& func = Function::Handle(function_);
146 ASSERT(!func.IsNull()); 142 ASSERT(!func.IsNull());
147 const Class& cls = Class::Handle(func.origin()); 143 const Class& cls = Class::Handle(func.origin());
148 *lib = cls.library(); 144 *lib = cls.library();
149 } else { 145 } else {
150 *lib = Library::null(); 146 *lib = Library::null();
151 } 147 }
152 } 148 }
153 } 149 }
154 150
155 151
156 intptr_t SourceBreakpoint::LineNumber() { 152 intptr_t BreakpointLocation::LineNumber() {
157 // Latent breakpoints must have a requested line number >= 0. 153 // Latent breakpoints must have a requested line number >= 0.
158 ASSERT(!IsLatent() || line_number_ >= 0); 154 ASSERT(!IsLatent() || line_number_ >= 0);
159 // Compute line number lazily since it causes scanning of the script. 155 // Compute line number lazily since it causes scanning of the script.
160 if (line_number_ < 0) { 156 if (line_number_ < 0) {
161 const Script& script = Script::Handle(this->script()); 157 const Script& script = Script::Handle(this->script());
162 script.GetTokenLocation(token_pos_, &line_number_, NULL); 158 script.GetTokenLocation(token_pos_, &line_number_, NULL);
163 } 159 }
164 return line_number_; 160 return line_number_;
165 } 161 }
166 162
167 163
168 void SourceBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { 164 void Breakpoint::set_bpt_location(BreakpointLocation* new_bpt_location) {
165 ASSERT(bpt_location_->IsLatent()); // Only reason to move.
166 bpt_location_ = new_bpt_location;
167 }
168
169
170 void Breakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
171 visitor->VisitPointer(reinterpret_cast<RawObject**>(&closure_));
172 }
173
174
175 void BreakpointLocation::VisitObjectPointers(ObjectPointerVisitor* visitor) {
169 visitor->VisitPointer(reinterpret_cast<RawObject**>(&script_)); 176 visitor->VisitPointer(reinterpret_cast<RawObject**>(&script_));
170 visitor->VisitPointer(reinterpret_cast<RawObject**>(&url_)); 177 visitor->VisitPointer(reinterpret_cast<RawObject**>(&url_));
171 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_)); 178 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_));
179
180 Breakpoint* bpt = conditions_;
181 while (bpt != NULL) {
182 bpt -> VisitObjectPointers(visitor);
183 bpt = bpt->next();
184 }
172 } 185 }
173 186
174 187
175 void SourceBreakpoint::PrintJSON(JSONStream* stream) { 188 void Breakpoint::PrintJSON(JSONStream* stream) {
176 Isolate* isolate = Isolate::Current(); 189 Isolate* isolate = Isolate::Current();
177 190
178 JSONObject jsobj(stream); 191 JSONObject jsobj(stream);
179 jsobj.AddProperty("type", "Breakpoint"); 192 jsobj.AddProperty("type", "Breakpoint");
180 193
181 jsobj.AddPropertyF("id", "breakpoints/%" Pd "", id()); 194 jsobj.AddPropertyF("id", "breakpoints/%" Pd "", id());
182 jsobj.AddProperty("breakpointNumber", id()); 195 jsobj.AddProperty("breakpointNumber", id());
183 jsobj.AddProperty("resolved", IsResolved()); 196 jsobj.AddProperty("resolved", bpt_location_->IsResolved());
184 197
185 Library& library = Library::Handle(isolate); 198 Library& library = Library::Handle(isolate);
186 Script& script = Script::Handle(isolate); 199 Script& script = Script::Handle(isolate);
187 intptr_t token_pos; 200 intptr_t token_pos;
188 GetCodeLocation(&library, &script, &token_pos); 201 bpt_location_->GetCodeLocation(&library, &script, &token_pos);
189 { 202 {
190 JSONObject location(&jsobj, "location"); 203 JSONObject location(&jsobj, "location");
191 location.AddProperty("type", "Location"); 204 location.AddProperty("type", "Location");
192 location.AddProperty("script", script); 205 location.AddProperty("script", script);
193 location.AddProperty("tokenPos", token_pos); 206 location.AddProperty("tokenPos", token_pos);
194 } 207 }
195 } 208 }
196 209
197 210
198 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { 211 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 Debugger* debugger = Isolate::Current()->debugger(); 300 Debugger* debugger = Isolate::Current()->debugger();
288 ASSERT(debugger != NULL); 301 ASSERT(debugger != NULL);
289 debugger->SignalIsolateEvent(DebuggerEvent::kIsolateInterrupted); 302 debugger->SignalIsolateEvent(DebuggerEvent::kIsolateInterrupted);
290 } 303 }
291 } 304 }
292 305
293 306
294 // The vm service handles breakpoint notifications in a different way 307 // The vm service handles breakpoint notifications in a different way
295 // than the regular debugger breakpoint notifications. 308 // than the regular debugger breakpoint notifications.
296 static void SendServiceBreakpointEvent(ServiceEvent::EventType type, 309 static void SendServiceBreakpointEvent(ServiceEvent::EventType type,
297 SourceBreakpoint* bpt) { 310 Breakpoint* bpt) {
298 if (Service::NeedsEvents()) { 311 if (Service::NeedsEvents()) {
299 ServiceEvent service_event(Isolate::Current(), type); 312 ServiceEvent service_event(Isolate::Current(), type);
300 service_event.set_breakpoint(bpt); 313 service_event.set_breakpoint(bpt);
301 Service::HandleEvent(&service_event); 314 Service::HandleEvent(&service_event);
302 } 315 }
303 } 316 }
304 317
305 318
319 Breakpoint* BreakpointLocation::AddRepeated(Debugger* dbg) {
hausner 2015/05/21 22:46:23 Looks like the code for the AddXXXX() functions co
rmacnak 2015/05/21 23:51:56 Done.
320 Breakpoint* bpt = breakpoints();
321 while (bpt != NULL) {
322 if (bpt->IsRepeated()) break;
323 bpt = bpt->next();
324 }
325 if (bpt == NULL) {
326 bpt = new Breakpoint(dbg->nextId(), this);
327 bpt->SetIsRepeated();
328 bpt->set_next(breakpoints());
329 set_breakpoints(bpt);
330
331 dbg->SyncBreakpointLocation(this);
332
333 if (IsResolved()) {
334 dbg->SignalBpResolved(bpt);
335 }
336 SendServiceBreakpointEvent(ServiceEvent::kBreakpointAdded, bpt);
337 }
338 return bpt;
339 }
340
341
342 Breakpoint* BreakpointLocation::AddSingleShot(Debugger* dbg) {
343 Breakpoint* bpt = breakpoints();
344 while (bpt != NULL) {
345 if (bpt->IsSingleShot()) break;
346 bpt = bpt->next();
347 }
348 if (bpt == NULL) {
349 bpt = new Breakpoint(dbg->nextId(), this);
350 bpt->SetIsSingleShot();
351 bpt->set_next(breakpoints());
352 set_breakpoints(bpt);
353
354 dbg->SyncBreakpointLocation(this);
355
356 if (IsResolved()) {
357 dbg->SignalBpResolved(bpt);
358 }
359 SendServiceBreakpointEvent(ServiceEvent::kBreakpointAdded, bpt);
360 }
361 return bpt;
362 }
363
364
365 Breakpoint* BreakpointLocation::AddPerClosure(Debugger* dbg,
366 const Instance& closure) {
367 Breakpoint* bpt = breakpoints();
368 while (bpt != NULL) {
369 if (bpt->IsPerClosure() && bpt->closure() == closure.raw()) break;
370 bpt = bpt->next();
371 }
372 if (bpt == NULL) {
373 bpt = new Breakpoint(dbg->nextId(), this);
374 bpt->SetIsPerClosure(closure);
375 bpt->set_next(breakpoints());
376 set_breakpoints(bpt);
377
378 dbg->SyncBreakpointLocation(this);
379
380 if (IsResolved()) {
381 dbg->SignalBpResolved(bpt);
382 }
383 SendServiceBreakpointEvent(ServiceEvent::kBreakpointAdded, bpt);
384 }
385 return bpt;
386 }
387
388
306 const char* Debugger::QualifiedFunctionName(const Function& func) { 389 const char* Debugger::QualifiedFunctionName(const Function& func) {
307 const String& func_name = String::Handle(func.name()); 390 const String& func_name = String::Handle(func.name());
308 Class& func_class = Class::Handle(func.Owner()); 391 Class& func_class = Class::Handle(func.Owner());
309 String& class_name = String::Handle(func_class.Name()); 392 String& class_name = String::Handle(func_class.Name());
310 393
311 const char* kFormat = "%s%s%s"; 394 const char* kFormat = "%s%s%s";
312 intptr_t len = OS::SNPrint(NULL, 0, kFormat, 395 intptr_t len = OS::SNPrint(NULL, 0, kFormat,
313 func_class.IsTopLevel() ? "" : class_name.ToCString(), 396 func_class.IsTopLevel() ? "" : class_name.ToCString(),
314 func_class.IsTopLevel() ? "" : ".", 397 func_class.IsTopLevel() ? "" : ".",
315 func_name.ToCString()); 398 func_name.ToCString());
(...skipping 20 matching lines...) Expand all
336 } 419 }
337 420
338 421
339 bool Debugger::HasBreakpoint(const Function& func) { 422 bool Debugger::HasBreakpoint(const Function& func) {
340 if (!func.HasCode()) { 423 if (!func.HasCode()) {
341 // If the function is not compiled yet, just check whether there 424 // If the function is not compiled yet, just check whether there
342 // is a user-defined breakpoint that falls into the token 425 // is a user-defined breakpoint that falls into the token
343 // range of the function. This may be a false positive: the breakpoint 426 // range of the function. This may be a false positive: the breakpoint
344 // might be inside a local closure. 427 // might be inside a local closure.
345 Script& script = Script::Handle(isolate_); 428 Script& script = Script::Handle(isolate_);
346 SourceBreakpoint* sbpt = src_breakpoints_; 429 BreakpointLocation* sbpt = breakpoint_locations_;
347 while (sbpt != NULL) { 430 while (sbpt != NULL) {
348 script = sbpt->script(); 431 script = sbpt->script();
349 if (FunctionContains(func, script, sbpt->token_pos())) { 432 if (FunctionContains(func, script, sbpt->token_pos())) {
350 return true; 433 return true;
351 } 434 }
352 sbpt = sbpt->next_; 435 sbpt = sbpt->next_;
353 } 436 }
354 return false; 437 return false;
355 } 438 }
356 CodeBreakpoint* cbpt = code_breakpoints_; 439 CodeBreakpoint* cbpt = code_breakpoints_;
(...skipping 13 matching lines...) Expand all
370 if (code.raw() == cbpt->code_) { 453 if (code.raw() == cbpt->code_) {
371 return true; 454 return true;
372 } 455 }
373 cbpt = cbpt->next_; 456 cbpt = cbpt->next_;
374 } 457 }
375 return false; 458 return false;
376 } 459 }
377 460
378 461
379 void Debugger::PrintBreakpointsToJSONArray(JSONArray* jsarr) const { 462 void Debugger::PrintBreakpointsToJSONArray(JSONArray* jsarr) const {
380 SourceBreakpoint* sbpt = src_breakpoints_; 463 BreakpointLocation* sbpt = breakpoint_locations_;
381 while (sbpt != NULL) { 464 while (sbpt != NULL) {
382 jsarr->AddValue(sbpt); 465 Breakpoint* bpt = sbpt->breakpoints();
466 while (bpt != NULL) {
467 jsarr->AddValue(bpt);
468 bpt = bpt->next();
469 }
383 sbpt = sbpt->next_; 470 sbpt = sbpt->next_;
384 } 471 }
385 } 472 }
386 473
387 474
388 RawString* ActivationFrame::QualifiedFunctionName() { 475 RawString* ActivationFrame::QualifiedFunctionName() {
389 return String::New(Debugger::QualifiedFunctionName(function())); 476 return String::New(Debugger::QualifiedFunctionName(function()));
390 } 477 }
391 478
392 479
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
669 vars_initialized_ = true; 756 vars_initialized_ = true;
670 } 757 }
671 758
672 759
673 intptr_t ActivationFrame::NumLocalVariables() { 760 intptr_t ActivationFrame::NumLocalVariables() {
674 GetDescIndices(); 761 GetDescIndices();
675 return desc_indices_.length(); 762 return desc_indices_.length();
676 } 763 }
677 764
678 765
766 RawObject* ActivationFrame::GetParameter(intptr_t index) {
767 intptr_t num_parameters = function().num_fixed_parameters();
768 ASSERT(0 <= index && index < num_parameters);
769 intptr_t reverse_index = num_parameters - index;
770
771 if (function().NumOptionalParameters() > 0) {
772 // If the function has optional parameters, the first positional parameter
773 // can be in a number of places in the caller's frame depending on how many
774 // were actually supplied at the call site, but they are copied to a fixed
775 // place in the callee's frame.
776 uword var_address = fp() + ((kFirstLocalSlotFromFp - index) * kWordSize);
777 return reinterpret_cast<RawObject*>(
778 *reinterpret_cast<uword*>(var_address));
779 } else {
780 uword var_address = fp() + (kParamEndSlotFromFp * kWordSize)
781 + (reverse_index * kWordSize);
782 return reinterpret_cast<RawObject*>(
783 *reinterpret_cast<uword*>(var_address));
784 }
785 }
786
787
788 RawObject* ActivationFrame::GetClosure() {
789 ASSERT(function().IsClosureFunction());
790 return GetParameter(0);
791 }
792
793
679 RawObject* ActivationFrame::GetLocalVar(intptr_t slot_index) { 794 RawObject* ActivationFrame::GetLocalVar(intptr_t slot_index) {
680 if (deopt_frame_.IsNull()) { 795 if (deopt_frame_.IsNull()) {
681 uword var_address = fp() + slot_index * kWordSize; 796 uword var_address = fp() + slot_index * kWordSize;
682 return reinterpret_cast<RawObject*>( 797 return reinterpret_cast<RawObject*>(
683 *reinterpret_cast<uword*>(var_address)); 798 *reinterpret_cast<uword*>(var_address));
684 } else { 799 } else {
685 return deopt_frame_.At(deopt_frame_offset_ + slot_index); 800 return deopt_frame_.At(deopt_frame_offset_ + slot_index);
686 } 801 }
687 } 802 }
688 803
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
939 1054
940 CodeBreakpoint::CodeBreakpoint(const Code& code, 1055 CodeBreakpoint::CodeBreakpoint(const Code& code,
941 intptr_t token_pos, 1056 intptr_t token_pos,
942 uword pc, 1057 uword pc,
943 RawPcDescriptors::Kind kind) 1058 RawPcDescriptors::Kind kind)
944 : code_(code.raw()), 1059 : code_(code.raw()),
945 token_pos_(token_pos), 1060 token_pos_(token_pos),
946 pc_(pc), 1061 pc_(pc),
947 line_number_(-1), 1062 line_number_(-1),
948 is_enabled_(false), 1063 is_enabled_(false),
949 src_bpt_(NULL), 1064 bpt_location_(NULL),
950 next_(NULL), 1065 next_(NULL),
951 breakpoint_kind_(kind), 1066 breakpoint_kind_(kind),
952 saved_value_(0) { 1067 saved_value_(0) {
953 ASSERT(!code.IsNull()); 1068 ASSERT(!code.IsNull());
954 ASSERT(token_pos_ > 0); 1069 ASSERT(token_pos_ > 0);
955 ASSERT(pc_ != 0); 1070 ASSERT(pc_ != 0);
956 ASSERT((breakpoint_kind_ & kSafepointKind) != 0); 1071 ASSERT((breakpoint_kind_ & kSafepointKind) != 0);
957 } 1072 }
958 1073
959 1074
960 CodeBreakpoint::~CodeBreakpoint() { 1075 CodeBreakpoint::~CodeBreakpoint() {
961 // Make sure we don't leave patched code behind. 1076 // Make sure we don't leave patched code behind.
962 ASSERT(!IsEnabled()); 1077 ASSERT(!IsEnabled());
963 // Poison the data so we catch use after free errors. 1078 // Poison the data so we catch use after free errors.
964 #ifdef DEBUG 1079 #ifdef DEBUG
965 code_ = Code::null(); 1080 code_ = Code::null();
966 pc_ = 0ul; 1081 pc_ = 0ul;
967 src_bpt_ = NULL; 1082 bpt_location_ = NULL;
968 next_ = NULL; 1083 next_ = NULL;
969 breakpoint_kind_ = RawPcDescriptors::kOther; 1084 breakpoint_kind_ = RawPcDescriptors::kOther;
970 #endif 1085 #endif
971 } 1086 }
972 1087
973 1088
974 RawFunction* CodeBreakpoint::function() const { 1089 RawFunction* CodeBreakpoint::function() const {
975 return Code::Handle(code_).function(); 1090 return Code::Handle(code_).function();
976 } 1091 }
977 1092
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1036 ASSERT(IsValidId(obj_id)); 1151 ASSERT(IsValidId(obj_id));
1037 return objs_->At(obj_id); 1152 return objs_->At(obj_id);
1038 } 1153 }
1039 1154
1040 1155
1041 Debugger::Debugger() 1156 Debugger::Debugger()
1042 : isolate_(NULL), 1157 : isolate_(NULL),
1043 isolate_id_(ILLEGAL_ISOLATE_ID), 1158 isolate_id_(ILLEGAL_ISOLATE_ID),
1044 initialized_(false), 1159 initialized_(false),
1045 next_id_(1), 1160 next_id_(1),
1046 latent_breakpoints_(NULL), 1161 latent_locations_(NULL),
1047 src_breakpoints_(NULL), 1162 breakpoint_locations_(NULL),
1048 code_breakpoints_(NULL), 1163 code_breakpoints_(NULL),
1049 resume_action_(kContinue), 1164 resume_action_(kContinue),
1050 ignore_breakpoints_(false), 1165 ignore_breakpoints_(false),
1051 pause_event_(NULL), 1166 pause_event_(NULL),
1052 obj_cache_(NULL), 1167 obj_cache_(NULL),
1053 stack_trace_(NULL), 1168 stack_trace_(NULL),
1054 stepping_fp_(0), 1169 stepping_fp_(0),
1055 exc_pause_info_(kNoPauseOnExceptions) { 1170 exc_pause_info_(kNoPauseOnExceptions) {
1056 } 1171 }
1057 1172
1058 1173
1059 Debugger::~Debugger() { 1174 Debugger::~Debugger() {
1060 isolate_id_ = ILLEGAL_ISOLATE_ID; 1175 isolate_id_ = ILLEGAL_ISOLATE_ID;
1061 ASSERT(!IsPaused()); 1176 ASSERT(!IsPaused());
1062 ASSERT(latent_breakpoints_ == NULL); 1177 ASSERT(latent_locations_ == NULL);
1063 ASSERT(src_breakpoints_ == NULL); 1178 ASSERT(breakpoint_locations_ == NULL);
1064 ASSERT(code_breakpoints_ == NULL); 1179 ASSERT(code_breakpoints_ == NULL);
1065 ASSERT(stack_trace_ == NULL); 1180 ASSERT(stack_trace_ == NULL);
1066 ASSERT(obj_cache_ == NULL); 1181 ASSERT(obj_cache_ == NULL);
1067 } 1182 }
1068 1183
1069 1184
1070 void Debugger::Shutdown() { 1185 void Debugger::Shutdown() {
1071 while (src_breakpoints_ != NULL) { 1186 while (breakpoint_locations_ != NULL) {
1072 SourceBreakpoint* bpt = src_breakpoints_; 1187 BreakpointLocation* bpt = breakpoint_locations_;
1073 src_breakpoints_ = src_breakpoints_->next(); 1188 breakpoint_locations_ = breakpoint_locations_->next();
1074 delete bpt; 1189 delete bpt;
1075 } 1190 }
1076 while (latent_breakpoints_ != NULL) { 1191 while (latent_locations_ != NULL) {
1077 SourceBreakpoint* bpt = latent_breakpoints_; 1192 BreakpointLocation* bpt = latent_locations_;
1078 latent_breakpoints_ = latent_breakpoints_->next(); 1193 latent_locations_ = latent_locations_->next();
1079 delete bpt; 1194 delete bpt;
1080 } 1195 }
1081 while (code_breakpoints_ != NULL) { 1196 while (code_breakpoints_ != NULL) {
1082 CodeBreakpoint* bpt = code_breakpoints_; 1197 CodeBreakpoint* bpt = code_breakpoints_;
1083 code_breakpoints_ = code_breakpoints_->next(); 1198 code_breakpoints_ = code_breakpoints_->next();
1084 bpt->Disable(); 1199 bpt->Disable();
1085 delete bpt; 1200 delete bpt;
1086 } 1201 }
1087 // Signal isolate shutdown event. 1202 // Signal isolate shutdown event.
1088 if (!ServiceIsolate::IsServiceIsolateDescendant(isolate_)) { 1203 if (!ServiceIsolate::IsServiceIsolateDescendant(isolate_)) {
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
1186 if (function.HasOptimizedCode()) { 1301 if (function.HasOptimizedCode()) {
1187 function.SwitchToUnoptimizedCode(); 1302 function.SwitchToUnoptimizedCode();
1188 } 1303 }
1189 } 1304 }
1190 } 1305 }
1191 } 1306 }
1192 } 1307 }
1193 } 1308 }
1194 1309
1195 1310
1196 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { 1311 void Debugger::SignalBpResolved(Breakpoint* bpt) {
1197 if (HasEventHandler() && !bpt->IsOneShot()) { 1312 if (HasEventHandler() && !bpt->IsSingleShot()) {
1198 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointResolved); 1313 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointResolved);
1199 event.set_breakpoint(bpt); 1314 event.set_breakpoint(bpt);
1200 InvokeEventHandler(&event); 1315 InvokeEventHandler(&event);
1201 } 1316 }
1202 } 1317 }
1203 1318
1204 1319
1205 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate, 1320 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate,
1206 uword pc, 1321 uword pc,
1207 StackFrame* frame, 1322 StackFrame* frame,
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
1505 // We didn't find a safe point in the given token range. Try and find 1620 // We didn't find a safe point in the given token range. Try and find
1506 // a safe point in the remaining source code of the function. 1621 // a safe point in the remaining source code of the function.
1507 if (last_token_pos < func.end_token_pos()) { 1622 if (last_token_pos < func.end_token_pos()) {
1508 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos()); 1623 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos());
1509 } 1624 }
1510 return -1; 1625 return -1;
1511 } 1626 }
1512 1627
1513 1628
1514 void Debugger::MakeCodeBreakpointAt(const Function& func, 1629 void Debugger::MakeCodeBreakpointAt(const Function& func,
1515 SourceBreakpoint* bpt) { 1630 BreakpointLocation* loc) {
1516 ASSERT(bpt->token_pos_ != Scanner::kNoSourcePos); 1631 ASSERT(loc->token_pos_ != Scanner::kNoSourcePos);
1517 ASSERT((bpt != NULL) && bpt->IsResolved()); 1632 ASSERT((loc != NULL) && loc->IsResolved());
1518 ASSERT(!func.HasOptimizedCode()); 1633 ASSERT(!func.HasOptimizedCode());
1519 Code& code = Code::Handle(func.unoptimized_code()); 1634 Code& code = Code::Handle(func.unoptimized_code());
1520 ASSERT(!code.IsNull()); 1635 ASSERT(!code.IsNull());
1521 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); 1636 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
1522 uword lowest_pc_offset = kUwordMax; 1637 uword lowest_pc_offset = kUwordMax;
1523 RawPcDescriptors::Kind lowest_kind = RawPcDescriptors::kAnyKind; 1638 RawPcDescriptors::Kind lowest_kind = RawPcDescriptors::kAnyKind;
1524 // Find the safe point with the lowest compiled code address 1639 // Find the safe point with the lowest compiled code address
1525 // that maps to the token position of the source breakpoint. 1640 // that maps to the token position of the source breakpoint.
1526 PcDescriptors::Iterator iter(desc, kSafepointKind); 1641 PcDescriptors::Iterator iter(desc, kSafepointKind);
1527 while (iter.MoveNext()) { 1642 while (iter.MoveNext()) {
1528 if (iter.TokenPos() == bpt->token_pos_) { 1643 if (iter.TokenPos() == loc->token_pos_) {
1529 if (iter.PcOffset() < lowest_pc_offset) { 1644 if (iter.PcOffset() < lowest_pc_offset) {
1530 lowest_pc_offset = iter.PcOffset(); 1645 lowest_pc_offset = iter.PcOffset();
1531 lowest_kind = iter.Kind(); 1646 lowest_kind = iter.Kind();
1532 } 1647 }
1533 } 1648 }
1534 } 1649 }
1535 if (lowest_pc_offset == kUwordMax) { 1650 if (lowest_pc_offset == kUwordMax) {
1536 return; 1651 return;
1537 } 1652 }
1538 uword lowest_pc = code.EntryPoint() + lowest_pc_offset; 1653 uword lowest_pc = code.EntryPoint() + lowest_pc_offset;
1539 CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_pc); 1654 CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_pc);
1540 if (code_bpt == NULL) { 1655 if (code_bpt == NULL) {
1541 // No code breakpoint for this code exists; create one. 1656 // No code breakpoint for this code exists; create one.
1542 code_bpt = new CodeBreakpoint(code, bpt->token_pos_, 1657 code_bpt = new CodeBreakpoint(code, loc->token_pos_,
1543 lowest_pc, lowest_kind); 1658 lowest_pc, lowest_kind);
1544 RegisterCodeBreakpoint(code_bpt); 1659 RegisterCodeBreakpoint(code_bpt);
1545 } 1660 }
1546 code_bpt->set_src_bpt(bpt); 1661 code_bpt->set_bpt_location(loc);
1547 if (bpt->IsEnabled()) { 1662 if (loc->AnyEnabled()) {
1548 code_bpt->Enable(); 1663 code_bpt->Enable();
1549 } 1664 }
1550 } 1665 }
1551 1666
1552 1667
1553 void Debugger::FindCompiledFunctions(const Script& script, 1668 void Debugger::FindCompiledFunctions(const Script& script,
1554 intptr_t start_pos, 1669 intptr_t start_pos,
1555 intptr_t end_pos, 1670 intptr_t end_pos,
1556 GrowableObjectArray* function_list) { 1671 GrowableObjectArray* function_list) {
1557 Class& cls = Class::Handle(isolate_); 1672 Class& cls = Class::Handle(isolate_);
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
1689 SelectBestFit(&best_fit, &function); 1804 SelectBestFit(&best_fit, &function);
1690 } 1805 }
1691 } 1806 }
1692 } 1807 }
1693 } 1808 }
1694 } 1809 }
1695 return best_fit.raw(); 1810 return best_fit.raw();
1696 } 1811 }
1697 1812
1698 1813
1699 SourceBreakpoint* Debugger::SetBreakpoint(const Script& script, 1814 BreakpointLocation* Debugger::SetBreakpoint(const Script& script,
1700 intptr_t token_pos, 1815 intptr_t token_pos,
1701 intptr_t last_token_pos) { 1816 intptr_t last_token_pos) {
1702 Function& func = Function::Handle(isolate_); 1817 Function& func = Function::Handle(isolate_);
1703 func = FindBestFit(script, token_pos); 1818 func = FindBestFit(script, token_pos);
1704 if (func.IsNull()) { 1819 if (func.IsNull()) {
1705 return NULL; 1820 return NULL;
1706 } 1821 }
1707 // There may be more than one function object for a given function 1822 // There may be more than one function object for a given function
1708 // in source code. There may be implicit closure functions, and 1823 // in source code. There may be implicit closure functions, and
1709 // there may be copies of mixin functions. Collect all compiled 1824 // there may be copies of mixin functions. Collect all compiled
1710 // functions whose source code range matches exactly the best fit 1825 // functions whose source code range matches exactly the best fit
1711 // function we found. 1826 // function we found.
1712 GrowableObjectArray& functions = 1827 GrowableObjectArray& functions =
1713 GrowableObjectArray::Handle(GrowableObjectArray::New()); 1828 GrowableObjectArray::Handle(GrowableObjectArray::New());
1714 FindCompiledFunctions(script, 1829 FindCompiledFunctions(script,
1715 func.token_pos(), 1830 func.token_pos(),
1716 func.end_token_pos(), 1831 func.end_token_pos(),
1717 &functions); 1832 &functions);
1718 1833
1719 if (functions.Length() > 0) { 1834 if (functions.Length() > 0) {
1720 // One or more function object containing this breakpoint location 1835 // One or more function object containing this breakpoint location
1721 // have already been compiled. We can resolve the breakpoint now. 1836 // have already been compiled. We can resolve the breakpoint now.
1722 DeoptimizeWorld(); 1837 DeoptimizeWorld();
1723 func ^= functions.At(0); 1838 func ^= functions.At(0);
1724 intptr_t breakpoint_pos = 1839 intptr_t breakpoint_pos =
1725 ResolveBreakpointPos(func, token_pos, last_token_pos); 1840 ResolveBreakpointPos(func, token_pos, last_token_pos);
1726 if (breakpoint_pos >= 0) { 1841 if (breakpoint_pos >= 0) {
1727 SourceBreakpoint* bpt = GetSourceBreakpoint(script, breakpoint_pos); 1842 BreakpointLocation* bpt = GetBreakpointLocation(script, breakpoint_pos);
1728 if (bpt != NULL) { 1843 if (bpt != NULL) {
1729 // A source breakpoint for this location already exists. 1844 // A source breakpoint for this location already exists.
1730 return bpt; 1845 return bpt;
1731 } 1846 }
1732 bpt = new SourceBreakpoint(nextId(), script, token_pos, last_token_pos); 1847 bpt = new BreakpointLocation(script, token_pos, last_token_pos);
1733 bpt->SetResolved(func, breakpoint_pos); 1848 bpt->SetResolved(func, breakpoint_pos);
1734 RegisterSourceBreakpoint(bpt); 1849 RegisterBreakpointLocation(bpt);
1735 1850
1736 // Create code breakpoints for all compiled functions we found. 1851 // Create code breakpoints for all compiled functions we found.
1737 const intptr_t num_functions = functions.Length(); 1852 const intptr_t num_functions = functions.Length();
1738 for (intptr_t i = 0; i < num_functions; i++) { 1853 for (intptr_t i = 0; i < num_functions; i++) {
1739 func ^= functions.At(i); 1854 func ^= functions.At(i);
1740 ASSERT(func.HasCode()); 1855 ASSERT(func.HasCode());
1741 MakeCodeBreakpointAt(func, bpt); 1856 MakeCodeBreakpointAt(func, bpt);
1742 } 1857 }
1743 bpt->Enable();
1744 if (FLAG_verbose_debug) { 1858 if (FLAG_verbose_debug) {
1745 intptr_t line_number; 1859 intptr_t line_number;
1746 script.GetTokenLocation(breakpoint_pos, &line_number, NULL); 1860 script.GetTokenLocation(breakpoint_pos, &line_number, NULL);
1747 OS::Print("Resolved BP for " 1861 OS::Print("Resolved BP for "
1748 "function '%s' at line %" Pd "\n", 1862 "function '%s' at line %" Pd "\n",
1749 func.ToFullyQualifiedCString(), 1863 func.ToFullyQualifiedCString(),
1750 line_number); 1864 line_number);
1751 } 1865 }
1752 SignalBpResolved(bpt);
1753 SendServiceBreakpointEvent(ServiceEvent::kBreakpointAdded, bpt);
1754 return bpt; 1866 return bpt;
1755 } 1867 }
1756 } 1868 }
1757 // There is no compiled function at this token position. 1869 // There is no compiled function at this token position.
1758 // Register an unresolved breakpoint. 1870 // Register an unresolved breakpoint.
1759 if (FLAG_verbose_debug && !func.IsNull()) { 1871 if (FLAG_verbose_debug && !func.IsNull()) {
1760 intptr_t line_number; 1872 intptr_t line_number;
1761 script.GetTokenLocation(token_pos, &line_number, NULL); 1873 script.GetTokenLocation(token_pos, &line_number, NULL);
1762 OS::Print("Registering pending breakpoint for " 1874 OS::Print("Registering pending breakpoint for "
1763 "uncompiled function '%s' at line %" Pd "\n", 1875 "uncompiled function '%s' at line %" Pd "\n",
1764 func.ToFullyQualifiedCString(), 1876 func.ToFullyQualifiedCString(),
1765 line_number); 1877 line_number);
1766 } 1878 }
1767 SourceBreakpoint* bpt = GetSourceBreakpoint(script, token_pos); 1879 BreakpointLocation* bpt = GetBreakpointLocation(script, token_pos);
1768 if (bpt == NULL) { 1880 if (bpt == NULL) {
1769 bpt = new SourceBreakpoint(nextId(), script, token_pos, last_token_pos); 1881 bpt = new BreakpointLocation(script, token_pos, last_token_pos);
1770 RegisterSourceBreakpoint(bpt); 1882 RegisterBreakpointLocation(bpt);
1771 SendServiceBreakpointEvent(ServiceEvent::kBreakpointAdded, bpt);
1772 } 1883 }
1773 bpt->Enable();
1774 return bpt; 1884 return bpt;
1775 } 1885 }
1776 1886
1777 1887
1778 // Synchronize the enabled/disabled state of all code breakpoints 1888 // Synchronize the enabled/disabled state of all code breakpoints
1779 // associated with the source breakpoint bpt. 1889 // associated with the breakpoint location loc.
1780 void Debugger::SyncBreakpoint(SourceBreakpoint* bpt) { 1890 void Debugger::SyncBreakpointLocation(BreakpointLocation* loc) {
1891 bool any_enabled = loc->AnyEnabled();
1892
1781 CodeBreakpoint* cbpt = code_breakpoints_; 1893 CodeBreakpoint* cbpt = code_breakpoints_;
1782 while (cbpt != NULL) { 1894 while (cbpt != NULL) {
1783 if (bpt == cbpt->src_bpt()) { 1895 if (loc == cbpt->bpt_location()) {
1784 if (bpt->IsEnabled()) { 1896 if (any_enabled) {
1785 cbpt->Enable(); 1897 cbpt->Enable();
1786 } else { 1898 } else {
1787 cbpt->Disable(); 1899 cbpt->Disable();
1788 } 1900 }
1789 } 1901 }
1790 cbpt = cbpt->next(); 1902 cbpt = cbpt->next();
1791 } 1903 }
1792 } 1904 }
1793 1905
1794 1906
1795 RawError* Debugger::OneTimeBreakAtEntry(const Function& target_function) { 1907 RawError* Debugger::OneTimeBreakAtEntry(const Function& target_function) {
1796 LongJumpScope jump; 1908 LongJumpScope jump;
1797 if (setjmp(*jump.Set()) == 0) { 1909 if (setjmp(*jump.Set()) == 0) {
1798 SourceBreakpoint* bpt = SetBreakpointAtEntry(target_function); 1910 SetBreakpointAtEntry(target_function, true);
1799 if (bpt != NULL) {
1800 bpt->SetIsOneShot();
1801 }
1802 return Error::null(); 1911 return Error::null();
1803 } else { 1912 } else {
1804 return isolate_->object_store()->sticky_error(); 1913 return isolate_->object_store()->sticky_error();
1805 } 1914 }
1806 } 1915 }
1807 1916
1808 1917
1809 SourceBreakpoint* Debugger::SetBreakpointAtEntry( 1918 Breakpoint* Debugger::SetBreakpointAtEntry(const Function& target_function,
1810 const Function& target_function) { 1919 bool single_shot) {
1811 ASSERT(!target_function.IsNull()); 1920 ASSERT(!target_function.IsNull());
1812 if (!target_function.is_debuggable()) { 1921 if (!target_function.is_debuggable()) {
1813 return NULL; 1922 return NULL;
1814 } 1923 }
1815 const Script& script = Script::Handle(target_function.script()); 1924 const Script& script = Script::Handle(target_function.script());
1816 return SetBreakpoint(script, 1925 BreakpointLocation* bpt_location =
1817 target_function.token_pos(), 1926 SetBreakpoint(script,
1818 target_function.end_token_pos()); 1927 target_function.token_pos(),
1928 target_function.end_token_pos());
1929 if (single_shot) {
1930 return bpt_location->AddSingleShot(this);
1931 } else {
1932 return bpt_location->AddRepeated(this);
1933 }
1819 } 1934 }
1820 1935
1821 1936
1822 SourceBreakpoint* Debugger::SetBreakpointAtLine(const String& script_url, 1937 Breakpoint* Debugger::SetBreakpointAtActivation(
1823 intptr_t line_number) { 1938 const Instance& closure) {
1939 if (!closure.IsClosure()) {
1940 return NULL;
1941 }
1942 const Function& func = Function::Handle(Closure::function(closure));
1943 const Script& script = Script::Handle(func.script());
1944 BreakpointLocation* bpt = SetBreakpoint(script,
1945 func.token_pos(),
1946 func.end_token_pos());
1947 return bpt->AddPerClosure(this, closure);
1948 }
1949
1950
1951 Breakpoint* Debugger::SetBreakpointAtLine(const String& script_url,
1952 intptr_t line_number) {
1953 BreakpointLocation* bpt = BreakpointLocationAtLine(script_url, line_number);
1954 return bpt->AddRepeated(this);
1955 }
1956
1957
1958 BreakpointLocation* Debugger::BreakpointLocationAtLine(const String& script_url,
1959 intptr_t line_number) {
1824 Library& lib = Library::Handle(isolate_); 1960 Library& lib = Library::Handle(isolate_);
1825 Script& script = Script::Handle(isolate_); 1961 Script& script = Script::Handle(isolate_);
1826 const GrowableObjectArray& libs = 1962 const GrowableObjectArray& libs =
1827 GrowableObjectArray::Handle(isolate_->object_store()->libraries()); 1963 GrowableObjectArray::Handle(isolate_->object_store()->libraries());
1828 const GrowableObjectArray& scripts = 1964 const GrowableObjectArray& scripts =
1829 GrowableObjectArray::Handle(isolate_, GrowableObjectArray::New()); 1965 GrowableObjectArray::Handle(isolate_, GrowableObjectArray::New());
1830 for (intptr_t i = 0; i < libs.Length(); i++) { 1966 for (intptr_t i = 0; i < libs.Length(); i++) {
1831 lib ^= libs.At(i); 1967 lib ^= libs.At(i);
1832 script = lib.LookupScript(script_url); 1968 script = lib.LookupScript(script_url);
1833 if (!script.IsNull()) { 1969 if (!script.IsNull()) {
1834 scripts.Add(script); 1970 scripts.Add(script);
1835 } 1971 }
1836 } 1972 }
1837 if (scripts.Length() == 0) { 1973 if (scripts.Length() == 0) {
1838 // No script found with given url. Create a latent breakpoint which 1974 // No script found with given url. Create a latent breakpoint which
1839 // will be set if the url is loaded later. 1975 // will be set if the url is loaded later.
1840 SourceBreakpoint* latent_bpt = GetLatentBreakpoint(script_url, line_number); 1976 BreakpointLocation* latent_bpt = GetLatentBreakpoint(script_url,
1977 line_number);
1841 if (FLAG_verbose_debug) { 1978 if (FLAG_verbose_debug) {
1842 OS::Print("Set latent breakpoint in url '%s' at line %" Pd "\n", 1979 OS::Print("Set latent breakpoint in url '%s' at line %" Pd "\n",
1843 script_url.ToCString(), 1980 script_url.ToCString(),
1844 line_number); 1981 line_number);
1845 } 1982 }
1846 return latent_bpt; 1983 return latent_bpt;
1847 } 1984 }
1848 if (scripts.Length() > 1) { 1985 if (scripts.Length() > 1) {
1849 if (FLAG_verbose_debug) { 1986 if (FLAG_verbose_debug) {
1850 OS::Print("Multiple scripts match url '%s'\n", script_url.ToCString()); 1987 OS::Print("Multiple scripts match url '%s'\n", script_url.ToCString());
(...skipping 12 matching lines...) Expand all
1863 return NULL; 2000 return NULL;
1864 } else if (last_token_idx < 0) { 2001 } else if (last_token_idx < 0) {
1865 // Line does not contain any tokens. 2002 // Line does not contain any tokens.
1866 if (FLAG_verbose_debug) { 2003 if (FLAG_verbose_debug) {
1867 OS::Print("No executable code at line %" Pd " in '%s'\n", 2004 OS::Print("No executable code at line %" Pd " in '%s'\n",
1868 line_number, script_url.ToCString()); 2005 line_number, script_url.ToCString());
1869 } 2006 }
1870 return NULL; 2007 return NULL;
1871 } 2008 }
1872 2009
1873 SourceBreakpoint* bpt = NULL; 2010 BreakpointLocation* bpt = NULL;
1874 ASSERT(first_token_idx <= last_token_idx); 2011 ASSERT(first_token_idx <= last_token_idx);
1875 while ((bpt == NULL) && (first_token_idx <= last_token_idx)) { 2012 while ((bpt == NULL) && (first_token_idx <= last_token_idx)) {
1876 bpt = SetBreakpoint(script, first_token_idx, last_token_idx); 2013 bpt = SetBreakpoint(script, first_token_idx, last_token_idx);
1877 first_token_idx++; 2014 first_token_idx++;
1878 } 2015 }
1879 if ((bpt == NULL) && FLAG_verbose_debug) { 2016 if ((bpt == NULL) && FLAG_verbose_debug) {
1880 OS::Print("No executable code at line %" Pd " in '%s'\n", 2017 OS::Print("No executable code at line %" Pd " in '%s'\n",
1881 line_number, script_url.ToCString()); 2018 line_number, script_url.ToCString());
1882 } 2019 }
1883 return bpt; 2020 return bpt;
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
2077 CollectLibraryFields(field_list, imported, prefix_name, false); 2214 CollectLibraryFields(field_list, imported, prefix_name, false);
2078 } 2215 }
2079 } 2216 }
2080 return Array::MakeArray(field_list); 2217 return Array::MakeArray(field_list);
2081 } 2218 }
2082 2219
2083 2220
2084 // static 2221 // static
2085 void Debugger::VisitObjectPointers(ObjectPointerVisitor* visitor) { 2222 void Debugger::VisitObjectPointers(ObjectPointerVisitor* visitor) {
2086 ASSERT(visitor != NULL); 2223 ASSERT(visitor != NULL);
2087 SourceBreakpoint* bpt = src_breakpoints_; 2224 BreakpointLocation* bpt = breakpoint_locations_;
2088 while (bpt != NULL) { 2225 while (bpt != NULL) {
2089 bpt->VisitObjectPointers(visitor); 2226 bpt->VisitObjectPointers(visitor);
2090 bpt = bpt->next(); 2227 bpt = bpt->next();
2091 } 2228 }
2092 bpt = latent_breakpoints_; 2229 bpt = latent_locations_;
2093 while (bpt != NULL) { 2230 while (bpt != NULL) {
2094 bpt->VisitObjectPointers(visitor); 2231 bpt->VisitObjectPointers(visitor);
2095 bpt = bpt->next(); 2232 bpt = bpt->next();
2096 } 2233 }
2097 CodeBreakpoint* cbpt = code_breakpoints_; 2234 CodeBreakpoint* cbpt = code_breakpoints_;
2098 while (cbpt != NULL) { 2235 while (cbpt != NULL) {
2099 cbpt->VisitObjectPointers(visitor); 2236 cbpt->VisitObjectPointers(visitor);
2100 cbpt = cbpt->next(); 2237 cbpt = cbpt->next();
2101 } 2238 }
2102 } 2239 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2165 if (ServiceIsolate::IsRunning()) { 2302 if (ServiceIsolate::IsRunning()) {
2166 return true; 2303 return true;
2167 } 2304 }
2168 const Class& cls = Class::Handle(func.Owner()); 2305 const Class& cls = Class::Handle(func.Owner());
2169 const Library& lib = Library::Handle(cls.library()); 2306 const Library& lib = Library::Handle(cls.library());
2170 return lib.IsDebuggable(); 2307 return lib.IsDebuggable();
2171 } 2308 }
2172 2309
2173 2310
2174 void Debugger::SignalPausedEvent(ActivationFrame* top_frame, 2311 void Debugger::SignalPausedEvent(ActivationFrame* top_frame,
2175 SourceBreakpoint* bpt) { 2312 Breakpoint* bpt) {
2176 resume_action_ = kContinue; 2313 resume_action_ = kContinue;
2177 stepping_fp_ = 0; 2314 stepping_fp_ = 0;
2178 isolate_->set_single_step(false); 2315 isolate_->set_single_step(false);
2179 ASSERT(!IsPaused()); 2316 ASSERT(!IsPaused());
2180 ASSERT(obj_cache_ == NULL); 2317 ASSERT(obj_cache_ == NULL);
2181 if ((bpt != NULL) && bpt->IsOneShot()) { 2318 if ((bpt != NULL) && bpt->IsSingleShot()) {
2182 RemoveBreakpoint(bpt->id()); 2319 RemoveBreakpoint(bpt->id());
2183 bpt = NULL; 2320 bpt = NULL;
2184 } 2321 }
2185 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointReached); 2322 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointReached);
2186 event.set_top_frame(top_frame); 2323 event.set_top_frame(top_frame);
2187 event.set_breakpoint(bpt); 2324 event.set_breakpoint(bpt);
2188 Pause(&event); 2325 Pause(&event);
2189 } 2326 }
2190 2327
2191 2328
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
2253 // We ignore this breakpoint when the VM is executing code invoked 2390 // We ignore this breakpoint when the VM is executing code invoked
2254 // by the debugger to evaluate variables values, or when we see a nested 2391 // by the debugger to evaluate variables values, or when we see a nested
2255 // breakpoint or exception event. 2392 // breakpoint or exception event.
2256 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) { 2393 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) {
2257 return; 2394 return;
2258 } 2395 }
2259 DebuggerStackTrace* stack_trace = CollectStackTrace(); 2396 DebuggerStackTrace* stack_trace = CollectStackTrace();
2260 ASSERT(stack_trace->Length() > 0); 2397 ASSERT(stack_trace->Length() > 0);
2261 ActivationFrame* top_frame = stack_trace->FrameAt(0); 2398 ActivationFrame* top_frame = stack_trace->FrameAt(0);
2262 ASSERT(top_frame != NULL); 2399 ASSERT(top_frame != NULL);
2263 CodeBreakpoint* bpt = GetCodeBreakpoint(top_frame->pc()); 2400 CodeBreakpoint* cbpt = GetCodeBreakpoint(top_frame->pc());
2264 ASSERT(bpt != NULL); 2401 ASSERT(cbpt != NULL);
2402
2403 BreakpointLocation* bpt_location = cbpt->bpt_location_;
2404 Breakpoint* bpt_hit = NULL;
hausner 2015/05/21 22:46:23 Maybe a quick explanation of the heuristics we use
rmacnak 2015/05/21 23:51:56 Done.
2405 if (bpt_location != NULL) {
2406 // Prefer a single-shot breakpoint.
2407 Breakpoint* bpt = bpt_location->breakpoints();
2408 while (bpt != NULL) {
2409 if (bpt->IsSingleShot()) {
2410 bpt_hit = bpt;
2411 break;
2412 }
2413 bpt = bpt->next();
2414 }
2415
2416 // Then a closure-specific breakpoint.
2417 if (bpt_hit == NULL) {
2418 bpt = bpt_location->breakpoints();
2419 while (bpt != NULL) {
2420 if (bpt->IsPerClosure()) {
2421 Object& closure = Object::Handle(top_frame->GetClosure());
2422 ASSERT(closure.IsInstance());
2423 ASSERT(Instance::Cast(closure).IsClosure());
2424 if (closure.raw() == bpt->closure()) {
2425 bpt_hit = bpt;
2426 break;
2427 }
2428 }
2429 bpt = bpt->next();
2430 }
2431 }
2432
2433 // Then a general breakpoint.
2434 if (bpt_hit == NULL) {
2435 bpt = bpt_location->breakpoints();
2436 while (bpt != NULL) {
2437 if (bpt->IsRepeated()) {
2438 bpt_hit = bpt;
2439 break;
2440 }
2441 bpt = bpt->next();
2442 }
2443 }
2444 }
2445
2446 if (bpt_hit == NULL) {
2447 return;
2448 }
2265 2449
2266 if (FLAG_verbose_debug) { 2450 if (FLAG_verbose_debug) {
2267 OS::Print(">>> hit %s breakpoint at %s:%" Pd " " 2451 OS::Print(">>> hit %s breakpoint at %s:%" Pd " "
2268 "(token %" Pd ") (address %#" Px ")\n", 2452 "(token %" Pd ") (address %#" Px ")\n",
2269 bpt->IsInternal() ? "internal" : "user", 2453 cbpt->IsInternal() ? "internal" : "user",
2270 String::Handle(bpt->SourceUrl()).ToCString(), 2454 String::Handle(cbpt->SourceUrl()).ToCString(),
2271 bpt->LineNumber(), 2455 cbpt->LineNumber(),
2272 bpt->token_pos(), 2456 cbpt->token_pos(),
2273 top_frame->pc()); 2457 top_frame->pc());
2274 } 2458 }
2275 2459
2276 ASSERT(stack_trace_ == NULL); 2460 ASSERT(stack_trace_ == NULL);
2277 stack_trace_ = stack_trace; 2461 stack_trace_ = stack_trace;
2278 SignalPausedEvent(top_frame, bpt->src_bpt_); 2462 SignalPausedEvent(top_frame, bpt_hit);
2279 HandleSteppingRequest(stack_trace_); 2463 HandleSteppingRequest(stack_trace_);
2280 stack_trace_ = NULL; 2464 stack_trace_ = NULL;
2281 if (bpt->IsInternal()) { 2465 if (cbpt->IsInternal()) {
2282 RemoveInternalBreakpoints(); 2466 RemoveInternalBreakpoints();
2283 } 2467 }
2284 } 2468 }
2285 2469
2286 2470
2287 void Debugger::BreakHere(const String& msg) { 2471 void Debugger::BreakHere(const String& msg) {
2288 // We ignore this breakpoint when the VM is executing code invoked 2472 // We ignore this breakpoint when the VM is executing code invoked
2289 // by the debugger to evaluate variables values, or when we see a nested 2473 // by the debugger to evaluate variables values, or when we see a nested
2290 // breakpoint or exception event. 2474 // breakpoint or exception event.
2291 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) { 2475 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
2357 (token_pos <= closure.end_token_pos()) && 2541 (token_pos <= closure.end_token_pos()) &&
2358 (closure.script() == outer_origin.raw())) { 2542 (closure.script() == outer_origin.raw())) {
2359 SelectBestFit(&best_fit, &closure); 2543 SelectBestFit(&best_fit, &closure);
2360 } 2544 }
2361 } 2545 }
2362 return best_fit.raw(); 2546 return best_fit.raw();
2363 } 2547 }
2364 2548
2365 2549
2366 void Debugger::NotifyCompilation(const Function& func) { 2550 void Debugger::NotifyCompilation(const Function& func) {
2367 if (src_breakpoints_ == NULL) { 2551 if (breakpoint_locations_ == NULL) {
2368 // Return with minimal overhead if there are no breakpoints. 2552 // Return with minimal overhead if there are no breakpoints.
2369 return; 2553 return;
2370 } 2554 }
2371 if (!func.is_debuggable()) { 2555 if (!func.is_debuggable()) {
2372 // Nothing to do if the function is not debuggable. If there is 2556 // Nothing to do if the function is not debuggable. If there is
2373 // a pending breakpoint in an inner function (that is debuggable), 2557 // a pending breakpoint in an inner function (that is debuggable),
2374 // we'll resolve the breakpoint when the inner function is compiled. 2558 // we'll resolve the breakpoint when the inner function is compiled.
2375 return; 2559 return;
2376 } 2560 }
2377 // Iterate over all source breakpoints to check whether breakpoints 2561 // Iterate over all source breakpoints to check whether breakpoints
2378 // need to be set in the newly compiled function. 2562 // need to be set in the newly compiled function.
2379 Script& script = Script::Handle(isolate_); 2563 Script& script = Script::Handle(isolate_);
2380 for (SourceBreakpoint* bpt = src_breakpoints_; 2564 for (BreakpointLocation* loc = breakpoint_locations_;
2381 bpt != NULL; 2565 loc != NULL;
2382 bpt = bpt->next()) { 2566 loc = loc->next()) {
2383 script = bpt->script(); 2567 script = loc->script();
2384 if (FunctionContains(func, script, bpt->token_pos())) { 2568 if (FunctionContains(func, script, loc->token_pos())) {
2385 Function& inner_function = Function::Handle(isolate_); 2569 Function& inner_function = Function::Handle(isolate_);
2386 inner_function = FindInnermostClosure(func, bpt->token_pos()); 2570 inner_function = FindInnermostClosure(func, loc->token_pos());
2387 if (!inner_function.IsNull()) { 2571 if (!inner_function.IsNull()) {
2388 // The local function of a function we just compiled cannot 2572 // The local function of a function we just compiled cannot
2389 // be compiled already. 2573 // be compiled already.
2390 ASSERT(!inner_function.HasCode()); 2574 ASSERT(!inner_function.HasCode());
2391 if (FLAG_verbose_debug) { 2575 if (FLAG_verbose_debug) {
2392 OS::Print("Pending BP remains unresolved in inner function '%s'\n", 2576 OS::Print("Pending BP remains unresolved in inner function '%s'\n",
2393 inner_function.ToFullyQualifiedCString()); 2577 inner_function.ToFullyQualifiedCString());
2394 } 2578 }
2395 continue; 2579 continue;
2396 } 2580 }
2397 2581
2398 // TODO(hausner): What should we do if function is optimized? 2582 // TODO(hausner): What should we do if function is optimized?
2399 // Can we deoptimize the function? 2583 // Can we deoptimize the function?
2400 ASSERT(!func.HasOptimizedCode()); 2584 ASSERT(!func.HasOptimizedCode());
2401 2585
2402 // There is no local function within func that contains the 2586 // There is no local function within func that contains the
2403 // breakpoint token position. Resolve the breakpoint if necessary 2587 // breakpoint token position. Resolve the breakpoint if necessary
2404 // and set the code breakpoints. 2588 // and set the code breakpoints.
2405 if (!bpt->IsResolved()) { 2589 if (!loc->IsResolved()) {
2406 // Resolve source breakpoint in the newly compiled function. 2590 // Resolve source breakpoint in the newly compiled function.
2407 intptr_t bp_pos = 2591 intptr_t bp_pos =
2408 ResolveBreakpointPos(func, bpt->token_pos(), bpt->end_token_pos()); 2592 ResolveBreakpointPos(func, loc->token_pos(), loc->end_token_pos());
2409 if (bp_pos < 0) { 2593 if (bp_pos < 0) {
2410 if (FLAG_verbose_debug) { 2594 if (FLAG_verbose_debug) {
2411 OS::Print("Failed resolving breakpoint for function '%s'\n", 2595 OS::Print("Failed resolving breakpoint for function '%s'\n",
2412 String::Handle(func.name()).ToCString()); 2596 String::Handle(func.name()).ToCString());
2413 } 2597 }
2414 continue; 2598 continue;
2415 } 2599 }
2416 intptr_t requested_pos = bpt->token_pos(); 2600 intptr_t requested_pos = loc->token_pos();
2417 intptr_t requested_end_pos = bpt->end_token_pos(); 2601 intptr_t requested_end_pos = loc->end_token_pos();
2418 bpt->SetResolved(func, bp_pos); 2602 loc->SetResolved(func, bp_pos);
2419 if (FLAG_verbose_debug) { 2603 Breakpoint* bpt = loc->breakpoints();
2420 OS::Print("Resolved BP %" Pd " to pos %" Pd ", line %" Pd ", " 2604 while (bpt != NULL) {
2421 "function '%s' (requested range %" Pd "-%" Pd ")\n", 2605 if (FLAG_verbose_debug) {
2606 OS::Print("Resolved BP %" Pd " to pos %" Pd ", line %" Pd ", "
2607 "function '%s' (requested range %" Pd "-%" Pd ")\n",
2608 bpt->id(),
2609 loc->token_pos(),
2610 loc->LineNumber(),
2611 func.ToFullyQualifiedCString(),
2612 requested_pos,
2613 requested_end_pos);
2614 }
2615 SignalBpResolved(bpt);
2616 SendServiceBreakpointEvent(ServiceEvent::kBreakpointResolved, bpt);
2617 bpt = bpt->next();
2618 }
2619 }
2620 ASSERT(loc->IsResolved());
2621 if (FLAG_verbose_debug) {
2622 Breakpoint* bpt = loc->breakpoints();
2623 while (bpt != NULL) {
2624 OS::Print("Setting breakpoint %" Pd " at line %" Pd " for %s '%s'\n",
2422 bpt->id(), 2625 bpt->id(),
2423 bpt->token_pos(), 2626 loc->LineNumber(),
2424 bpt->LineNumber(), 2627 func.IsClosureFunction() ? "closure" : "function",
2425 func.ToFullyQualifiedCString(), 2628 String::Handle(func.name()).ToCString());
2426 requested_pos, 2629 bpt = bpt->next();
2427 requested_end_pos);
2428 } 2630 }
2429 SignalBpResolved(bpt);
2430 SendServiceBreakpointEvent(ServiceEvent::kBreakpointResolved, bpt);
2431 } 2631 }
2432 ASSERT(bpt->IsResolved()); 2632 MakeCodeBreakpointAt(func, loc);
2433 if (FLAG_verbose_debug) {
2434 OS::Print("Setting breakpoint %" Pd " at line %" Pd " for %s '%s'\n",
2435 bpt->id(),
2436 bpt->LineNumber(),
2437 func.IsClosureFunction() ? "closure" : "function",
2438 String::Handle(func.name()).ToCString());
2439 }
2440 MakeCodeBreakpointAt(func, bpt);
2441 } 2633 }
2442 } 2634 }
2443 } 2635 }
2444 2636
2445 2637
2446 void Debugger::NotifyDoneLoading() { 2638 void Debugger::NotifyDoneLoading() {
2447 if (latent_breakpoints_ == NULL) { 2639 if (latent_locations_ == NULL) {
2448 // Common, fast path. 2640 // Common, fast path.
2449 return; 2641 return;
2450 } 2642 }
2451 Library& lib = Library::Handle(isolate_); 2643 Library& lib = Library::Handle(isolate_);
2452 Script& script = Script::Handle(isolate_); 2644 Script& script = Script::Handle(isolate_);
2453 String& url = String::Handle(isolate_); 2645 String& url = String::Handle(isolate_);
2454 SourceBreakpoint* bpt = latent_breakpoints_; 2646 BreakpointLocation* loc = latent_locations_;
2455 SourceBreakpoint* prev_bpt = NULL; 2647 BreakpointLocation* prev_loc = NULL;
2456 const GrowableObjectArray& libs = 2648 const GrowableObjectArray& libs =
2457 GrowableObjectArray::Handle(isolate_->object_store()->libraries()); 2649 GrowableObjectArray::Handle(isolate_->object_store()->libraries());
2458 while (bpt != NULL) { 2650 while (loc != NULL) {
2459 url = bpt->url(); 2651 url = loc->url();
2460 bool found_match = false; 2652 bool found_match = false;
2461 for (intptr_t i = 0; i < libs.Length(); i++) { 2653 for (intptr_t i = 0; i < libs.Length(); i++) {
2462 lib ^= libs.At(i); 2654 lib ^= libs.At(i);
2463 script = lib.LookupScript(url); 2655 script = lib.LookupScript(url);
2464 if (!script.IsNull()) { 2656 if (!script.IsNull()) {
2465 // Found a script with matching url for this latent breakpoint. 2657 // Found a script with matching url for this latent breakpoint.
2466 // Unlink the latent breakpoint from the list. 2658 // Unlink the latent breakpoint from the list.
2467 found_match = true; 2659 found_match = true;
2468 SourceBreakpoint* matched_bpt = bpt; 2660 BreakpointLocation* matched_loc = loc;
2469 bpt = bpt->next(); 2661 loc = loc->next();
2470 if (prev_bpt == NULL) { 2662 if (prev_loc == NULL) {
2471 latent_breakpoints_ = bpt; 2663 latent_locations_ = loc;
2472 } else { 2664 } else {
2473 prev_bpt->set_next(bpt); 2665 prev_loc->set_next(loc);
2474 } 2666 }
2475 // Now find the token range at the requested line and make a 2667 // Now find the token range at the requested line and make a
2476 // new unresolved source breakpoint. 2668 // new unresolved source breakpoint.
2477 intptr_t line_number = matched_bpt->LineNumber(); 2669 intptr_t line_number = matched_loc->LineNumber();
2478 ASSERT(line_number >= 0); 2670 ASSERT(line_number >= 0);
2479 intptr_t first_token_pos, last_token_pos; 2671 intptr_t first_token_pos, last_token_pos;
2480 script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos); 2672 script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos);
2481 if ((first_token_pos < 0) || 2673 if ((first_token_pos < 0) ||
2482 (last_token_pos < 0)) { 2674 (last_token_pos < 0)) {
2483 // Script does not contain the given line number or there are no 2675 // Script does not contain the given line number or there are no
2484 // tokens on the line. Drop the breakpoint silently. 2676 // tokens on the line. Drop the breakpoint silently.
2485 if (FLAG_verbose_debug) { 2677 Breakpoint* bpt = matched_loc->breakpoints();
2486 OS::Print("No code found at line %" Pd ": " 2678 while (bpt != NULL) {
2487 "dropping latent breakpoint %" Pd " in '%s'\n", 2679 if (FLAG_verbose_debug) {
2488 line_number, 2680 OS::Print("No code found at line %" Pd ": "
2489 matched_bpt->id(), 2681 "dropping latent breakpoint %" Pd " in '%s'\n",
2490 url.ToCString()); 2682 line_number,
2683 bpt->id(),
2684 url.ToCString());
2685 }
2686 Breakpoint* prev = bpt;
2687 bpt = bpt->next();
2688 delete prev;
2491 } 2689 }
2492 delete matched_bpt; 2690 delete matched_loc;
2493 } else { 2691 } else {
2494 // We don't expect to already have a breakpoint for this location. 2692 // We don't expect to already have a breakpoint for this location.
2495 // If there is one, assert in debug build but silently drop 2693 // If there is one, assert in debug build but silently drop
2496 // the latent breakpoint in release build. 2694 // the latent breakpoint in release build.
2497 SourceBreakpoint* existing_bpt = 2695 BreakpointLocation* existing_loc =
2498 GetSourceBreakpoint(script, first_token_pos); 2696 GetBreakpointLocation(script, first_token_pos);
2499 ASSERT(existing_bpt == NULL); 2697 ASSERT(existing_loc == NULL);
2500 if (existing_bpt == NULL) { 2698 if (existing_loc == NULL) {
2501 // Create and register a new source breakpoint for the 2699 // Create and register a new source breakpoint for the
2502 // latent breakpoint. 2700 // latent breakpoint.
2503 SourceBreakpoint* unresolved_bpt = 2701 BreakpointLocation* unresolved_loc =
2504 new SourceBreakpoint(matched_bpt->id(), 2702 new BreakpointLocation(script,
2505 script, 2703 first_token_pos,
2506 first_token_pos, 2704 last_token_pos);
2507 last_token_pos); 2705 RegisterBreakpointLocation(unresolved_loc);
2508 RegisterSourceBreakpoint(unresolved_bpt); 2706
2509 unresolved_bpt->Enable(); 2707 // Move breakpoints over.
2510 if (FLAG_verbose_debug) { 2708 Breakpoint* bpt = existing_loc->breakpoints();
2511 OS::Print("Converted latent breakpoint " 2709 unresolved_loc->set_breakpoints(bpt);
2512 "%" Pd " in '%s' at line %" Pd "\n", 2710 existing_loc->set_breakpoints(NULL);
2513 matched_bpt->id(), 2711 while (bpt != NULL) {
2514 url.ToCString(), 2712 bpt->set_bpt_location(unresolved_loc);
2515 line_number); 2713 if (FLAG_verbose_debug) {
2714 OS::Print("Converted latent breakpoint "
2715 "%" Pd " in '%s' at line %" Pd "\n",
2716 bpt->id(),
2717 url.ToCString(),
2718 line_number);
2719 }
2720 bpt = bpt->next();
2516 } 2721 }
2722 SyncBreakpointLocation(unresolved_loc);
2517 } 2723 }
2518 delete matched_bpt; 2724 delete matched_loc;
2519 // Break out of the iteration over loaded libraries. If the 2725 // Break out of the iteration over loaded libraries. If the
2520 // same url has been loaded into more than one library, we 2726 // same url has been loaded into more than one library, we
2521 // only set a breakpoint in the first one. 2727 // only set a breakpoint in the first one.
2522 // TODO(hausner): There is one possible pitfall here. 2728 // TODO(hausner): There is one possible pitfall here.
2523 // If the user sets a latent breakpoint using a partial url that 2729 // If the user sets a latent breakpoint using a partial url that
2524 // ends up matching more than one script, the breakpoint might 2730 // ends up matching more than one script, the breakpoint might
2525 // get set in the wrong script. 2731 // get set in the wrong script.
2526 // It would be better if we could warn the user if multiple 2732 // It would be better if we could warn the user if multiple
2527 // scripts are matching. 2733 // scripts are matching.
2528 break; 2734 break;
2529 } 2735 }
2530 } 2736 }
2531 } 2737 }
2532 if (!found_match) { 2738 if (!found_match) {
2533 // No matching url found in any of the libraries. 2739 // No matching url found in any of the libraries.
2534 if (FLAG_verbose_debug) { 2740 if (FLAG_verbose_debug) {
2535 OS::Print("No match found for latent breakpoint id " 2741 Breakpoint* bpt = loc->breakpoints();
2536 "%" Pd " with url '%s'\n", 2742 while (bpt != NULL) {
2537 bpt->id(), 2743 OS::Print("No match found for latent breakpoint id "
2538 url.ToCString()); 2744 "%" Pd " with url '%s'\n",
2745 bpt->id(),
2746 url.ToCString());
2747 bpt = bpt->next();
2748 }
2539 } 2749 }
2540 bpt = bpt->next(); 2750 loc = loc->next();
2541 } 2751 }
2542 } 2752 }
2543 } 2753 }
2544 2754
2545 2755
2546 // TODO(hausner): Could potentially make this faster by checking 2756 // TODO(hausner): Could potentially make this faster by checking
2547 // whether the call target at pc is a debugger stub. 2757 // whether the call target at pc is a debugger stub.
2548 bool Debugger::HasActiveBreakpoint(uword pc) { 2758 bool Debugger::HasActiveBreakpoint(uword pc) {
2549 CodeBreakpoint* bpt = GetCodeBreakpoint(pc); 2759 CodeBreakpoint* bpt = GetCodeBreakpoint(pc);
2550 return (bpt != NULL) && (bpt->IsEnabled()); 2760 return (bpt != NULL) && (bpt->IsEnabled());
(...skipping 18 matching lines...) Expand all
2569 return bpt->OrigStubAddress(); 2779 return bpt->OrigStubAddress();
2570 } 2780 }
2571 UNREACHABLE(); 2781 UNREACHABLE();
2572 return 0L; 2782 return 0L;
2573 } 2783 }
2574 2784
2575 2785
2576 // Remove and delete the source breakpoint bpt and its associated 2786 // Remove and delete the source breakpoint bpt and its associated
2577 // code breakpoints. 2787 // code breakpoints.
2578 void Debugger::RemoveBreakpoint(intptr_t bp_id) { 2788 void Debugger::RemoveBreakpoint(intptr_t bp_id) {
2579 SourceBreakpoint* prev_bpt = NULL; 2789 BreakpointLocation* prev_loc = NULL;
2580 SourceBreakpoint* curr_bpt = src_breakpoints_; 2790 BreakpointLocation* curr_loc = breakpoint_locations_;
2581 while (curr_bpt != NULL) { 2791 while (curr_loc != NULL) {
hausner 2015/05/21 22:46:23 Might be nice to factor out a function that return
2582 if (curr_bpt->id() == bp_id) { 2792 Breakpoint* prev_bpt = NULL;
2583 if (prev_bpt == NULL) { 2793 Breakpoint* curr_bpt = curr_loc->breakpoints();
2584 src_breakpoints_ = src_breakpoints_->next(); 2794 while (curr_bpt != NULL) {
2795 if (curr_bpt->id() == bp_id) {
2796 if (prev_bpt == NULL) {
2797 curr_loc->set_breakpoints(curr_bpt->next());
2798 } else {
2799 prev_bpt->set_next(curr_bpt->next());
2800 }
2801
2802 SendServiceBreakpointEvent(ServiceEvent::kBreakpointRemoved, curr_bpt);
2803
2804 // Remove references from the current debugger pause event.
2805 if (pause_event_ != NULL &&
2806 pause_event_->type() == DebuggerEvent::kBreakpointReached &&
2807 pause_event_->breakpoint() == curr_bpt) {
2808 pause_event_->set_breakpoint(NULL);
2809 }
2810 return;
2811 }
2812
2813 prev_bpt = curr_bpt;
2814 curr_bpt = curr_bpt->next();
2815 }
2816
2817 if (curr_loc->breakpoints() == NULL) {
2818 if (prev_loc == NULL) {
2819 breakpoint_locations_ = breakpoint_locations_->next();
2585 } else { 2820 } else {
2586 prev_bpt->set_next(curr_bpt->next()); 2821 prev_loc->set_next(curr_loc->next());
2587 } 2822 }
2588 SendServiceBreakpointEvent(ServiceEvent::kBreakpointRemoved, curr_bpt);
2589 2823
2590 // Remove references from code breakpoints to this source breakpoint, 2824 // Remove references from code breakpoints to this source breakpoint,
2591 // and disable the code breakpoints. 2825 // and disable the code breakpoints.
2592 UnlinkCodeBreakpoints(curr_bpt); 2826 UnlinkCodeBreakpoints(curr_loc);
2593 delete curr_bpt; 2827 delete curr_loc;
2828 }
2594 2829
2595 // Remove references from the current debugger pause event. 2830 prev_loc = curr_loc;
2596 if (pause_event_ != NULL && 2831 curr_loc = curr_loc->next();
2597 pause_event_->type() == DebuggerEvent::kBreakpointReached &&
2598 pause_event_->breakpoint() == curr_bpt) {
2599 pause_event_->set_breakpoint(NULL);
2600 }
2601 return;
2602 }
2603 prev_bpt = curr_bpt;
2604 curr_bpt = curr_bpt->next();
2605 } 2832 }
2606 // bpt is not a registered breakpoint, nothing to do. 2833 // bpt is not a registered breakpoint, nothing to do.
2607 } 2834 }
2608 2835
2609 2836
2610 // Turn code breakpoints associated with the given source breakpoint into 2837 // Turn code breakpoints associated with the given source breakpoint into
2611 // internal breakpoints. They will later be deleted when control 2838 // internal breakpoints. They will later be deleted when control
2612 // returns from the user-defined breakpoint callback. Also, disable the 2839 // returns from the user-defined breakpoint callback. Also, disable the
2613 // breakpoint so it no longer fires if it should be hit before it gets 2840 // breakpoint so it no longer fires if it should be hit before it gets
2614 // deleted. 2841 // deleted.
2615 void Debugger::UnlinkCodeBreakpoints(SourceBreakpoint* src_bpt) { 2842 void Debugger::UnlinkCodeBreakpoints(BreakpointLocation* bpt_location) {
2616 ASSERT(src_bpt != NULL); 2843 ASSERT(bpt_location != NULL);
2617 CodeBreakpoint* curr_bpt = code_breakpoints_; 2844 CodeBreakpoint* curr_bpt = code_breakpoints_;
2618 while (curr_bpt != NULL) { 2845 while (curr_bpt != NULL) {
2619 if (curr_bpt->src_bpt() == src_bpt) { 2846 if (curr_bpt->bpt_location() == bpt_location) {
2620 curr_bpt->Disable(); 2847 curr_bpt->Disable();
2621 curr_bpt->set_src_bpt(NULL); 2848 curr_bpt->set_bpt_location(NULL);
2622 } 2849 }
2623 curr_bpt = curr_bpt->next(); 2850 curr_bpt = curr_bpt->next();
2624 } 2851 }
2625 } 2852 }
2626 2853
2627 2854
2628 // Remove and delete internal breakpoints, i.e. breakpoints that 2855 // Remove and delete internal breakpoints, i.e. breakpoints that
2629 // are not associated with a source breakpoint. 2856 // are not associated with a source breakpoint.
2630 void Debugger::RemoveInternalBreakpoints() { 2857 void Debugger::RemoveInternalBreakpoints() {
2631 CodeBreakpoint* prev_bpt = NULL; 2858 CodeBreakpoint* prev_bpt = NULL;
2632 CodeBreakpoint* curr_bpt = code_breakpoints_; 2859 CodeBreakpoint* curr_bpt = code_breakpoints_;
2633 while (curr_bpt != NULL) { 2860 while (curr_bpt != NULL) {
2634 if (curr_bpt->src_bpt() == NULL) { 2861 if (curr_bpt->bpt_location() == NULL) {
2635 if (prev_bpt == NULL) { 2862 if (prev_bpt == NULL) {
2636 code_breakpoints_ = code_breakpoints_->next(); 2863 code_breakpoints_ = code_breakpoints_->next();
2637 } else { 2864 } else {
2638 prev_bpt->set_next(curr_bpt->next()); 2865 prev_bpt->set_next(curr_bpt->next());
2639 } 2866 }
2640 CodeBreakpoint* temp_bpt = curr_bpt; 2867 CodeBreakpoint* temp_bpt = curr_bpt;
2641 curr_bpt = curr_bpt->next(); 2868 curr_bpt = curr_bpt->next();
2642 temp_bpt->Disable(); 2869 temp_bpt->Disable();
2643 delete temp_bpt; 2870 delete temp_bpt;
2644 } else { 2871 } else {
2645 prev_bpt = curr_bpt; 2872 prev_bpt = curr_bpt;
2646 curr_bpt = curr_bpt->next(); 2873 curr_bpt = curr_bpt->next();
2647 } 2874 }
2648 } 2875 }
2649 } 2876 }
2650 2877
2651 2878
2652 SourceBreakpoint* Debugger::GetSourceBreakpoint(const Script& script, 2879 BreakpointLocation* Debugger::GetBreakpointLocation(const Script& script,
2653 intptr_t token_pos) { 2880 intptr_t token_pos) {
hausner 2015/05/21 22:46:23 indentation
2654 SourceBreakpoint* bpt = src_breakpoints_; 2881 BreakpointLocation* bpt = breakpoint_locations_;
2655 while (bpt != NULL) { 2882 while (bpt != NULL) {
2656 if ((bpt->script_ == script.raw()) && (bpt->token_pos_ == token_pos)) { 2883 if ((bpt->script_ == script.raw()) && (bpt->token_pos_ == token_pos)) {
2657 return bpt; 2884 return bpt;
2658 } 2885 }
2659 bpt = bpt->next(); 2886 bpt = bpt->next();
2660 } 2887 }
2661 return NULL; 2888 return NULL;
2662 } 2889 }
2663 2890
2664 2891
2665 SourceBreakpoint* Debugger::GetBreakpointById(intptr_t id) { 2892 Breakpoint* Debugger::GetBreakpointById(intptr_t id) {
2666 SourceBreakpoint* bpt = src_breakpoints_; 2893 BreakpointLocation* loc = breakpoint_locations_;
2667 while (bpt != NULL) { 2894 while (loc != NULL) {
2668 if (bpt->id() == id) { 2895 Breakpoint* bpt = loc->breakpoints();
2669 return bpt; 2896 while (bpt != NULL) {
2897 if (bpt->id() == id) {
2898 return bpt;
2899 }
2900 bpt = bpt->next();
2670 } 2901 }
2671 bpt = bpt->next(); 2902 loc = loc->next();
2672 } 2903 }
2673 return NULL; 2904 return NULL;
2674 } 2905 }
2675 2906
2676 2907
2677 SourceBreakpoint* Debugger::GetLatentBreakpoint(const String& url, 2908 BreakpointLocation* Debugger::GetLatentBreakpoint(const String& url,
2678 intptr_t line) { 2909 intptr_t line) {
2679 SourceBreakpoint* bpt = latent_breakpoints_; 2910 BreakpointLocation* bpt = latent_locations_;
2680 String& bpt_url = String::Handle(isolate_); 2911 String& bpt_url = String::Handle(isolate_);
2681 while (bpt != NULL) { 2912 while (bpt != NULL) {
2682 bpt_url = bpt->url(); 2913 bpt_url = bpt->url();
2683 if (bpt_url.Equals(url) && (bpt->LineNumber() == line)) { 2914 if (bpt_url.Equals(url) && (bpt->LineNumber() == line)) {
2684 return bpt; 2915 return bpt;
2685 } 2916 }
2686 bpt = bpt->next(); 2917 bpt = bpt->next();
2687 } 2918 }
2688 // No breakpint for this url and line requested. Allocate new one. 2919 // No breakpint for this url and line requested. Allocate new one.
2689 bpt = new SourceBreakpoint(nextId(), url, line); 2920 bpt = new BreakpointLocation(url, line);
2690 bpt->set_next(latent_breakpoints_); 2921 bpt->set_next(latent_locations_);
2691 latent_breakpoints_ = bpt; 2922 latent_locations_ = bpt;
2692 return bpt; 2923 return bpt;
2693 } 2924 }
2694 2925
2695 2926
2696 void Debugger::RegisterSourceBreakpoint(SourceBreakpoint* bpt) { 2927 void Debugger::RegisterBreakpointLocation(BreakpointLocation* bpt) {
2697 ASSERT(bpt->next() == NULL); 2928 ASSERT(bpt->next() == NULL);
2698 bpt->set_next(src_breakpoints_); 2929 bpt->set_next(breakpoint_locations_);
2699 src_breakpoints_ = bpt; 2930 breakpoint_locations_ = bpt;
2700 } 2931 }
2701 2932
2702 2933
2703 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 2934 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
2704 ASSERT(bpt->next() == NULL); 2935 ASSERT(bpt->next() == NULL);
2705 bpt->set_next(code_breakpoints_); 2936 bpt->set_next(code_breakpoints_);
2706 code_breakpoints_ = bpt; 2937 code_breakpoints_ = bpt;
2707 } 2938 }
2708 2939
2709 } // namespace dart 2940 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698