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 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 |