Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/debugger.h" | 5 #include "vm/debugger.h" |
| 6 | 6 |
| 7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
| 8 | 8 |
| 9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
| 10 #include "vm/code_patcher.h" | 10 #include "vm/code_patcher.h" |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |