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 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 uword fp, | 172 uword fp, |
173 uword sp, | 173 uword sp, |
174 const Code& code, | 174 const Code& code, |
175 const Array& deopt_frame, | 175 const Array& deopt_frame, |
176 intptr_t deopt_frame_offset) | 176 intptr_t deopt_frame_offset) |
177 : pc_(pc), fp_(fp), sp_(sp), | 177 : pc_(pc), fp_(fp), sp_(sp), |
178 ctx_(Context::ZoneHandle()), | 178 ctx_(Context::ZoneHandle()), |
179 code_(Code::ZoneHandle(code.raw())), | 179 code_(Code::ZoneHandle(code.raw())), |
180 function_(Function::ZoneHandle(code.function())), | 180 function_(Function::ZoneHandle(code.function())), |
181 token_pos_(-1), | 181 token_pos_(-1), |
182 pc_desc_index_(-1), | 182 desc_rec_(NULL), |
183 line_number_(-1), | 183 line_number_(-1), |
184 column_number_(-1), | 184 column_number_(-1), |
185 context_level_(-1), | 185 context_level_(-1), |
186 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())), | 186 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())), |
187 deopt_frame_offset_(deopt_frame_offset), | 187 deopt_frame_offset_(deopt_frame_offset), |
188 vars_initialized_(false), | 188 vars_initialized_(false), |
189 var_descriptors_(LocalVarDescriptors::ZoneHandle()), | 189 var_descriptors_(LocalVarDescriptors::ZoneHandle()), |
190 desc_indices_(8), | 190 desc_indices_(8), |
191 pc_desc_(PcDescriptors::ZoneHandle()) { | 191 pc_desc_(PcDescriptors::ZoneHandle()) { |
192 } | 192 } |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 ASSERT(!pc_desc_.IsNull()); | 332 ASSERT(!pc_desc_.IsNull()); |
333 } | 333 } |
334 } | 334 } |
335 | 335 |
336 | 336 |
337 // Compute token_pos_ and pc_desc_index_. | 337 // Compute token_pos_ and pc_desc_index_. |
338 intptr_t ActivationFrame::TokenPos() { | 338 intptr_t ActivationFrame::TokenPos() { |
339 if (token_pos_ < 0) { | 339 if (token_pos_ < 0) { |
340 token_pos_ = Scanner::kNoSourcePos; | 340 token_pos_ = Scanner::kNoSourcePos; |
341 GetPcDescriptors(); | 341 GetPcDescriptors(); |
342 for (intptr_t i = 0; i < pc_desc_.Length(); i++) { | 342 PcDescriptors::Iterator iter(pc_desc_); |
343 if (pc_desc_.PC(i) == pc_) { | 343 while (iter.HasNext()) { |
344 pc_desc_index_ = i; | 344 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
345 token_pos_ = pc_desc_.TokenPos(i); | 345 if (rec.pc == pc_) { |
| 346 desc_rec_ = &rec; |
| 347 token_pos_ = rec.token_pos; |
346 break; | 348 break; |
347 } | 349 } |
348 } | 350 } |
349 } | 351 } |
350 return token_pos_; | 352 return token_pos_; |
351 } | 353 } |
352 | 354 |
353 | 355 |
354 intptr_t ActivationFrame::PcDescIndex() { | |
355 if (pc_desc_index_ < 0) { | |
356 TokenPos(); // Sets pc_desc_index_ as a side effect. | |
357 } | |
358 return pc_desc_index_; | |
359 } | |
360 | |
361 | |
362 intptr_t ActivationFrame::TryIndex() { | 356 intptr_t ActivationFrame::TryIndex() { |
363 intptr_t desc_index = PcDescIndex(); | 357 if (desc_rec_ == NULL) { |
364 if (desc_index < 0) { | |
365 return -1; | 358 return -1; |
366 } else { | 359 } else { |
367 return pc_desc_.TryIndex(desc_index); | 360 return desc_rec_->try_index; |
368 } | 361 } |
369 } | 362 } |
370 | 363 |
371 | 364 |
372 intptr_t ActivationFrame::LineNumber() { | 365 intptr_t ActivationFrame::LineNumber() { |
373 // Compute line number lazily since it causes scanning of the script. | 366 // Compute line number lazily since it causes scanning of the script. |
374 if ((line_number_ < 0) && (TokenPos() >= 0)) { | 367 if ((line_number_ < 0) && (TokenPos() >= 0)) { |
375 const Script& script = Script::Handle(SourceScript()); | 368 const Script& script = Script::Handle(SourceScript()); |
376 script.GetTokenLocation(TokenPos(), &line_number_, NULL); | 369 script.GetTokenLocation(TokenPos(), &line_number_, NULL); |
377 } | 370 } |
(...skipping 26 matching lines...) Expand all Loading... |
404 bool ActivationFrame::IsDebuggable() const { | 397 bool ActivationFrame::IsDebuggable() const { |
405 return Debugger::IsDebuggable(function()); | 398 return Debugger::IsDebuggable(function()); |
406 } | 399 } |
407 | 400 |
408 | 401 |
409 // Calculate the context level at the current token index of the frame. | 402 // Calculate the context level at the current token index of the frame. |
410 intptr_t ActivationFrame::ContextLevel() { | 403 intptr_t ActivationFrame::ContextLevel() { |
411 if (context_level_ < 0 && !ctx_.IsNull()) { | 404 if (context_level_ < 0 && !ctx_.IsNull()) { |
412 ASSERT(!code_.is_optimized()); | 405 ASSERT(!code_.is_optimized()); |
413 context_level_ = 0; | 406 context_level_ = 0; |
414 intptr_t pc_desc_idx = PcDescIndex(); | |
415 // TODO(hausner): What to do if there is no descriptor entry | 407 // TODO(hausner): What to do if there is no descriptor entry |
416 // for the code position of the frame? For now say we are at context | 408 // for the code position of the frame? For now say we are at context |
417 // level 0. | 409 // level 0. |
418 if (pc_desc_idx < 0) { | 410 if (desc_rec_ == NULL) { |
419 return context_level_; | 411 return context_level_; |
420 } | 412 } |
421 ASSERT(!pc_desc_.IsNull()); | 413 ASSERT(!pc_desc_.IsNull()); |
422 intptr_t innermost_begin_pos = 0; | 414 intptr_t innermost_begin_pos = 0; |
423 intptr_t activation_token_pos = TokenPos(); | 415 intptr_t activation_token_pos = TokenPos(); |
424 ASSERT(activation_token_pos >= 0); | 416 ASSERT(activation_token_pos >= 0); |
425 GetVarDescriptors(); | 417 GetVarDescriptors(); |
426 intptr_t var_desc_len = var_descriptors_.Length(); | 418 intptr_t var_desc_len = var_descriptors_.Length(); |
427 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { | 419 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { |
428 RawLocalVarDescriptors::VarInfo var_info; | 420 RawLocalVarDescriptors::VarInfo var_info; |
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
902 | 894 |
903 | 895 |
904 | 896 |
905 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) { | 897 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) { |
906 if (FLAG_show_invisible_frames || frame->function().is_visible()) { | 898 if (FLAG_show_invisible_frames || frame->function().is_visible()) { |
907 trace_.Add(frame); | 899 trace_.Add(frame); |
908 } | 900 } |
909 } | 901 } |
910 | 902 |
911 | 903 |
912 static bool IsSafeDescKind(PcDescriptors::Kind kind) { | 904 static bool IsSafeDescKind(int8_t kind) { |
913 return ((kind == PcDescriptors::kIcCall) || | 905 return ((kind == RawPcDescriptors::kIcCall) || |
914 (kind == PcDescriptors::kOptStaticCall) || | 906 (kind == RawPcDescriptors::kOptStaticCall) || |
915 (kind == PcDescriptors::kUnoptStaticCall) || | 907 (kind == RawPcDescriptors::kUnoptStaticCall) || |
916 (kind == PcDescriptors::kClosureCall) || | 908 (kind == RawPcDescriptors::kClosureCall) || |
917 (kind == PcDescriptors::kRuntimeCall)); | 909 (kind == RawPcDescriptors::kRuntimeCall)); |
918 } | 910 } |
919 | 911 |
920 | 912 |
921 static bool IsSafePoint(const PcDescriptors& desc, intptr_t i) { | 913 static bool IsSafePoint(const RawPcDescriptors::PcDescriptorRec& rec) { |
922 return IsSafeDescKind(desc.DescriptorKind(i)) && | 914 return IsSafeDescKind(rec.kind()) && (rec.token_pos != Scanner::kNoSourcePos); |
923 (desc.TokenPos(i) != Scanner::kNoSourcePos); | |
924 } | 915 } |
925 | 916 |
926 | 917 |
927 CodeBreakpoint::CodeBreakpoint(const Code& code, intptr_t pc_desc_index) | 918 CodeBreakpoint::CodeBreakpoint(const Code& code, |
| 919 const RawPcDescriptors::PcDescriptorRec& rec) |
928 : code_(code.raw()), | 920 : code_(code.raw()), |
929 pc_desc_index_(pc_desc_index), | 921 token_pos_(rec.token_pos), |
930 pc_(0), | 922 pc_(rec.pc), |
931 line_number_(-1), | 923 line_number_(-1), |
932 is_enabled_(false), | 924 is_enabled_(false), |
933 src_bpt_(NULL), | 925 src_bpt_(NULL), |
934 next_(NULL) { | 926 next_(NULL), |
935 saved_value_ = 0; | 927 breakpoint_kind_(rec.kind()), |
| 928 saved_value_(0) { |
936 ASSERT(!code.IsNull()); | 929 ASSERT(!code.IsNull()); |
937 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | |
938 ASSERT(pc_desc_index < desc.Length()); | |
939 token_pos_ = desc.TokenPos(pc_desc_index); | |
940 ASSERT(token_pos_ > 0); | 930 ASSERT(token_pos_ > 0); |
941 pc_ = desc.PC(pc_desc_index); | |
942 ASSERT(pc_ != 0); | 931 ASSERT(pc_ != 0); |
943 breakpoint_kind_ = desc.DescriptorKind(pc_desc_index); | |
944 ASSERT(IsSafeDescKind(breakpoint_kind_)); | 932 ASSERT(IsSafeDescKind(breakpoint_kind_)); |
945 } | 933 } |
946 | 934 |
947 | 935 |
948 CodeBreakpoint::~CodeBreakpoint() { | 936 CodeBreakpoint::~CodeBreakpoint() { |
949 // Make sure we don't leave patched code behind. | 937 // Make sure we don't leave patched code behind. |
950 ASSERT(!IsEnabled()); | 938 ASSERT(!IsEnabled()); |
951 // Poison the data so we catch use after free errors. | 939 // Poison the data so we catch use after free errors. |
952 #ifdef DEBUG | 940 #ifdef DEBUG |
953 code_ = Code::null(); | 941 code_ = Code::null(); |
954 pc_ = 0ul; | 942 pc_ = 0ul; |
955 src_bpt_ = NULL; | 943 src_bpt_ = NULL; |
956 next_ = NULL; | 944 next_ = NULL; |
957 breakpoint_kind_ = PcDescriptors::kOther; | 945 breakpoint_kind_ = RawPcDescriptors::kOther; |
958 #endif | 946 #endif |
959 } | 947 } |
960 | 948 |
961 | 949 |
962 RawFunction* CodeBreakpoint::function() const { | 950 RawFunction* CodeBreakpoint::function() const { |
963 return Code::Handle(code_).function(); | 951 return Code::Handle(code_).function(); |
964 } | 952 } |
965 | 953 |
966 | 954 |
967 RawScript* CodeBreakpoint::SourceCode() { | 955 RawScript* CodeBreakpoint::SourceCode() { |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1187 return; | 1175 return; |
1188 } | 1176 } |
1189 } | 1177 } |
1190 // Hang on to the code object before deoptimizing, in case deoptimization | 1178 // Hang on to the code object before deoptimizing, in case deoptimization |
1191 // might cause the GC to run. | 1179 // might cause the GC to run. |
1192 Code& code = Code::Handle(isolate, target_function.unoptimized_code()); | 1180 Code& code = Code::Handle(isolate, target_function.unoptimized_code()); |
1193 ASSERT(!code.IsNull()); | 1181 ASSERT(!code.IsNull()); |
1194 DeoptimizeWorld(); | 1182 DeoptimizeWorld(); |
1195 ASSERT(!target_function.HasOptimizedCode()); | 1183 ASSERT(!target_function.HasOptimizedCode()); |
1196 PcDescriptors& desc = PcDescriptors::Handle(isolate, code.pc_descriptors()); | 1184 PcDescriptors& desc = PcDescriptors::Handle(isolate, code.pc_descriptors()); |
1197 for (intptr_t i = 0; i < desc.Length(); i++) { | 1185 PcDescriptors::Iterator iter(desc); |
1198 if (IsSafePoint(desc, i)) { | 1186 while (iter.HasNext()) { |
1199 CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(i)); | 1187 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
| 1188 if (IsSafePoint(rec)) { |
| 1189 CodeBreakpoint* bpt = GetCodeBreakpoint(rec.pc); |
1200 if (bpt != NULL) { | 1190 if (bpt != NULL) { |
1201 // There is already a breakpoint for this address. Make sure | 1191 // There is already a breakpoint for this address. Make sure |
1202 // it is enabled. | 1192 // it is enabled. |
1203 bpt->Enable(); | 1193 bpt->Enable(); |
1204 continue; | 1194 continue; |
1205 } | 1195 } |
1206 bpt = new CodeBreakpoint(code, i); | 1196 bpt = new CodeBreakpoint(code, rec); |
1207 RegisterCodeBreakpoint(bpt); | 1197 RegisterCodeBreakpoint(bpt); |
1208 bpt->Enable(); | 1198 bpt->Enable(); |
1209 } | 1199 } |
1210 } | 1200 } |
1211 } | 1201 } |
1212 | 1202 |
1213 | 1203 |
1214 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { | 1204 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { |
1215 if (event_handler_ != NULL) { | 1205 if (event_handler_ != NULL) { |
1216 DebuggerEvent event(DebuggerEvent::kBreakpointResolved); | 1206 DebuggerEvent event(DebuggerEvent::kBreakpointResolved); |
(...skipping 19 matching lines...) Expand all Loading... |
1236 new ActivationFrame(pc, frame->fp(), frame->sp(), code, | 1226 new ActivationFrame(pc, frame->fp(), frame->sp(), code, |
1237 deopt_frame, deopt_frame_offset); | 1227 deopt_frame, deopt_frame_offset); |
1238 | 1228 |
1239 // Is there a closure call at the current PC? | 1229 // Is there a closure call at the current PC? |
1240 // | 1230 // |
1241 // We can't just check the callee_activation to see if it is a | 1231 // We can't just check the callee_activation to see if it is a |
1242 // closure function, because it may not be on the stack yet. | 1232 // closure function, because it may not be on the stack yet. |
1243 bool is_closure_call = false; | 1233 bool is_closure_call = false; |
1244 const PcDescriptors& pc_desc = | 1234 const PcDescriptors& pc_desc = |
1245 PcDescriptors::Handle(isolate, code.pc_descriptors()); | 1235 PcDescriptors::Handle(isolate, code.pc_descriptors()); |
1246 | 1236 PcDescriptors::Iterator iter(pc_desc); |
1247 for (int i = 0; i < pc_desc.Length(); i++) { | 1237 while (iter.HasNext()) { |
1248 if (pc_desc.PC(i) == pc && | 1238 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
1249 pc_desc.DescriptorKind(i) == PcDescriptors::kClosureCall) { | 1239 if ((rec.pc == pc) && (rec.kind() == RawPcDescriptors::kClosureCall)) { |
1250 is_closure_call = true; | 1240 is_closure_call = true; |
1251 break; | 1241 break; |
1252 } | 1242 } |
1253 } | 1243 } |
1254 | 1244 |
1255 // Recover the context for this frame. | 1245 // Recover the context for this frame. |
1256 if (is_closure_call) { | 1246 if (is_closure_call) { |
1257 // If the callee is a closure, we should have stored the context | 1247 // If the callee is a closure, we should have stored the context |
1258 // in the current frame before making the call. | 1248 // in the current frame before making the call. |
1259 const Context& closure_call_ctx = | 1249 const Context& closure_call_ctx = |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1529 if (requested_token_pos < func.token_pos()) { | 1519 if (requested_token_pos < func.token_pos()) { |
1530 requested_token_pos = func.token_pos(); | 1520 requested_token_pos = func.token_pos(); |
1531 } | 1521 } |
1532 if (last_token_pos > func.end_token_pos()) { | 1522 if (last_token_pos > func.end_token_pos()) { |
1533 last_token_pos = func.end_token_pos(); | 1523 last_token_pos = func.end_token_pos(); |
1534 } | 1524 } |
1535 | 1525 |
1536 Code& code = Code::Handle(func.unoptimized_code()); | 1526 Code& code = Code::Handle(func.unoptimized_code()); |
1537 ASSERT(!code.IsNull()); | 1527 ASSERT(!code.IsNull()); |
1538 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 1528 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
1539 intptr_t best_fit_index = -1; | |
1540 intptr_t best_fit_pos = INT_MAX; | 1529 intptr_t best_fit_pos = INT_MAX; |
| 1530 const RawPcDescriptors::PcDescriptorRec* best_fit_rec = NULL; |
1541 uword lowest_pc = kUwordMax; | 1531 uword lowest_pc = kUwordMax; |
1542 intptr_t lowest_pc_index = -1; | 1532 const RawPcDescriptors::PcDescriptorRec* lowest_pc_rec = NULL; |
1543 | 1533 |
1544 for (intptr_t i = 0; i < desc.Length(); i++) { | 1534 const RawPcDescriptors::PcDescriptorRec* rec = NULL; |
1545 intptr_t desc_token_pos = desc.TokenPos(i); | 1535 PcDescriptors::Iterator iter(desc); |
| 1536 while (iter.HasNext()) { |
| 1537 rec = &iter.Next(); |
| 1538 intptr_t desc_token_pos = rec->token_pos; |
1546 ASSERT(desc_token_pos >= 0); | 1539 ASSERT(desc_token_pos >= 0); |
1547 if (IsSafePoint(desc, i)) { | 1540 if (IsSafePoint(*rec)) { |
1548 if ((desc_token_pos < requested_token_pos) || | 1541 if ((desc_token_pos < requested_token_pos) || |
1549 (desc_token_pos > last_token_pos)) { | 1542 (desc_token_pos > last_token_pos)) { |
1550 // This descriptor is outside the desired token range. | 1543 // This descriptor is outside the desired token range. |
1551 continue; | 1544 continue; |
1552 } | 1545 } |
1553 if (desc_token_pos < best_fit_pos) { | 1546 if (desc_token_pos < best_fit_pos) { |
1554 // So far, this descriptor has the lowest token position after | 1547 // So far, this descriptor has the lowest token position after |
1555 // the first acceptable token position. | 1548 // the first acceptable token position. |
1556 best_fit_pos = desc_token_pos; | 1549 best_fit_pos = desc_token_pos; |
1557 best_fit_index = i; | 1550 best_fit_rec = rec; |
1558 } | 1551 } |
1559 if (desc.PC(i) < lowest_pc) { | 1552 if (rec->pc < lowest_pc) { |
1560 // This descriptor so far has the lowest code address. | 1553 // This descriptor so far has the lowest code address. |
1561 lowest_pc = desc.PC(i); | 1554 lowest_pc = rec->pc; |
1562 lowest_pc_index = i; | 1555 lowest_pc_rec = rec; |
1563 } | 1556 } |
1564 } | 1557 } |
1565 } | 1558 } |
1566 if (lowest_pc_index >= 0) { | 1559 if (lowest_pc_rec != NULL) { |
1567 // We found the pc descriptor that has the lowest execution address. | 1560 // We found the pc descriptor that has the lowest execution address. |
1568 // This is the first possible breakpoint after the requested token | 1561 // This is the first possible breakpoint after the requested token |
1569 // position. We use this instead of the nearest PC descriptor | 1562 // position. We use this instead of the nearest PC descriptor |
1570 // measured in token index distance. | 1563 // measured in token index distance. |
1571 best_fit_index = lowest_pc_index; | 1564 best_fit_rec = lowest_pc_rec; |
1572 } | 1565 } |
1573 if (best_fit_index >= 0) { | 1566 if (best_fit_rec != NULL) { |
1574 return desc.TokenPos(best_fit_index); | 1567 return best_fit_rec->token_pos; |
1575 } | 1568 } |
1576 // We didn't find a safe point in the given token range. Try and find | 1569 // We didn't find a safe point in the given token range. Try and find |
1577 // a safe point in the remaining source code of the function. | 1570 // a safe point in the remaining source code of the function. |
1578 if (last_token_pos < func.end_token_pos()) { | 1571 if (last_token_pos < func.end_token_pos()) { |
1579 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos()); | 1572 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos()); |
1580 } | 1573 } |
1581 return -1; | 1574 return -1; |
1582 } | 1575 } |
1583 | 1576 |
1584 | 1577 |
1585 void Debugger::MakeCodeBreakpointAt(const Function& func, | 1578 void Debugger::MakeCodeBreakpointAt(const Function& func, |
1586 SourceBreakpoint* bpt) { | 1579 SourceBreakpoint* bpt) { |
1587 ASSERT((bpt != NULL) && bpt->IsResolved()); | 1580 ASSERT((bpt != NULL) && bpt->IsResolved()); |
1588 ASSERT(!func.HasOptimizedCode()); | 1581 ASSERT(!func.HasOptimizedCode()); |
1589 Code& code = Code::Handle(func.unoptimized_code()); | 1582 Code& code = Code::Handle(func.unoptimized_code()); |
1590 ASSERT(!code.IsNull()); | 1583 ASSERT(!code.IsNull()); |
1591 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 1584 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
1592 uword lowest_pc = kUwordMax; | 1585 uword lowest_pc = kUwordMax; |
1593 intptr_t lowest_pc_index = -1; | |
1594 // Find the safe point with the lowest compiled code address | 1586 // Find the safe point with the lowest compiled code address |
1595 // that maps to the token position of the source breakpoint. | 1587 // that maps to the token position of the source breakpoint. |
1596 for (intptr_t i = 0; i < desc.Length(); i++) { | 1588 PcDescriptors::Iterator iter(desc); |
1597 intptr_t desc_token_pos = desc.TokenPos(i); | 1589 const RawPcDescriptors::PcDescriptorRec* lowest_rec = NULL; |
1598 if ((desc_token_pos == bpt->token_pos_) && IsSafePoint(desc, i)) { | 1590 while (iter.HasNext()) { |
1599 if (desc.PC(i) < lowest_pc) { | 1591 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
1600 // This descriptor so far has the lowest code address. | 1592 intptr_t desc_token_pos = rec.token_pos; |
1601 lowest_pc = desc.PC(i); | 1593 if ((desc_token_pos == bpt->token_pos_) && IsSafePoint(rec)) { |
1602 lowest_pc_index = i; | 1594 if (rec.pc < lowest_pc) { |
| 1595 lowest_pc = rec.pc; |
| 1596 lowest_rec = &rec; |
1603 } | 1597 } |
1604 } | 1598 } |
1605 } | 1599 } |
1606 if (lowest_pc_index < 0) { | 1600 if (lowest_rec == NULL) { |
1607 return; | 1601 return; |
1608 } | 1602 } |
1609 CodeBreakpoint* code_bpt = GetCodeBreakpoint(desc.PC(lowest_pc_index)); | 1603 CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_rec->pc); |
1610 if (code_bpt == NULL) { | 1604 if (code_bpt == NULL) { |
1611 // No code breakpoint for this code exists; create one. | 1605 // No code breakpoint for this code exists; create one. |
1612 code_bpt = new CodeBreakpoint(code, lowest_pc_index); | 1606 code_bpt = new CodeBreakpoint(code, *lowest_rec); |
1613 RegisterCodeBreakpoint(code_bpt); | 1607 RegisterCodeBreakpoint(code_bpt); |
1614 } | 1608 } |
1615 code_bpt->set_src_bpt(bpt); | 1609 code_bpt->set_src_bpt(bpt); |
1616 if (bpt->IsEnabled()) { | 1610 if (bpt->IsEnabled()) { |
1617 code_bpt->Enable(); | 1611 code_bpt->Enable(); |
1618 } | 1612 } |
1619 } | 1613 } |
1620 | 1614 |
1621 | 1615 |
1622 void Debugger::FindCompiledFunctions(const Script& script, | 1616 void Debugger::FindCompiledFunctions(const Script& script, |
(...skipping 939 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2562 } | 2556 } |
2563 | 2557 |
2564 | 2558 |
2565 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 2559 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
2566 ASSERT(bpt->next() == NULL); | 2560 ASSERT(bpt->next() == NULL); |
2567 bpt->set_next(code_breakpoints_); | 2561 bpt->set_next(code_breakpoints_); |
2568 code_breakpoints_ = bpt; | 2562 code_breakpoints_ = bpt; |
2569 } | 2563 } |
2570 | 2564 |
2571 } // namespace dart | 2565 } // namespace dart |
OLD | NEW |