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

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

Issue 808643004: Support breakpoints in deferred libraries (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years 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 | Annotate | Revision Log
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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 return obj_id < objs_->Length(); 47 return obj_id < objs_->Length();
48 } 48 }
49 49
50 private: 50 private:
51 GrowableObjectArray* objs_; 51 GrowableObjectArray* objs_;
52 52
53 DISALLOW_COPY_AND_ASSIGN(RemoteObjectCache); 53 DISALLOW_COPY_AND_ASSIGN(RemoteObjectCache);
54 }; 54 };
55 55
56 56
57 // Create an unresolved breakpoint in given token range and script.
57 SourceBreakpoint::SourceBreakpoint(intptr_t id, 58 SourceBreakpoint::SourceBreakpoint(intptr_t id,
58 const Script& script, 59 const Script& script,
59 intptr_t token_pos, 60 intptr_t token_pos,
60 intptr_t end_token_pos) 61 intptr_t end_token_pos)
61 : id_(id), 62 : id_(id),
62 script_(script.raw()), 63 script_(script.raw()),
64 url_(script.url()),
63 token_pos_(token_pos), 65 token_pos_(token_pos),
64 end_token_pos_(end_token_pos), 66 end_token_pos_(end_token_pos),
65 is_resolved_(false), 67 is_resolved_(false),
66 is_enabled_(false), 68 is_enabled_(false),
67 is_one_shot_(false), 69 is_one_shot_(false),
68 next_(NULL), 70 next_(NULL),
69 function_(Function::null()), 71 function_(Function::null()),
70 line_number_(-1) { 72 line_number_(-1) {
71 ASSERT(id_ > 0); 73 ASSERT(id_ > 0);
72 ASSERT(!script.IsNull()); 74 ASSERT(!script.IsNull());
73 ASSERT(token_pos_ >= 0); 75 ASSERT(token_pos_ >= 0);
74 } 76 }
75 77
78 // Create a latent breakpoint at given url and line number.
79 SourceBreakpoint::SourceBreakpoint(intptr_t id,
80 const String& url,
81 intptr_t line_number)
82 : id_(id),
83 script_(Script::null()),
84 url_(url.raw()),
85 token_pos_(-1),
86 end_token_pos_(-1),
87 is_resolved_(false),
88 is_enabled_(false),
89 is_one_shot_(false),
90 next_(NULL),
91 function_(Function::null()),
92 line_number_(line_number) {
93 ASSERT(id >= 0);
94 ASSERT(line_number_ >= 0);
95 }
76 96
77 void SourceBreakpoint::Enable() { 97 void SourceBreakpoint::Enable() {
78 is_enabled_ = true; 98 is_enabled_ = true;
79 Isolate::Current()->debugger()->SyncBreakpoint(this); 99 Isolate::Current()->debugger()->SyncBreakpoint(this);
80 } 100 }
81 101
82 102
83 void SourceBreakpoint::Disable() { 103 void SourceBreakpoint::Disable() {
84 is_enabled_ = false; 104 is_enabled_ = false;
85 Isolate::Current()->debugger()->SyncBreakpoint(this); 105 Isolate::Current()->debugger()->SyncBreakpoint(this);
86 } 106 }
87 107
88 108
89 void SourceBreakpoint::SetResolved(const Function& func, intptr_t token_pos) { 109 void SourceBreakpoint::SetResolved(const Function& func, intptr_t token_pos) {
110 ASSERT(!IsLatent());
90 ASSERT(func.script() == script_); 111 ASSERT(func.script() == script_);
91 ASSERT((func.token_pos() <= token_pos) && 112 ASSERT((func.token_pos() <= token_pos) &&
92 (token_pos <= func.end_token_pos())); 113 (token_pos <= func.end_token_pos()));
93 function_ = func.raw(); 114 function_ = func.raw();
94 token_pos_ = token_pos; 115 token_pos_ = token_pos;
95 end_token_pos_ = token_pos; 116 end_token_pos_ = token_pos;
96 line_number_ = -1; // Recalcualte lazily. 117 line_number_ = -1; // Recalcualte lazily.
97 is_resolved_ = true; 118 is_resolved_ = true;
98 } 119 }
99 120
100 121
101 // TODO(hausner): Get rid of library parameter. A source breakpoint location 122 // TODO(hausner): Get rid of library parameter. A source breakpoint location
102 // does not imply a library, since the same source code can be included 123 // does not imply a library, since the same source code can be included
103 // in more than one library, e.g. the text location of mixin functions. 124 // in more than one library, e.g. the text location of mixin functions.
104 void SourceBreakpoint::GetCodeLocation(Library* lib, 125 void SourceBreakpoint::GetCodeLocation(Library* lib,
105 Script* script, 126 Script* script,
106 intptr_t* pos) { 127 intptr_t* pos) {
107 *script = this->script(); 128 if (IsLatent()) {
108 *pos = token_pos_; 129 *lib = Library::null();
109 if (IsResolved()) { 130 *script = Script::null();
110 const Function& func = Function::Handle(function_); 131 *pos = -1;
111 ASSERT(!func.IsNull());
112 const Class& cls = Class::Handle(func.origin());
113 *lib = cls.library();
114 } else { 132 } else {
115 *lib = Library::null(); 133 *script = this->script();
134 *pos = token_pos_;
135 if (IsResolved()) {
136 const Function& func = Function::Handle(function_);
137 ASSERT(!func.IsNull());
138 const Class& cls = Class::Handle(func.origin());
139 *lib = cls.library();
140 } else {
141 *lib = Library::null();
142 }
116 } 143 }
117 } 144 }
118 145
119 146
120 RawString* SourceBreakpoint::SourceUrl() {
121 return Script::Handle(script()).url();
122 }
123
124
125 intptr_t SourceBreakpoint::LineNumber() { 147 intptr_t SourceBreakpoint::LineNumber() {
148 // Latent breakpoints must have a requested line number >= 0.
149 ASSERT(!IsLatent() || line_number_ >= 0);
126 // Compute line number lazily since it causes scanning of the script. 150 // Compute line number lazily since it causes scanning of the script.
127 if (line_number_ < 0) { 151 if (line_number_ < 0) {
128 const Script& script = Script::Handle(this->script()); 152 const Script& script = Script::Handle(this->script());
129 script.GetTokenLocation(token_pos_, &line_number_, NULL); 153 script.GetTokenLocation(token_pos_, &line_number_, NULL);
130 } 154 }
131 return line_number_; 155 return line_number_;
132 } 156 }
133 157
134 158
135 void SourceBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { 159 void SourceBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
136 visitor->VisitPointer(reinterpret_cast<RawObject**>(&script_)); 160 visitor->VisitPointer(reinterpret_cast<RawObject**>(&script_));
161 visitor->VisitPointer(reinterpret_cast<RawObject**>(&url_));
137 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_)); 162 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_));
138 } 163 }
139 164
140 165
141 void SourceBreakpoint::PrintJSON(JSONStream* stream) { 166 void SourceBreakpoint::PrintJSON(JSONStream* stream) {
142 Isolate* isolate = Isolate::Current(); 167 Isolate* isolate = Isolate::Current();
143 168
144 JSONObject jsobj(stream); 169 JSONObject jsobj(stream);
145 jsobj.AddProperty("type", "Breakpoint"); 170 jsobj.AddProperty("type", "Breakpoint");
146 171
(...skipping 843 matching lines...) Expand 10 before | Expand all | Expand 10 after
990 ASSERT(IsValidId(obj_id)); 1015 ASSERT(IsValidId(obj_id));
991 return objs_->At(obj_id); 1016 return objs_->At(obj_id);
992 } 1017 }
993 1018
994 1019
995 Debugger::Debugger() 1020 Debugger::Debugger()
996 : isolate_(NULL), 1021 : isolate_(NULL),
997 isolate_id_(ILLEGAL_ISOLATE_ID), 1022 isolate_id_(ILLEGAL_ISOLATE_ID),
998 initialized_(false), 1023 initialized_(false),
999 next_id_(1), 1024 next_id_(1),
1025 latent_breakpoints_(NULL),
1000 src_breakpoints_(NULL), 1026 src_breakpoints_(NULL),
1001 code_breakpoints_(NULL), 1027 code_breakpoints_(NULL),
1002 resume_action_(kContinue), 1028 resume_action_(kContinue),
1003 ignore_breakpoints_(false), 1029 ignore_breakpoints_(false),
1004 pause_event_(NULL), 1030 pause_event_(NULL),
1005 obj_cache_(NULL), 1031 obj_cache_(NULL),
1006 stack_trace_(NULL), 1032 stack_trace_(NULL),
1007 stepping_fp_(0), 1033 stepping_fp_(0),
1008 exc_pause_info_(kNoPauseOnExceptions) { 1034 exc_pause_info_(kNoPauseOnExceptions) {
1009 } 1035 }
1010 1036
1011 1037
1012 Debugger::~Debugger() { 1038 Debugger::~Debugger() {
1013 isolate_id_ = ILLEGAL_ISOLATE_ID; 1039 isolate_id_ = ILLEGAL_ISOLATE_ID;
1014 ASSERT(!IsPaused()); 1040 ASSERT(!IsPaused());
1041 ASSERT(latent_breakpoints_ == NULL);
1015 ASSERT(src_breakpoints_ == NULL); 1042 ASSERT(src_breakpoints_ == NULL);
1016 ASSERT(code_breakpoints_ == NULL); 1043 ASSERT(code_breakpoints_ == NULL);
1017 ASSERT(stack_trace_ == NULL); 1044 ASSERT(stack_trace_ == NULL);
1018 ASSERT(obj_cache_ == NULL); 1045 ASSERT(obj_cache_ == NULL);
1019 } 1046 }
1020 1047
1021 1048
1022 void Debugger::Shutdown() { 1049 void Debugger::Shutdown() {
1023 while (src_breakpoints_ != NULL) { 1050 while (src_breakpoints_ != NULL) {
1024 SourceBreakpoint* bpt = src_breakpoints_; 1051 SourceBreakpoint* bpt = src_breakpoints_;
1025 src_breakpoints_ = src_breakpoints_->next(); 1052 src_breakpoints_ = src_breakpoints_->next();
1026 delete bpt; 1053 delete bpt;
1027 } 1054 }
1055 while (latent_breakpoints_ != NULL) {
1056 SourceBreakpoint* bpt = latent_breakpoints_;
1057 latent_breakpoints_ = latent_breakpoints_->next();
1058 delete bpt;
1059 }
1028 while (code_breakpoints_ != NULL) { 1060 while (code_breakpoints_ != NULL) {
1029 CodeBreakpoint* bpt = code_breakpoints_; 1061 CodeBreakpoint* bpt = code_breakpoints_;
1030 code_breakpoints_ = code_breakpoints_->next(); 1062 code_breakpoints_ = code_breakpoints_->next();
1031 bpt->Disable(); 1063 bpt->Disable();
1032 delete bpt; 1064 delete bpt;
1033 } 1065 }
1034 // Signal isolate shutdown event. 1066 // Signal isolate shutdown event.
1035 SignalIsolateEvent(DebuggerEvent::kIsolateShutdown); 1067 SignalIsolateEvent(DebuggerEvent::kIsolateShutdown);
1036 } 1068 }
1037 1069
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after
1507 GrowableObjectArray& closures = GrowableObjectArray::Handle(isolate_); 1539 GrowableObjectArray& closures = GrowableObjectArray::Handle(isolate_);
1508 Function& function = Function::Handle(isolate_); 1540 Function& function = Function::Handle(isolate_);
1509 1541
1510 const ClassTable& class_table = *isolate_->class_table(); 1542 const ClassTable& class_table = *isolate_->class_table();
1511 const intptr_t num_classes = class_table.NumCids(); 1543 const intptr_t num_classes = class_table.NumCids();
1512 for (intptr_t i = 1; i < num_classes; i++) { 1544 for (intptr_t i = 1; i < num_classes; i++) {
1513 if (class_table.HasValidClassAt(i)) { 1545 if (class_table.HasValidClassAt(i)) {
1514 cls = class_table.At(i); 1546 cls = class_table.At(i);
1515 // If the class is not finalized, e.g. if it hasn't been parsed 1547 // If the class is not finalized, e.g. if it hasn't been parsed
1516 // yet entirely, we can ignore it. If it contains a function with 1548 // yet entirely, we can ignore it. If it contains a function with
1517 // a latent breakpoint, we will detect it if and when the function 1549 // an unresolved breakpoint, we will detect it if and when the
1518 // gets compiled. 1550 // function gets compiled.
1519 if (!cls.is_finalized()) { 1551 if (!cls.is_finalized()) {
1520 continue; 1552 continue;
1521 } 1553 }
1522 // Note: we need to check the functions of this class even if 1554 // Note: we need to check the functions of this class even if
1523 // the class is defined in a differenct 'script'. There could 1555 // the class is defined in a differenct 'script'. There could
1524 // be mixin functions from the given script in this class. 1556 // be mixin functions from the given script in this class.
1525 functions = cls.functions(); 1557 functions = cls.functions();
1526 if (!functions.IsNull()) { 1558 if (!functions.IsNull()) {
1527 const intptr_t num_functions = functions.Length(); 1559 const intptr_t num_functions = functions.Length();
1528 for (intptr_t pos = 0; pos < num_functions; pos++) { 1560 for (intptr_t pos = 0; pos < num_functions; pos++) {
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
1776 const GrowableObjectArray& scripts = 1808 const GrowableObjectArray& scripts =
1777 GrowableObjectArray::Handle(isolate_, GrowableObjectArray::New()); 1809 GrowableObjectArray::Handle(isolate_, GrowableObjectArray::New());
1778 for (intptr_t i = 0; i < libs.Length(); i++) { 1810 for (intptr_t i = 0; i < libs.Length(); i++) {
1779 lib ^= libs.At(i); 1811 lib ^= libs.At(i);
1780 script = lib.LookupScript(script_url); 1812 script = lib.LookupScript(script_url);
1781 if (!script.IsNull()) { 1813 if (!script.IsNull()) {
1782 scripts.Add(script); 1814 scripts.Add(script);
1783 } 1815 }
1784 } 1816 }
1785 if (scripts.Length() == 0) { 1817 if (scripts.Length() == 0) {
1818 // No script found with given url. Create a latent breakpoint which
1819 // will be set if the url is loaded later.
1820 SourceBreakpoint* latent_bpt = GetLatentBreakpoint(script_url, line_number);
1786 if (FLAG_verbose_debug) { 1821 if (FLAG_verbose_debug) {
1787 OS::Print("Failed to find script with url '%s'\n", 1822 OS::Print("Set latent breakpoint in url '%s' at line %" Pd "\n",
1788 script_url.ToCString()); 1823 script_url.ToCString(),
1824 line_number);
1789 } 1825 }
1790 return NULL; 1826 return latent_bpt;
1791 } 1827 }
1792 if (scripts.Length() > 1) { 1828 if (scripts.Length() > 1) {
1793 if (FLAG_verbose_debug) { 1829 if (FLAG_verbose_debug) {
1794 OS::Print("Multiple scripts match url '%s'\n", script_url.ToCString()); 1830 OS::Print("Multiple scripts match url '%s'\n", script_url.ToCString());
1795 } 1831 }
1796 return NULL; 1832 return NULL;
1797 } 1833 }
1798 script ^= scripts.At(0); 1834 script ^= scripts.At(0);
1799 intptr_t first_token_idx, last_token_idx; 1835 intptr_t first_token_idx, last_token_idx;
1800 script.TokenRangeAtLine(line_number, &first_token_idx, &last_token_idx); 1836 script.TokenRangeAtLine(line_number, &first_token_idx, &last_token_idx);
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
2026 2062
2027 2063
2028 // static 2064 // static
2029 void Debugger::VisitObjectPointers(ObjectPointerVisitor* visitor) { 2065 void Debugger::VisitObjectPointers(ObjectPointerVisitor* visitor) {
2030 ASSERT(visitor != NULL); 2066 ASSERT(visitor != NULL);
2031 SourceBreakpoint* bpt = src_breakpoints_; 2067 SourceBreakpoint* bpt = src_breakpoints_;
2032 while (bpt != NULL) { 2068 while (bpt != NULL) {
2033 bpt->VisitObjectPointers(visitor); 2069 bpt->VisitObjectPointers(visitor);
2034 bpt = bpt->next(); 2070 bpt = bpt->next();
2035 } 2071 }
2072 bpt = latent_breakpoints_;
2073 while (bpt != NULL) {
2074 bpt->VisitObjectPointers(visitor);
2075 bpt = bpt->next();
2076 }
2036 CodeBreakpoint* cbpt = code_breakpoints_; 2077 CodeBreakpoint* cbpt = code_breakpoints_;
2037 while (cbpt != NULL) { 2078 while (cbpt != NULL) {
2038 cbpt->VisitObjectPointers(visitor); 2079 cbpt->VisitObjectPointers(visitor);
2039 cbpt = cbpt->next(); 2080 cbpt = cbpt->next();
2040 } 2081 }
2041 } 2082 }
2042 2083
2043 2084
2044 // static 2085 // static
2045 void Debugger::SetEventHandler(EventHandler* handler) { 2086 void Debugger::SetEventHandler(EventHandler* handler) {
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
2307 intptr_t bp_pos = 2348 intptr_t bp_pos =
2308 ResolveBreakpointPos(func, bpt->token_pos(), bpt->end_token_pos()); 2349 ResolveBreakpointPos(func, bpt->token_pos(), bpt->end_token_pos());
2309 if (bp_pos < 0) { 2350 if (bp_pos < 0) {
2310 if (FLAG_verbose_debug) { 2351 if (FLAG_verbose_debug) {
2311 OS::Print("Failed resolving breakpoint for function '%s'\n", 2352 OS::Print("Failed resolving breakpoint for function '%s'\n",
2312 String::Handle(func.name()).ToCString()); 2353 String::Handle(func.name()).ToCString());
2313 } 2354 }
2314 continue; 2355 continue;
2315 } 2356 }
2316 intptr_t requested_pos = bpt->token_pos(); 2357 intptr_t requested_pos = bpt->token_pos();
2358 intptr_t requested_end_pos = bpt->end_token_pos();
2317 bpt->SetResolved(func, bp_pos); 2359 bpt->SetResolved(func, bp_pos);
2318 if (FLAG_verbose_debug) { 2360 if (FLAG_verbose_debug) {
2319 OS::Print("Resolved BP %" Pd " to pos %" Pd ", line %" Pd ", " 2361 OS::Print("Resolved BP %" Pd " to pos %" Pd ", line %" Pd ", "
2320 "function '%s' (requested pos %" Pd ")\n", 2362 "function '%s' (requested range %" Pd "-%" Pd ")\n",
2321 bpt->id(), 2363 bpt->id(),
2322 bpt->token_pos(), 2364 bpt->token_pos(),
2323 bpt->LineNumber(), 2365 bpt->LineNumber(),
2324 func.ToFullyQualifiedCString(), 2366 func.ToFullyQualifiedCString(),
2325 requested_pos); 2367 requested_pos,
2368 requested_end_pos);
2326 } 2369 }
2327 SignalBpResolved(bpt); 2370 SignalBpResolved(bpt);
2328 } 2371 }
2329 ASSERT(bpt->IsResolved()); 2372 ASSERT(bpt->IsResolved());
2330 if (FLAG_verbose_debug) { 2373 if (FLAG_verbose_debug) {
2331 OS::Print("Setting breakpoint %" Pd " at line %" Pd " for %s '%s'\n", 2374 OS::Print("Setting breakpoint %" Pd " at line %" Pd " for %s '%s'\n",
2332 bpt->id(), 2375 bpt->id(),
2333 bpt->LineNumber(), 2376 bpt->LineNumber(),
2334 func.IsClosureFunction() ? "closure" : "function", 2377 func.IsClosureFunction() ? "closure" : "function",
2335 String::Handle(func.name()).ToCString()); 2378 String::Handle(func.name()).ToCString());
2336 } 2379 }
2337 MakeCodeBreakpointAt(func, bpt); 2380 MakeCodeBreakpointAt(func, bpt);
2338 } 2381 }
2339 } 2382 }
2340 } 2383 }
2341 2384
2342 2385
2386 void Debugger::NotifyDoneLoading() {
2387 if (latent_breakpoints_ == NULL) {
2388 // Common, fast path.
2389 return;
2390 }
2391 Library& lib = Library::Handle(isolate_);
2392 Script& script = Script::Handle(isolate_);
2393 String& url = String::Handle(isolate_);
2394 SourceBreakpoint* bpt = latent_breakpoints_;
2395 SourceBreakpoint* prev_bpt = NULL;
2396 const GrowableObjectArray& libs =
2397 GrowableObjectArray::Handle(isolate_->object_store()->libraries());
2398 while (bpt != NULL) {
2399 url = bpt->url();
2400 for (intptr_t i = 0; i < libs.Length(); i++) {
2401 lib ^= libs.At(i);
2402 script = lib.LookupScript(url);
2403 if (!script.IsNull()) {
2404 // Found a script with matching url for this latent breakpoint.
2405 // Unlink the latent breakpoint from the list.
2406 SourceBreakpoint* matched_bpt = bpt;
2407 bpt = bpt->next();
2408 if (prev_bpt == NULL) {
2409 latent_breakpoints_ = bpt;
2410 } else {
2411 prev_bpt->set_next(bpt);
2412 }
2413 // Now find the token range at the requested line and make a
2414 // new unresolved source breakpoint.
2415 intptr_t line_number = matched_bpt->LineNumber();
2416 ASSERT(line_number >= 0);
2417 intptr_t first_token_pos, last_token_pos;
2418 script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos);
2419 if ((first_token_pos < 0) ||
2420 (last_token_pos < 0)) {
2421 // Script does not contain the given line number or there are no
2422 // tokens on the line. Drop the breakpoint silently.
2423 if (FLAG_verbose_debug) {
2424 OS::Print("No code found at line %" Pd ": "
2425 "dropping latent breakpoint %" Pd " in '%s'\n",
2426 line_number,
2427 matched_bpt->id(),
2428 url.ToCString());
2429 }
2430 delete matched_bpt;
2431 } else {
2432 // We don't expect to already have a breakpoint for this location.
2433 // If there is one, assert in debug build but silently drop
2434 // the latent breakpoint in release build.
2435 SourceBreakpoint* existing_bpt =
2436 GetSourceBreakpoint(script, first_token_pos);
2437 ASSERT(existing_bpt == NULL);
2438 if (existing_bpt == NULL) {
2439 // Create and register a new source breakpoint for the
2440 // latent breakpoint.
2441 SourceBreakpoint* unresolved_bpt =
2442 new SourceBreakpoint(matched_bpt->id(),
2443 script,
2444 first_token_pos,
2445 last_token_pos);
2446 RegisterSourceBreakpoint(unresolved_bpt);
2447 unresolved_bpt->Enable();
2448 if (FLAG_verbose_debug) {
2449 OS::Print("Converted latent breakpoint "
2450 "%" Pd " in '%s' at line %" Pd "\n",
2451 matched_bpt->id(),
2452 url.ToCString(),
2453 line_number);
2454 }
2455 }
2456 delete matched_bpt;
2457 // Break out of the iteration over loaded libraries. If the
2458 // same url has been loaded into more than one library, we
2459 // only set a breakpoint in the first one.
2460 // TODO(hausner): There is one possible pitfall here.
2461 // If the user sets a latent breakpoint using a partial url that
2462 // ends up matching more than one script, the breakpoint might
2463 // get set in the wrong script.
2464 // It would be better if we could warn the user if multiple
2465 // scripts are matching.
2466 break;
2467 }
2468 }
2469 }
2470 }
2471 }
2472
2473
2343 // TODO(hausner): Could potentially make this faster by checking 2474 // TODO(hausner): Could potentially make this faster by checking
2344 // whether the call target at pc is a debugger stub. 2475 // whether the call target at pc is a debugger stub.
2345 bool Debugger::HasActiveBreakpoint(uword pc) { 2476 bool Debugger::HasActiveBreakpoint(uword pc) {
2346 CodeBreakpoint* bpt = GetCodeBreakpoint(pc); 2477 CodeBreakpoint* bpt = GetCodeBreakpoint(pc);
2347 return (bpt != NULL) && (bpt->IsEnabled()); 2478 return (bpt != NULL) && (bpt->IsEnabled());
2348 } 2479 }
2349 2480
2350 2481
2351 CodeBreakpoint* Debugger::GetCodeBreakpoint(uword breakpoint_address) { 2482 CodeBreakpoint* Debugger::GetCodeBreakpoint(uword breakpoint_address) {
2352 CodeBreakpoint* bpt = code_breakpoints_; 2483 CodeBreakpoint* bpt = code_breakpoints_;
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
2463 while (bpt != NULL) { 2594 while (bpt != NULL) {
2464 if (bpt->id() == id) { 2595 if (bpt->id() == id) {
2465 return bpt; 2596 return bpt;
2466 } 2597 }
2467 bpt = bpt->next(); 2598 bpt = bpt->next();
2468 } 2599 }
2469 return NULL; 2600 return NULL;
2470 } 2601 }
2471 2602
2472 2603
2604 SourceBreakpoint* Debugger::GetLatentBreakpoint(const String& url,
2605 intptr_t line) {
2606 SourceBreakpoint* bpt = latent_breakpoints_;
2607 String& bpt_url = String::Handle(isolate_);
2608 while (bpt != NULL) {
2609 bpt_url = bpt->url();
2610 if (bpt_url.Equals(url) && (bpt->LineNumber() == line)) {
2611 return bpt;
2612 }
2613 bpt = bpt->next();
2614 }
2615 // No breakpint for this url and line requested. Allocate new one.
2616 bpt = new SourceBreakpoint(nextId(), url, line);
2617 bpt->set_next(latent_breakpoints_);
2618 latent_breakpoints_ = bpt;
2619 return bpt;
2620 }
2621
2622
2473 void Debugger::RegisterSourceBreakpoint(SourceBreakpoint* bpt) { 2623 void Debugger::RegisterSourceBreakpoint(SourceBreakpoint* bpt) {
2474 ASSERT(bpt->next() == NULL); 2624 ASSERT(bpt->next() == NULL);
2475 bpt->set_next(src_breakpoints_); 2625 bpt->set_next(src_breakpoints_);
2476 src_breakpoints_ = bpt; 2626 src_breakpoints_ = bpt;
2477 } 2627 }
2478 2628
2479 2629
2480 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 2630 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
2481 ASSERT(bpt->next() == NULL); 2631 ASSERT(bpt->next() == NULL);
2482 bpt->set_next(code_breakpoints_); 2632 bpt->set_next(code_breakpoints_);
2483 code_breakpoints_ = bpt; 2633 code_breakpoints_ = bpt;
2484 } 2634 }
2485 2635
2486 } // namespace dart 2636 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698