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 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind); | 362 PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind); |
363 while (iter.HasNext()) { | 363 while (iter.HasNext()) { |
364 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); | 364 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
365 if (rec.pc == pc_) { | 365 if (rec.pc() == pc_) { |
366 desc_rec_ = &rec; | 366 desc_rec_ = &rec; |
367 token_pos_ = rec.token_pos; | 367 token_pos_ = rec.token_pos(); |
368 break; | 368 break; |
369 } | 369 } |
370 } | 370 } |
371 } | 371 } |
372 return token_pos_; | 372 return token_pos_; |
373 } | 373 } |
374 | 374 |
375 | 375 |
376 intptr_t ActivationFrame::TryIndex() { | 376 intptr_t ActivationFrame::TryIndex() { |
377 if (desc_rec_ == NULL) { | 377 if (desc_rec_ == NULL) { |
378 return -1; | 378 return -1; |
379 } else { | 379 } else { |
380 return desc_rec_->try_index; | 380 return desc_rec_->try_index(); |
381 } | 381 } |
382 } | 382 } |
383 | 383 |
384 | 384 |
385 intptr_t ActivationFrame::LineNumber() { | 385 intptr_t ActivationFrame::LineNumber() { |
386 // Compute line number lazily since it causes scanning of the script. | 386 // Compute line number lazily since it causes scanning of the script. |
387 if ((line_number_ < 0) && (TokenPos() >= 0)) { | 387 if ((line_number_ < 0) && (TokenPos() >= 0)) { |
388 const Script& script = Script::Handle(SourceScript()); | 388 const Script& script = Script::Handle(SourceScript()); |
389 script.GetTokenLocation(TokenPos(), &line_number_, NULL); | 389 script.GetTokenLocation(TokenPos(), &line_number_, NULL); |
390 } | 390 } |
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
921 } | 921 } |
922 | 922 |
923 | 923 |
924 const uint8_t kSafepointKind = | 924 const uint8_t kSafepointKind = |
925 RawPcDescriptors::kIcCall | RawPcDescriptors::kOptStaticCall | | 925 RawPcDescriptors::kIcCall | RawPcDescriptors::kOptStaticCall | |
926 RawPcDescriptors::kUnoptStaticCall | RawPcDescriptors::kClosureCall | | 926 RawPcDescriptors::kUnoptStaticCall | RawPcDescriptors::kClosureCall | |
927 RawPcDescriptors::kRuntimeCall; | 927 RawPcDescriptors::kRuntimeCall; |
928 | 928 |
929 | 929 |
930 static bool HasTokenPos(const RawPcDescriptors::PcDescriptorRec& rec) { | 930 static bool HasTokenPos(const RawPcDescriptors::PcDescriptorRec& rec) { |
931 return rec.token_pos != Scanner::kNoSourcePos; | 931 return rec.token_pos() != Scanner::kNoSourcePos; |
932 } | 932 } |
933 | 933 |
934 | 934 |
935 CodeBreakpoint::CodeBreakpoint(const Code& code, | 935 CodeBreakpoint::CodeBreakpoint(const Code& code, |
936 const RawPcDescriptors::PcDescriptorRec& rec) | 936 const RawPcDescriptors::PcDescriptorRec& rec) |
937 : code_(code.raw()), | 937 : code_(code.raw()), |
938 token_pos_(rec.token_pos), | 938 token_pos_(rec.token_pos()), |
939 pc_(rec.pc), | 939 pc_(rec.pc()), |
940 line_number_(-1), | 940 line_number_(-1), |
941 is_enabled_(false), | 941 is_enabled_(false), |
942 src_bpt_(NULL), | 942 src_bpt_(NULL), |
943 next_(NULL), | 943 next_(NULL), |
944 breakpoint_kind_(rec.kind()), | 944 breakpoint_kind_(rec.kind()), |
945 saved_value_(0) { | 945 saved_value_(0) { |
946 ASSERT(!code.IsNull()); | 946 ASSERT(!code.IsNull()); |
947 ASSERT(token_pos_ > 0); | 947 ASSERT(token_pos_ > 0); |
948 ASSERT(pc_ != 0); | 948 ASSERT(pc_ != 0); |
949 ASSERT((breakpoint_kind_ & kSafepointKind) != 0); | 949 ASSERT((breakpoint_kind_ & kSafepointKind) != 0); |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1196 // might cause the GC to run. | 1196 // might cause the GC to run. |
1197 Code& code = Code::Handle(isolate, target_function.unoptimized_code()); | 1197 Code& code = Code::Handle(isolate, target_function.unoptimized_code()); |
1198 ASSERT(!code.IsNull()); | 1198 ASSERT(!code.IsNull()); |
1199 DeoptimizeWorld(); | 1199 DeoptimizeWorld(); |
1200 ASSERT(!target_function.HasOptimizedCode()); | 1200 ASSERT(!target_function.HasOptimizedCode()); |
1201 PcDescriptors& desc = PcDescriptors::Handle(isolate, code.pc_descriptors()); | 1201 PcDescriptors& desc = PcDescriptors::Handle(isolate, code.pc_descriptors()); |
1202 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1202 PcDescriptors::Iterator iter(desc, kSafepointKind); |
1203 while (iter.HasNext()) { | 1203 while (iter.HasNext()) { |
1204 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); | 1204 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
1205 if (HasTokenPos(rec)) { | 1205 if (HasTokenPos(rec)) { |
1206 CodeBreakpoint* bpt = GetCodeBreakpoint(rec.pc); | 1206 CodeBreakpoint* bpt = GetCodeBreakpoint(rec.pc()); |
1207 if (bpt != NULL) { | 1207 if (bpt != NULL) { |
1208 // There is already a breakpoint for this address. Make sure | 1208 // There is already a breakpoint for this address. Make sure |
1209 // it is enabled. | 1209 // it is enabled. |
1210 bpt->Enable(); | 1210 bpt->Enable(); |
1211 continue; | 1211 continue; |
1212 } | 1212 } |
1213 bpt = new CodeBreakpoint(code, rec); | 1213 bpt = new CodeBreakpoint(code, rec); |
1214 RegisterCodeBreakpoint(bpt); | 1214 RegisterCodeBreakpoint(bpt); |
1215 bpt->Enable(); | 1215 bpt->Enable(); |
1216 } | 1216 } |
(...skipping 29 matching lines...) Expand all Loading... |
1246 // Is there a closure call at the current PC? | 1246 // Is there a closure call at the current PC? |
1247 // | 1247 // |
1248 // We can't just check the callee_activation to see if it is a | 1248 // We can't just check the callee_activation to see if it is a |
1249 // closure function, because it may not be on the stack yet. | 1249 // closure function, because it may not be on the stack yet. |
1250 bool is_closure_call = false; | 1250 bool is_closure_call = false; |
1251 const PcDescriptors& pc_desc = | 1251 const PcDescriptors& pc_desc = |
1252 PcDescriptors::Handle(isolate, code.pc_descriptors()); | 1252 PcDescriptors::Handle(isolate, code.pc_descriptors()); |
1253 PcDescriptors::Iterator iter(pc_desc, RawPcDescriptors::kClosureCall); | 1253 PcDescriptors::Iterator iter(pc_desc, RawPcDescriptors::kClosureCall); |
1254 while (iter.HasNext()) { | 1254 while (iter.HasNext()) { |
1255 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); | 1255 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
1256 if (rec.pc == pc) { | 1256 if (rec.pc() == pc) { |
1257 is_closure_call = true; | 1257 is_closure_call = true; |
1258 break; | 1258 break; |
1259 } | 1259 } |
1260 } | 1260 } |
1261 | 1261 |
1262 // Recover the context for this frame. | 1262 // Recover the context for this frame. |
1263 if (is_closure_call) { | 1263 if (is_closure_call) { |
1264 // If the callee is a closure, we should have stored the context | 1264 // If the callee is a closure, we should have stored the context |
1265 // in the current frame before making the call. | 1265 // in the current frame before making the call. |
1266 const Context& closure_call_ctx = | 1266 const Context& closure_call_ctx = |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1545 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 1545 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
1546 intptr_t best_fit_pos = INT_MAX; | 1546 intptr_t best_fit_pos = INT_MAX; |
1547 const RawPcDescriptors::PcDescriptorRec* best_fit_rec = NULL; | 1547 const RawPcDescriptors::PcDescriptorRec* best_fit_rec = NULL; |
1548 uword lowest_pc = kUwordMax; | 1548 uword lowest_pc = kUwordMax; |
1549 const RawPcDescriptors::PcDescriptorRec* lowest_pc_rec = NULL; | 1549 const RawPcDescriptors::PcDescriptorRec* lowest_pc_rec = NULL; |
1550 | 1550 |
1551 const RawPcDescriptors::PcDescriptorRec* rec = NULL; | 1551 const RawPcDescriptors::PcDescriptorRec* rec = NULL; |
1552 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1552 PcDescriptors::Iterator iter(desc, kSafepointKind); |
1553 while (iter.HasNext()) { | 1553 while (iter.HasNext()) { |
1554 rec = &iter.Next(); | 1554 rec = &iter.Next(); |
1555 intptr_t desc_token_pos = rec->token_pos; | 1555 intptr_t desc_token_pos = rec->token_pos(); |
1556 ASSERT(desc_token_pos >= 0); | 1556 ASSERT(desc_token_pos >= 0); |
1557 if (HasTokenPos(*rec)) { | 1557 if (HasTokenPos(*rec)) { |
1558 if ((desc_token_pos < requested_token_pos) || | 1558 if ((desc_token_pos < requested_token_pos) || |
1559 (desc_token_pos > last_token_pos)) { | 1559 (desc_token_pos > last_token_pos)) { |
1560 // This descriptor is outside the desired token range. | 1560 // This descriptor is outside the desired token range. |
1561 continue; | 1561 continue; |
1562 } | 1562 } |
1563 if (desc_token_pos < best_fit_pos) { | 1563 if (desc_token_pos < best_fit_pos) { |
1564 // So far, this descriptor has the lowest token position after | 1564 // So far, this descriptor has the lowest token position after |
1565 // the first acceptable token position. | 1565 // the first acceptable token position. |
1566 best_fit_pos = desc_token_pos; | 1566 best_fit_pos = desc_token_pos; |
1567 best_fit_rec = rec; | 1567 best_fit_rec = rec; |
1568 } | 1568 } |
1569 if (rec->pc < lowest_pc) { | 1569 if (rec->pc() < lowest_pc) { |
1570 // This descriptor so far has the lowest code address. | 1570 // This descriptor so far has the lowest code address. |
1571 lowest_pc = rec->pc; | 1571 lowest_pc = rec->pc(); |
1572 lowest_pc_rec = rec; | 1572 lowest_pc_rec = rec; |
1573 } | 1573 } |
1574 } | 1574 } |
1575 } | 1575 } |
1576 if (lowest_pc_rec != NULL) { | 1576 if (lowest_pc_rec != NULL) { |
1577 // We found the pc descriptor that has the lowest execution address. | 1577 // We found the pc descriptor that has the lowest execution address. |
1578 // This is the first possible breakpoint after the requested token | 1578 // This is the first possible breakpoint after the requested token |
1579 // position. We use this instead of the nearest PC descriptor | 1579 // position. We use this instead of the nearest PC descriptor |
1580 // measured in token index distance. | 1580 // measured in token index distance. |
1581 best_fit_rec = lowest_pc_rec; | 1581 best_fit_rec = lowest_pc_rec; |
1582 } | 1582 } |
1583 if (best_fit_rec != NULL) { | 1583 if (best_fit_rec != NULL) { |
1584 return best_fit_rec->token_pos; | 1584 return best_fit_rec->token_pos(); |
1585 } | 1585 } |
1586 // We didn't find a safe point in the given token range. Try and find | 1586 // We didn't find a safe point in the given token range. Try and find |
1587 // a safe point in the remaining source code of the function. | 1587 // a safe point in the remaining source code of the function. |
1588 if (last_token_pos < func.end_token_pos()) { | 1588 if (last_token_pos < func.end_token_pos()) { |
1589 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos()); | 1589 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos()); |
1590 } | 1590 } |
1591 return -1; | 1591 return -1; |
1592 } | 1592 } |
1593 | 1593 |
1594 | 1594 |
1595 void Debugger::MakeCodeBreakpointAt(const Function& func, | 1595 void Debugger::MakeCodeBreakpointAt(const Function& func, |
1596 SourceBreakpoint* bpt) { | 1596 SourceBreakpoint* bpt) { |
1597 ASSERT((bpt != NULL) && bpt->IsResolved()); | 1597 ASSERT((bpt != NULL) && bpt->IsResolved()); |
1598 ASSERT(!func.HasOptimizedCode()); | 1598 ASSERT(!func.HasOptimizedCode()); |
1599 Code& code = Code::Handle(func.unoptimized_code()); | 1599 Code& code = Code::Handle(func.unoptimized_code()); |
1600 ASSERT(!code.IsNull()); | 1600 ASSERT(!code.IsNull()); |
1601 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 1601 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
1602 uword lowest_pc = kUwordMax; | 1602 uword lowest_pc = kUwordMax; |
1603 // Find the safe point with the lowest compiled code address | 1603 // Find the safe point with the lowest compiled code address |
1604 // that maps to the token position of the source breakpoint. | 1604 // that maps to the token position of the source breakpoint. |
1605 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1605 PcDescriptors::Iterator iter(desc, kSafepointKind); |
1606 const RawPcDescriptors::PcDescriptorRec* lowest_rec = NULL; | 1606 const RawPcDescriptors::PcDescriptorRec* lowest_rec = NULL; |
1607 while (iter.HasNext()) { | 1607 while (iter.HasNext()) { |
1608 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); | 1608 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
1609 intptr_t desc_token_pos = rec.token_pos; | 1609 intptr_t desc_token_pos = rec.token_pos(); |
1610 if ((desc_token_pos == bpt->token_pos_) && HasTokenPos(rec)) { | 1610 if ((desc_token_pos == bpt->token_pos_) && HasTokenPos(rec)) { |
1611 if (rec.pc < lowest_pc) { | 1611 if (rec.pc() < lowest_pc) { |
1612 lowest_pc = rec.pc; | 1612 lowest_pc = rec.pc(); |
1613 lowest_rec = &rec; | 1613 lowest_rec = &rec; |
1614 } | 1614 } |
1615 } | 1615 } |
1616 } | 1616 } |
1617 if (lowest_rec == NULL) { | 1617 if (lowest_rec == NULL) { |
1618 return; | 1618 return; |
1619 } | 1619 } |
1620 CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_rec->pc); | 1620 CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_rec->pc()); |
1621 if (code_bpt == NULL) { | 1621 if (code_bpt == NULL) { |
1622 // No code breakpoint for this code exists; create one. | 1622 // No code breakpoint for this code exists; create one. |
1623 code_bpt = new CodeBreakpoint(code, *lowest_rec); | 1623 code_bpt = new CodeBreakpoint(code, *lowest_rec); |
1624 RegisterCodeBreakpoint(code_bpt); | 1624 RegisterCodeBreakpoint(code_bpt); |
1625 } | 1625 } |
1626 code_bpt->set_src_bpt(bpt); | 1626 code_bpt->set_src_bpt(bpt); |
1627 if (bpt->IsEnabled()) { | 1627 if (bpt->IsEnabled()) { |
1628 code_bpt->Enable(); | 1628 code_bpt->Enable(); |
1629 } | 1629 } |
1630 } | 1630 } |
(...skipping 944 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2575 } | 2575 } |
2576 | 2576 |
2577 | 2577 |
2578 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 2578 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
2579 ASSERT(bpt->next() == NULL); | 2579 ASSERT(bpt->next() == NULL); |
2580 bpt->set_next(code_breakpoints_); | 2580 bpt->set_next(code_breakpoints_); |
2581 code_breakpoints_ = bpt; | 2581 code_breakpoints_ = bpt; |
2582 } | 2582 } |
2583 | 2583 |
2584 } // namespace dart | 2584 } // namespace dart |
OLD | NEW |