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

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

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

Powered by Google App Engine
This is Rietveld 408576698