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 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
173 uword fp, | 173 uword fp, |
174 uword sp, | 174 uword sp, |
175 const Code& code, | 175 const Code& code, |
176 const Array& deopt_frame, | 176 const Array& deopt_frame, |
177 intptr_t deopt_frame_offset) | 177 intptr_t deopt_frame_offset) |
178 : pc_(pc), fp_(fp), sp_(sp), | 178 : pc_(pc), fp_(fp), sp_(sp), |
179 ctx_(Context::ZoneHandle()), | 179 ctx_(Context::ZoneHandle()), |
180 code_(Code::ZoneHandle(code.raw())), | 180 code_(Code::ZoneHandle(code.raw())), |
181 function_(Function::ZoneHandle(code.function())), | 181 function_(Function::ZoneHandle(code.function())), |
182 token_pos_(-1), | 182 token_pos_(-1), |
183 pc_desc_index_(-1), | 183 desc_rec_(NULL), |
184 line_number_(-1), | 184 line_number_(-1), |
185 column_number_(-1), | 185 column_number_(-1), |
186 context_level_(-1), | 186 context_level_(-1), |
187 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())), | 187 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())), |
188 deopt_frame_offset_(deopt_frame_offset), | 188 deopt_frame_offset_(deopt_frame_offset), |
189 vars_initialized_(false), | 189 vars_initialized_(false), |
190 var_descriptors_(LocalVarDescriptors::ZoneHandle()), | 190 var_descriptors_(LocalVarDescriptors::ZoneHandle()), |
191 desc_indices_(8), | 191 desc_indices_(8), |
192 pc_desc_(PcDescriptors::ZoneHandle()) { | 192 pc_desc_(PcDescriptors::ZoneHandle()) { |
193 } | 193 } |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
352 ASSERT(!pc_desc_.IsNull()); | 352 ASSERT(!pc_desc_.IsNull()); |
353 } | 353 } |
354 } | 354 } |
355 | 355 |
356 | 356 |
357 // Compute token_pos_ and pc_desc_index_. | 357 // Compute token_pos_ and pc_desc_index_. |
358 intptr_t ActivationFrame::TokenPos() { | 358 intptr_t ActivationFrame::TokenPos() { |
359 if (token_pos_ < 0) { | 359 if (token_pos_ < 0) { |
360 token_pos_ = Scanner::kNoSourcePos; | 360 token_pos_ = Scanner::kNoSourcePos; |
361 GetPcDescriptors(); | 361 GetPcDescriptors(); |
362 for (intptr_t i = 0; i < pc_desc_.Length(); i++) { | 362 PcDescriptors::Iterator iter(pc_desc_); |
363 if (pc_desc_.PC(i) == pc_) { | 363 while (iter.HasNext()) { |
364 pc_desc_index_ = i; | 364 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
365 token_pos_ = pc_desc_.TokenPos(i); | 365 if (rec.pc == pc_) { |
366 desc_rec_ = &rec; | |
Ivan Posva
2014/07/16 08:08:49
What is the lifetime of this PcDescriptorRec? Or a
hausner
2014/07/16 16:14:08
Good call. It seems that desc_rec_ is pointing int
| |
367 token_pos_ = rec.token_pos; | |
366 break; | 368 break; |
367 } | 369 } |
368 } | 370 } |
369 } | 371 } |
370 return token_pos_; | 372 return token_pos_; |
371 } | 373 } |
372 | 374 |
373 | 375 |
374 intptr_t ActivationFrame::PcDescIndex() { | |
375 if (pc_desc_index_ < 0) { | |
376 TokenPos(); // Sets pc_desc_index_ as a side effect. | |
377 } | |
378 return pc_desc_index_; | |
379 } | |
380 | |
381 | |
382 intptr_t ActivationFrame::TryIndex() { | 376 intptr_t ActivationFrame::TryIndex() { |
383 intptr_t desc_index = PcDescIndex(); | 377 if (desc_rec_ == NULL) { |
384 if (desc_index < 0) { | |
385 return -1; | 378 return -1; |
386 } else { | 379 } else { |
387 return pc_desc_.TryIndex(desc_index); | 380 return desc_rec_->try_index; |
388 } | 381 } |
389 } | 382 } |
390 | 383 |
391 | 384 |
392 intptr_t ActivationFrame::LineNumber() { | 385 intptr_t ActivationFrame::LineNumber() { |
393 // Compute line number lazily since it causes scanning of the script. | 386 // Compute line number lazily since it causes scanning of the script. |
394 if ((line_number_ < 0) && (TokenPos() >= 0)) { | 387 if ((line_number_ < 0) && (TokenPos() >= 0)) { |
395 const Script& script = Script::Handle(SourceScript()); | 388 const Script& script = Script::Handle(SourceScript()); |
396 script.GetTokenLocation(TokenPos(), &line_number_, NULL); | 389 script.GetTokenLocation(TokenPos(), &line_number_, NULL); |
397 } | 390 } |
(...skipping 26 matching lines...) Expand all Loading... | |
424 bool ActivationFrame::IsDebuggable() const { | 417 bool ActivationFrame::IsDebuggable() const { |
425 return Debugger::IsDebuggable(function()); | 418 return Debugger::IsDebuggable(function()); |
426 } | 419 } |
427 | 420 |
428 | 421 |
429 // Calculate the context level at the current token index of the frame. | 422 // Calculate the context level at the current token index of the frame. |
430 intptr_t ActivationFrame::ContextLevel() { | 423 intptr_t ActivationFrame::ContextLevel() { |
431 if (context_level_ < 0 && !ctx_.IsNull()) { | 424 if (context_level_ < 0 && !ctx_.IsNull()) { |
432 ASSERT(!code_.is_optimized()); | 425 ASSERT(!code_.is_optimized()); |
433 context_level_ = 0; | 426 context_level_ = 0; |
434 intptr_t pc_desc_idx = PcDescIndex(); | |
435 // TODO(hausner): What to do if there is no descriptor entry | 427 // TODO(hausner): What to do if there is no descriptor entry |
436 // for the code position of the frame? For now say we are at context | 428 // for the code position of the frame? For now say we are at context |
437 // level 0. | 429 // level 0. |
438 if (pc_desc_idx < 0) { | 430 if (desc_rec_ == NULL) { |
439 return context_level_; | 431 return context_level_; |
440 } | 432 } |
441 ASSERT(!pc_desc_.IsNull()); | 433 ASSERT(!pc_desc_.IsNull()); |
442 intptr_t innermost_begin_pos = 0; | 434 intptr_t innermost_begin_pos = 0; |
443 intptr_t activation_token_pos = TokenPos(); | 435 intptr_t activation_token_pos = TokenPos(); |
444 ASSERT(activation_token_pos >= 0); | 436 ASSERT(activation_token_pos >= 0); |
445 GetVarDescriptors(); | 437 GetVarDescriptors(); |
446 intptr_t var_desc_len = var_descriptors_.Length(); | 438 intptr_t var_desc_len = var_descriptors_.Length(); |
447 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { | 439 for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) { |
448 RawLocalVarDescriptors::VarInfo var_info; | 440 RawLocalVarDescriptors::VarInfo var_info; |
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
922 | 914 |
923 | 915 |
924 | 916 |
925 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) { | 917 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) { |
926 if (FLAG_show_invisible_frames || frame->function().is_visible()) { | 918 if (FLAG_show_invisible_frames || frame->function().is_visible()) { |
927 trace_.Add(frame); | 919 trace_.Add(frame); |
928 } | 920 } |
929 } | 921 } |
930 | 922 |
931 | 923 |
932 static bool IsSafeDescKind(PcDescriptors::Kind kind) { | 924 static bool IsSafeDescKind(int8_t kind) { |
933 return ((kind == PcDescriptors::kIcCall) || | 925 return ((kind == RawPcDescriptors::kIcCall) || |
934 (kind == PcDescriptors::kOptStaticCall) || | 926 (kind == RawPcDescriptors::kOptStaticCall) || |
935 (kind == PcDescriptors::kUnoptStaticCall) || | 927 (kind == RawPcDescriptors::kUnoptStaticCall) || |
936 (kind == PcDescriptors::kClosureCall) || | 928 (kind == RawPcDescriptors::kClosureCall) || |
937 (kind == PcDescriptors::kRuntimeCall)); | 929 (kind == RawPcDescriptors::kRuntimeCall)); |
938 } | 930 } |
939 | 931 |
940 | 932 |
941 static bool IsSafePoint(const PcDescriptors& desc, intptr_t i) { | 933 static bool IsSafePoint(const RawPcDescriptors::PcDescriptorRec& rec) { |
942 return IsSafeDescKind(desc.DescriptorKind(i)) && | 934 return IsSafeDescKind(rec.kind()) && (rec.token_pos != Scanner::kNoSourcePos); |
943 (desc.TokenPos(i) != Scanner::kNoSourcePos); | |
944 } | 935 } |
945 | 936 |
946 | 937 |
947 CodeBreakpoint::CodeBreakpoint(const Code& code, intptr_t pc_desc_index) | 938 CodeBreakpoint::CodeBreakpoint(const Code& code, |
939 const RawPcDescriptors::PcDescriptorRec& rec) | |
948 : code_(code.raw()), | 940 : code_(code.raw()), |
949 pc_desc_index_(pc_desc_index), | 941 token_pos_(rec.token_pos), |
950 pc_(0), | 942 pc_(rec.pc), |
951 line_number_(-1), | 943 line_number_(-1), |
952 is_enabled_(false), | 944 is_enabled_(false), |
953 src_bpt_(NULL), | 945 src_bpt_(NULL), |
954 next_(NULL) { | 946 next_(NULL), |
955 saved_value_ = 0; | 947 breakpoint_kind_(rec.kind()), |
948 saved_value_(0) { | |
956 ASSERT(!code.IsNull()); | 949 ASSERT(!code.IsNull()); |
957 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | |
958 ASSERT(pc_desc_index < desc.Length()); | |
959 token_pos_ = desc.TokenPos(pc_desc_index); | |
960 ASSERT(token_pos_ > 0); | 950 ASSERT(token_pos_ > 0); |
961 pc_ = desc.PC(pc_desc_index); | |
962 ASSERT(pc_ != 0); | 951 ASSERT(pc_ != 0); |
963 breakpoint_kind_ = desc.DescriptorKind(pc_desc_index); | |
964 ASSERT(IsSafeDescKind(breakpoint_kind_)); | 952 ASSERT(IsSafeDescKind(breakpoint_kind_)); |
965 } | 953 } |
966 | 954 |
967 | 955 |
968 CodeBreakpoint::~CodeBreakpoint() { | 956 CodeBreakpoint::~CodeBreakpoint() { |
969 // Make sure we don't leave patched code behind. | 957 // Make sure we don't leave patched code behind. |
970 ASSERT(!IsEnabled()); | 958 ASSERT(!IsEnabled()); |
971 // Poison the data so we catch use after free errors. | 959 // Poison the data so we catch use after free errors. |
972 #ifdef DEBUG | 960 #ifdef DEBUG |
973 code_ = Code::null(); | 961 code_ = Code::null(); |
974 pc_ = 0ul; | 962 pc_ = 0ul; |
975 src_bpt_ = NULL; | 963 src_bpt_ = NULL; |
976 next_ = NULL; | 964 next_ = NULL; |
977 breakpoint_kind_ = PcDescriptors::kOther; | 965 breakpoint_kind_ = RawPcDescriptors::kOther; |
978 #endif | 966 #endif |
979 } | 967 } |
980 | 968 |
981 | 969 |
982 RawFunction* CodeBreakpoint::function() const { | 970 RawFunction* CodeBreakpoint::function() const { |
983 return Code::Handle(code_).function(); | 971 return Code::Handle(code_).function(); |
984 } | 972 } |
985 | 973 |
986 | 974 |
987 RawScript* CodeBreakpoint::SourceCode() { | 975 RawScript* CodeBreakpoint::SourceCode() { |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1207 return; | 1195 return; |
1208 } | 1196 } |
1209 } | 1197 } |
1210 // Hang on to the code object before deoptimizing, in case deoptimization | 1198 // Hang on to the code object before deoptimizing, in case deoptimization |
1211 // might cause the GC to run. | 1199 // might cause the GC to run. |
1212 Code& code = Code::Handle(isolate, target_function.unoptimized_code()); | 1200 Code& code = Code::Handle(isolate, target_function.unoptimized_code()); |
1213 ASSERT(!code.IsNull()); | 1201 ASSERT(!code.IsNull()); |
1214 DeoptimizeWorld(); | 1202 DeoptimizeWorld(); |
1215 ASSERT(!target_function.HasOptimizedCode()); | 1203 ASSERT(!target_function.HasOptimizedCode()); |
1216 PcDescriptors& desc = PcDescriptors::Handle(isolate, code.pc_descriptors()); | 1204 PcDescriptors& desc = PcDescriptors::Handle(isolate, code.pc_descriptors()); |
1217 for (intptr_t i = 0; i < desc.Length(); i++) { | 1205 PcDescriptors::Iterator iter(desc); |
1218 if (IsSafePoint(desc, i)) { | 1206 while (iter.HasNext()) { |
1219 CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(i)); | 1207 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
1208 if (IsSafePoint(rec)) { | |
1209 CodeBreakpoint* bpt = GetCodeBreakpoint(rec.pc); | |
1220 if (bpt != NULL) { | 1210 if (bpt != NULL) { |
1221 // There is already a breakpoint for this address. Make sure | 1211 // There is already a breakpoint for this address. Make sure |
1222 // it is enabled. | 1212 // it is enabled. |
1223 bpt->Enable(); | 1213 bpt->Enable(); |
1224 continue; | 1214 continue; |
1225 } | 1215 } |
1226 bpt = new CodeBreakpoint(code, i); | 1216 bpt = new CodeBreakpoint(code, rec); |
1227 RegisterCodeBreakpoint(bpt); | 1217 RegisterCodeBreakpoint(bpt); |
1228 bpt->Enable(); | 1218 bpt->Enable(); |
1229 } | 1219 } |
1230 } | 1220 } |
1231 } | 1221 } |
1232 | 1222 |
1233 | 1223 |
1234 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { | 1224 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { |
1235 if (HasEventHandler()) { | 1225 if (HasEventHandler()) { |
1236 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointResolved); | 1226 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointResolved); |
(...skipping 19 matching lines...) Expand all Loading... | |
1256 new ActivationFrame(pc, frame->fp(), frame->sp(), code, | 1246 new ActivationFrame(pc, frame->fp(), frame->sp(), code, |
1257 deopt_frame, deopt_frame_offset); | 1247 deopt_frame, deopt_frame_offset); |
1258 | 1248 |
1259 // Is there a closure call at the current PC? | 1249 // Is there a closure call at the current PC? |
1260 // | 1250 // |
1261 // We can't just check the callee_activation to see if it is a | 1251 // We can't just check the callee_activation to see if it is a |
1262 // closure function, because it may not be on the stack yet. | 1252 // closure function, because it may not be on the stack yet. |
1263 bool is_closure_call = false; | 1253 bool is_closure_call = false; |
1264 const PcDescriptors& pc_desc = | 1254 const PcDescriptors& pc_desc = |
1265 PcDescriptors::Handle(isolate, code.pc_descriptors()); | 1255 PcDescriptors::Handle(isolate, code.pc_descriptors()); |
1266 | 1256 PcDescriptors::Iterator iter(pc_desc); |
1267 for (int i = 0; i < pc_desc.Length(); i++) { | 1257 while (iter.HasNext()) { |
1268 if (pc_desc.PC(i) == pc && | 1258 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
1269 pc_desc.DescriptorKind(i) == PcDescriptors::kClosureCall) { | 1259 if ((rec.pc == pc) && (rec.kind() == RawPcDescriptors::kClosureCall)) { |
1270 is_closure_call = true; | 1260 is_closure_call = true; |
1271 break; | 1261 break; |
1272 } | 1262 } |
1273 } | 1263 } |
1274 | 1264 |
1275 // Recover the context for this frame. | 1265 // Recover the context for this frame. |
1276 if (is_closure_call) { | 1266 if (is_closure_call) { |
1277 // If the callee is a closure, we should have stored the context | 1267 // If the callee is a closure, we should have stored the context |
1278 // in the current frame before making the call. | 1268 // in the current frame before making the call. |
1279 const Context& closure_call_ctx = | 1269 const Context& closure_call_ctx = |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1549 if (requested_token_pos < func.token_pos()) { | 1539 if (requested_token_pos < func.token_pos()) { |
1550 requested_token_pos = func.token_pos(); | 1540 requested_token_pos = func.token_pos(); |
1551 } | 1541 } |
1552 if (last_token_pos > func.end_token_pos()) { | 1542 if (last_token_pos > func.end_token_pos()) { |
1553 last_token_pos = func.end_token_pos(); | 1543 last_token_pos = func.end_token_pos(); |
1554 } | 1544 } |
1555 | 1545 |
1556 Code& code = Code::Handle(func.unoptimized_code()); | 1546 Code& code = Code::Handle(func.unoptimized_code()); |
1557 ASSERT(!code.IsNull()); | 1547 ASSERT(!code.IsNull()); |
1558 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 1548 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
1559 intptr_t best_fit_index = -1; | |
1560 intptr_t best_fit_pos = INT_MAX; | 1549 intptr_t best_fit_pos = INT_MAX; |
1550 const RawPcDescriptors::PcDescriptorRec* best_fit_rec = NULL; | |
1561 uword lowest_pc = kUwordMax; | 1551 uword lowest_pc = kUwordMax; |
1562 intptr_t lowest_pc_index = -1; | 1552 const RawPcDescriptors::PcDescriptorRec* lowest_pc_rec = NULL; |
1563 | 1553 |
1564 for (intptr_t i = 0; i < desc.Length(); i++) { | 1554 const RawPcDescriptors::PcDescriptorRec* rec = NULL; |
1565 intptr_t desc_token_pos = desc.TokenPos(i); | 1555 PcDescriptors::Iterator iter(desc); |
1556 while (iter.HasNext()) { | |
1557 rec = &iter.Next(); | |
1558 intptr_t desc_token_pos = rec->token_pos; | |
1566 ASSERT(desc_token_pos >= 0); | 1559 ASSERT(desc_token_pos >= 0); |
1567 if (IsSafePoint(desc, i)) { | 1560 if (IsSafePoint(*rec)) { |
1568 if ((desc_token_pos < requested_token_pos) || | 1561 if ((desc_token_pos < requested_token_pos) || |
1569 (desc_token_pos > last_token_pos)) { | 1562 (desc_token_pos > last_token_pos)) { |
1570 // This descriptor is outside the desired token range. | 1563 // This descriptor is outside the desired token range. |
1571 continue; | 1564 continue; |
1572 } | 1565 } |
1573 if (desc_token_pos < best_fit_pos) { | 1566 if (desc_token_pos < best_fit_pos) { |
1574 // So far, this descriptor has the lowest token position after | 1567 // So far, this descriptor has the lowest token position after |
1575 // the first acceptable token position. | 1568 // the first acceptable token position. |
1576 best_fit_pos = desc_token_pos; | 1569 best_fit_pos = desc_token_pos; |
1577 best_fit_index = i; | 1570 best_fit_rec = rec; |
1578 } | 1571 } |
1579 if (desc.PC(i) < lowest_pc) { | 1572 if (rec->pc < lowest_pc) { |
1580 // This descriptor so far has the lowest code address. | 1573 // This descriptor so far has the lowest code address. |
1581 lowest_pc = desc.PC(i); | 1574 lowest_pc = rec->pc; |
1582 lowest_pc_index = i; | 1575 lowest_pc_rec = rec; |
1583 } | 1576 } |
1584 } | 1577 } |
1585 } | 1578 } |
1586 if (lowest_pc_index >= 0) { | 1579 if (lowest_pc_rec != NULL) { |
1587 // We found the pc descriptor that has the lowest execution address. | 1580 // We found the pc descriptor that has the lowest execution address. |
1588 // This is the first possible breakpoint after the requested token | 1581 // This is the first possible breakpoint after the requested token |
1589 // position. We use this instead of the nearest PC descriptor | 1582 // position. We use this instead of the nearest PC descriptor |
1590 // measured in token index distance. | 1583 // measured in token index distance. |
1591 best_fit_index = lowest_pc_index; | 1584 best_fit_rec = lowest_pc_rec; |
1592 } | 1585 } |
1593 if (best_fit_index >= 0) { | 1586 if (best_fit_rec != NULL) { |
1594 return desc.TokenPos(best_fit_index); | 1587 return best_fit_rec->token_pos; |
1595 } | 1588 } |
1596 // We didn't find a safe point in the given token range. Try and find | 1589 // We didn't find a safe point in the given token range. Try and find |
1597 // a safe point in the remaining source code of the function. | 1590 // a safe point in the remaining source code of the function. |
1598 if (last_token_pos < func.end_token_pos()) { | 1591 if (last_token_pos < func.end_token_pos()) { |
1599 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos()); | 1592 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos()); |
1600 } | 1593 } |
1601 return -1; | 1594 return -1; |
1602 } | 1595 } |
1603 | 1596 |
1604 | 1597 |
1605 void Debugger::MakeCodeBreakpointAt(const Function& func, | 1598 void Debugger::MakeCodeBreakpointAt(const Function& func, |
1606 SourceBreakpoint* bpt) { | 1599 SourceBreakpoint* bpt) { |
1607 ASSERT((bpt != NULL) && bpt->IsResolved()); | 1600 ASSERT((bpt != NULL) && bpt->IsResolved()); |
1608 ASSERT(!func.HasOptimizedCode()); | 1601 ASSERT(!func.HasOptimizedCode()); |
1609 Code& code = Code::Handle(func.unoptimized_code()); | 1602 Code& code = Code::Handle(func.unoptimized_code()); |
1610 ASSERT(!code.IsNull()); | 1603 ASSERT(!code.IsNull()); |
1611 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 1604 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
1612 uword lowest_pc = kUwordMax; | 1605 uword lowest_pc = kUwordMax; |
1613 intptr_t lowest_pc_index = -1; | |
1614 // Find the safe point with the lowest compiled code address | 1606 // Find the safe point with the lowest compiled code address |
1615 // that maps to the token position of the source breakpoint. | 1607 // that maps to the token position of the source breakpoint. |
1616 for (intptr_t i = 0; i < desc.Length(); i++) { | 1608 PcDescriptors::Iterator iter(desc); |
1617 intptr_t desc_token_pos = desc.TokenPos(i); | 1609 const RawPcDescriptors::PcDescriptorRec* lowest_rec = NULL; |
1618 if ((desc_token_pos == bpt->token_pos_) && IsSafePoint(desc, i)) { | 1610 while (iter.HasNext()) { |
1619 if (desc.PC(i) < lowest_pc) { | 1611 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
1620 // This descriptor so far has the lowest code address. | 1612 intptr_t desc_token_pos = rec.token_pos; |
1621 lowest_pc = desc.PC(i); | 1613 if ((desc_token_pos == bpt->token_pos_) && IsSafePoint(rec)) { |
1622 lowest_pc_index = i; | 1614 if (rec.pc < lowest_pc) { |
1615 lowest_pc = rec.pc; | |
1616 lowest_rec = &rec; | |
1623 } | 1617 } |
1624 } | 1618 } |
1625 } | 1619 } |
1626 if (lowest_pc_index < 0) { | 1620 if (lowest_rec == NULL) { |
1627 return; | 1621 return; |
1628 } | 1622 } |
1629 CodeBreakpoint* code_bpt = GetCodeBreakpoint(desc.PC(lowest_pc_index)); | 1623 CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_rec->pc); |
1630 if (code_bpt == NULL) { | 1624 if (code_bpt == NULL) { |
1631 // No code breakpoint for this code exists; create one. | 1625 // No code breakpoint for this code exists; create one. |
1632 code_bpt = new CodeBreakpoint(code, lowest_pc_index); | 1626 code_bpt = new CodeBreakpoint(code, *lowest_rec); |
1633 RegisterCodeBreakpoint(code_bpt); | 1627 RegisterCodeBreakpoint(code_bpt); |
1634 } | 1628 } |
1635 code_bpt->set_src_bpt(bpt); | 1629 code_bpt->set_src_bpt(bpt); |
1636 if (bpt->IsEnabled()) { | 1630 if (bpt->IsEnabled()) { |
1637 code_bpt->Enable(); | 1631 code_bpt->Enable(); |
1638 } | 1632 } |
1639 } | 1633 } |
1640 | 1634 |
1641 | 1635 |
1642 void Debugger::FindCompiledFunctions(const Script& script, | 1636 void Debugger::FindCompiledFunctions(const Script& script, |
(...skipping 941 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2584 } | 2578 } |
2585 | 2579 |
2586 | 2580 |
2587 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 2581 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
2588 ASSERT(bpt->next() == NULL); | 2582 ASSERT(bpt->next() == NULL); |
2589 bpt->set_next(code_breakpoints_); | 2583 bpt->set_next(code_breakpoints_); |
2590 code_breakpoints_ = bpt; | 2584 code_breakpoints_ = bpt; |
2591 } | 2585 } |
2592 | 2586 |
2593 } // namespace dart | 2587 } // namespace dart |
OLD | NEW |