| 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 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 | 356 |
| 357 | 357 |
| 358 // Compute token_pos_ and try_index_ and token_pos_initialized_. | 358 // Compute token_pos_ and try_index_ and token_pos_initialized_. |
| 359 intptr_t ActivationFrame::TokenPos() { | 359 intptr_t ActivationFrame::TokenPos() { |
| 360 if (!token_pos_initialized_) { | 360 if (!token_pos_initialized_) { |
| 361 token_pos_initialized_ = true; | 361 token_pos_initialized_ = true; |
| 362 token_pos_ = Scanner::kNoSourcePos; | 362 token_pos_ = Scanner::kNoSourcePos; |
| 363 GetPcDescriptors(); | 363 GetPcDescriptors(); |
| 364 PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind); | 364 PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind); |
| 365 while (iter.HasNext()) { | 365 while (iter.HasNext()) { |
| 366 RawPcDescriptors::PcDescriptorRec rec; | 366 const uword pc = iter.NextPc(); |
| 367 iter.NextRec(&rec); | 367 if (pc == pc_) { |
| 368 if (rec.pc() == pc_) { | 368 try_index_ = iter.current_try_index(); |
| 369 try_index_ = rec.try_index(); | 369 token_pos_ = iter.current_token_pos(); |
| 370 token_pos_ = rec.token_pos(); | |
| 371 break; | 370 break; |
| 372 } | 371 } |
| 373 } | 372 } |
| 374 } | 373 } |
| 375 return token_pos_; | 374 return token_pos_; |
| 376 } | 375 } |
| 377 | 376 |
| 378 | 377 |
| 379 intptr_t ActivationFrame::TryIndex() { | 378 intptr_t ActivationFrame::TryIndex() { |
| 380 if (!token_pos_initialized_) { | 379 if (!token_pos_initialized_) { |
| (...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 924 } | 923 } |
| 925 } | 924 } |
| 926 | 925 |
| 927 | 926 |
| 928 const uint8_t kSafepointKind = | 927 const uint8_t kSafepointKind = |
| 929 RawPcDescriptors::kIcCall | RawPcDescriptors::kOptStaticCall | | 928 RawPcDescriptors::kIcCall | RawPcDescriptors::kOptStaticCall | |
| 930 RawPcDescriptors::kUnoptStaticCall | RawPcDescriptors::kClosureCall | | 929 RawPcDescriptors::kUnoptStaticCall | RawPcDescriptors::kClosureCall | |
| 931 RawPcDescriptors::kRuntimeCall; | 930 RawPcDescriptors::kRuntimeCall; |
| 932 | 931 |
| 933 | 932 |
| 934 static bool HasTokenPos(const RawPcDescriptors::PcDescriptorRec& rec) { | |
| 935 return rec.token_pos() != Scanner::kNoSourcePos; | |
| 936 } | |
| 937 | |
| 938 | |
| 939 CodeBreakpoint::CodeBreakpoint(const Code& code, | 933 CodeBreakpoint::CodeBreakpoint(const Code& code, |
| 940 const RawPcDescriptors::PcDescriptorRec& rec) | 934 intptr_t token_pos, |
| 935 uword pc, |
| 936 RawPcDescriptors::Kind kind) |
| 941 : code_(code.raw()), | 937 : code_(code.raw()), |
| 942 token_pos_(rec.token_pos()), | 938 token_pos_(token_pos), |
| 943 pc_(rec.pc()), | 939 pc_(pc), |
| 944 line_number_(-1), | 940 line_number_(-1), |
| 945 is_enabled_(false), | 941 is_enabled_(false), |
| 946 src_bpt_(NULL), | 942 src_bpt_(NULL), |
| 947 next_(NULL), | 943 next_(NULL), |
| 948 breakpoint_kind_(rec.kind()), | 944 breakpoint_kind_(kind), |
| 949 saved_value_(0) { | 945 saved_value_(0) { |
| 950 ASSERT(!code.IsNull()); | 946 ASSERT(!code.IsNull()); |
| 951 ASSERT(token_pos_ > 0); | 947 ASSERT(token_pos_ > 0); |
| 952 ASSERT(pc_ != 0); | 948 ASSERT(pc_ != 0); |
| 953 ASSERT((breakpoint_kind_ & kSafepointKind) != 0); | 949 ASSERT((breakpoint_kind_ & kSafepointKind) != 0); |
| 954 } | 950 } |
| 955 | 951 |
| 956 | 952 |
| 957 CodeBreakpoint::~CodeBreakpoint() { | 953 CodeBreakpoint::~CodeBreakpoint() { |
| 958 // Make sure we don't leave patched code behind. | 954 // Make sure we don't leave patched code behind. |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1198 } | 1194 } |
| 1199 // Hang on to the code object before deoptimizing, in case deoptimization | 1195 // Hang on to the code object before deoptimizing, in case deoptimization |
| 1200 // might cause the GC to run. | 1196 // might cause the GC to run. |
| 1201 Code& code = Code::Handle(isolate, target_function.unoptimized_code()); | 1197 Code& code = Code::Handle(isolate, target_function.unoptimized_code()); |
| 1202 ASSERT(!code.IsNull()); | 1198 ASSERT(!code.IsNull()); |
| 1203 DeoptimizeWorld(); | 1199 DeoptimizeWorld(); |
| 1204 ASSERT(!target_function.HasOptimizedCode()); | 1200 ASSERT(!target_function.HasOptimizedCode()); |
| 1205 PcDescriptors& desc = PcDescriptors::Handle(isolate, code.pc_descriptors()); | 1201 PcDescriptors& desc = PcDescriptors::Handle(isolate, code.pc_descriptors()); |
| 1206 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1202 PcDescriptors::Iterator iter(desc, kSafepointKind); |
| 1207 while (iter.HasNext()) { | 1203 while (iter.HasNext()) { |
| 1208 RawPcDescriptors::PcDescriptorRec rec; | 1204 const intptr_t token_pos = iter.NextTokenPos(); |
| 1209 iter.NextRec(&rec); | 1205 if (token_pos != Scanner::kNoSourcePos) { |
| 1210 if (HasTokenPos(rec)) { | 1206 CodeBreakpoint* bpt = GetCodeBreakpoint(iter.current_pc()); |
| 1211 CodeBreakpoint* bpt = GetCodeBreakpoint(rec.pc()); | |
| 1212 if (bpt != NULL) { | 1207 if (bpt != NULL) { |
| 1213 // There is already a breakpoint for this address. Make sure | 1208 // There is already a breakpoint for this address. Make sure |
| 1214 // it is enabled. | 1209 // it is enabled. |
| 1215 bpt->Enable(); | 1210 bpt->Enable(); |
| 1216 continue; | 1211 continue; |
| 1217 } | 1212 } |
| 1218 bpt = new CodeBreakpoint(code, rec); | 1213 bpt = new CodeBreakpoint(code, iter.current_token_pos(), |
| 1214 iter.current_pc(), iter.current_kind()); |
| 1219 RegisterCodeBreakpoint(bpt); | 1215 RegisterCodeBreakpoint(bpt); |
| 1220 bpt->Enable(); | 1216 bpt->Enable(); |
| 1221 } | 1217 } |
| 1222 } | 1218 } |
| 1223 } | 1219 } |
| 1224 | 1220 |
| 1225 | 1221 |
| 1226 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { | 1222 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { |
| 1227 if (HasEventHandler()) { | 1223 if (HasEventHandler()) { |
| 1228 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointResolved); | 1224 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointResolved); |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1546 } | 1542 } |
| 1547 | 1543 |
| 1548 Code& code = Code::Handle(func.unoptimized_code()); | 1544 Code& code = Code::Handle(func.unoptimized_code()); |
| 1549 ASSERT(!code.IsNull()); | 1545 ASSERT(!code.IsNull()); |
| 1550 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 1546 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
| 1551 intptr_t best_fit_pos = INT_MAX; | 1547 intptr_t best_fit_pos = INT_MAX; |
| 1552 uword lowest_pc = kUwordMax; | 1548 uword lowest_pc = kUwordMax; |
| 1553 intptr_t lowest_pc_token_pos = INT_MAX; | 1549 intptr_t lowest_pc_token_pos = INT_MAX; |
| 1554 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1550 PcDescriptors::Iterator iter(desc, kSafepointKind); |
| 1555 while (iter.HasNext()) { | 1551 while (iter.HasNext()) { |
| 1556 RawPcDescriptors::PcDescriptorRec rec; | 1552 const intptr_t desc_token_pos = iter.NextTokenPos(); |
| 1557 iter.NextRec(&rec); | |
| 1558 intptr_t desc_token_pos = rec.token_pos(); | |
| 1559 ASSERT(desc_token_pos >= 0); | 1553 ASSERT(desc_token_pos >= 0); |
| 1560 if (HasTokenPos(rec)) { | 1554 if (desc_token_pos != Scanner::kNoSourcePos) { |
| 1561 if ((desc_token_pos < requested_token_pos) || | 1555 if ((desc_token_pos < requested_token_pos) || |
| 1562 (desc_token_pos > last_token_pos)) { | 1556 (desc_token_pos > last_token_pos)) { |
| 1563 // This descriptor is outside the desired token range. | 1557 // This descriptor is outside the desired token range. |
| 1564 continue; | 1558 continue; |
| 1565 } | 1559 } |
| 1566 if (desc_token_pos < best_fit_pos) { | 1560 if (desc_token_pos < best_fit_pos) { |
| 1567 // So far, this descriptor has the lowest token position after | 1561 // So far, this descriptor has the lowest token position after |
| 1568 // the first acceptable token position. | 1562 // the first acceptable token position. |
| 1569 best_fit_pos = desc_token_pos; | 1563 best_fit_pos = desc_token_pos; |
| 1570 } | 1564 } |
| 1571 if (rec.pc() < lowest_pc) { | 1565 if (iter.current_pc() < lowest_pc) { |
| 1572 // This descriptor so far has the lowest code address. | 1566 // This descriptor so far has the lowest code address. |
| 1573 lowest_pc = rec.pc(); | 1567 lowest_pc = iter.current_pc(); |
| 1574 lowest_pc_token_pos = desc_token_pos; | 1568 lowest_pc_token_pos = desc_token_pos; |
| 1575 } | 1569 } |
| 1576 } | 1570 } |
| 1577 } | 1571 } |
| 1578 if (lowest_pc_token_pos != INT_MAX) { | 1572 if (lowest_pc_token_pos != INT_MAX) { |
| 1579 // We found the pc descriptor that has the lowest execution address. | 1573 // We found the pc descriptor that has the lowest execution address. |
| 1580 // This is the first possible breakpoint after the requested token | 1574 // This is the first possible breakpoint after the requested token |
| 1581 // position. We use this instead of the nearest PC descriptor | 1575 // position. We use this instead of the nearest PC descriptor |
| 1582 // measured in token index distance. | 1576 // measured in token index distance. |
| 1583 return lowest_pc_token_pos; | 1577 return lowest_pc_token_pos; |
| 1584 } | 1578 } |
| 1585 if (best_fit_pos != INT_MAX) { | 1579 if (best_fit_pos != INT_MAX) { |
| 1586 return best_fit_pos; | 1580 return best_fit_pos; |
| 1587 } | 1581 } |
| 1588 // We didn't find a safe point in the given token range. Try and find | 1582 // We didn't find a safe point in the given token range. Try and find |
| 1589 // a safe point in the remaining source code of the function. | 1583 // a safe point in the remaining source code of the function. |
| 1590 if (last_token_pos < func.end_token_pos()) { | 1584 if (last_token_pos < func.end_token_pos()) { |
| 1591 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos()); | 1585 return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos()); |
| 1592 } | 1586 } |
| 1593 return -1; | 1587 return -1; |
| 1594 } | 1588 } |
| 1595 | 1589 |
| 1596 | 1590 |
| 1597 void Debugger::MakeCodeBreakpointAt(const Function& func, | 1591 void Debugger::MakeCodeBreakpointAt(const Function& func, |
| 1598 SourceBreakpoint* bpt) { | 1592 SourceBreakpoint* bpt) { |
| 1593 ASSERT(bpt->token_pos_ != Scanner::kNoSourcePos); |
| 1599 ASSERT((bpt != NULL) && bpt->IsResolved()); | 1594 ASSERT((bpt != NULL) && bpt->IsResolved()); |
| 1600 ASSERT(!func.HasOptimizedCode()); | 1595 ASSERT(!func.HasOptimizedCode()); |
| 1601 Code& code = Code::Handle(func.unoptimized_code()); | 1596 Code& code = Code::Handle(func.unoptimized_code()); |
| 1602 ASSERT(!code.IsNull()); | 1597 ASSERT(!code.IsNull()); |
| 1603 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 1598 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
| 1604 uword lowest_pc = kUwordMax; | 1599 uword lowest_pc = kUwordMax; |
| 1600 RawPcDescriptors::Kind lowest_kind = RawPcDescriptors::kAnyKind; |
| 1605 // Find the safe point with the lowest compiled code address | 1601 // Find the safe point with the lowest compiled code address |
| 1606 // that maps to the token position of the source breakpoint. | 1602 // that maps to the token position of the source breakpoint. |
| 1607 PcDescriptors::Iterator iter(desc, kSafepointKind); | 1603 PcDescriptors::Iterator iter(desc, kSafepointKind); |
| 1608 RawPcDescriptors::PcDescriptorRec lowest_rec; | |
| 1609 while (iter.HasNext()) { | 1604 while (iter.HasNext()) { |
| 1610 RawPcDescriptors::PcDescriptorRec rec; | 1605 intptr_t desc_token_pos = iter.NextTokenPos(); |
| 1611 iter.NextRec(&rec); | 1606 if (desc_token_pos == bpt->token_pos_) { |
| 1612 intptr_t desc_token_pos = rec.token_pos(); | 1607 if (iter.current_pc() < lowest_pc) { |
| 1613 if ((desc_token_pos == bpt->token_pos_) && HasTokenPos(rec)) { | 1608 lowest_pc = iter.current_pc(); |
| 1614 if (rec.pc() < lowest_pc) { | 1609 lowest_kind = iter.current_kind(); |
| 1615 lowest_pc = rec.pc(); | |
| 1616 lowest_rec = rec; | |
| 1617 } | 1610 } |
| 1618 } | 1611 } |
| 1619 } | 1612 } |
| 1620 if (lowest_pc == kUwordMax) { | 1613 if (lowest_pc == kUwordMax) { |
| 1621 return; | 1614 return; |
| 1622 } | 1615 } |
| 1623 CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_rec.pc()); | 1616 CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_pc); |
| 1624 if (code_bpt == NULL) { | 1617 if (code_bpt == NULL) { |
| 1625 // No code breakpoint for this code exists; create one. | 1618 // No code breakpoint for this code exists; create one. |
| 1626 code_bpt = new CodeBreakpoint(code, lowest_rec); | 1619 code_bpt = new CodeBreakpoint(code, bpt->token_pos_, |
| 1620 lowest_pc, lowest_kind); |
| 1627 RegisterCodeBreakpoint(code_bpt); | 1621 RegisterCodeBreakpoint(code_bpt); |
| 1628 } | 1622 } |
| 1629 code_bpt->set_src_bpt(bpt); | 1623 code_bpt->set_src_bpt(bpt); |
| 1630 if (bpt->IsEnabled()) { | 1624 if (bpt->IsEnabled()) { |
| 1631 code_bpt->Enable(); | 1625 code_bpt->Enable(); |
| 1632 } | 1626 } |
| 1633 } | 1627 } |
| 1634 | 1628 |
| 1635 | 1629 |
| 1636 void Debugger::FindCompiledFunctions(const Script& script, | 1630 void Debugger::FindCompiledFunctions(const Script& script, |
| (...skipping 941 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2578 } | 2572 } |
| 2579 | 2573 |
| 2580 | 2574 |
| 2581 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 2575 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
| 2582 ASSERT(bpt->next() == NULL); | 2576 ASSERT(bpt->next() == NULL); |
| 2583 bpt->set_next(code_breakpoints_); | 2577 bpt->set_next(code_breakpoints_); |
| 2584 code_breakpoints_ = bpt; | 2578 code_breakpoints_ = bpt; |
| 2585 } | 2579 } |
| 2586 | 2580 |
| 2587 } // namespace dart | 2581 } // namespace dart |
| OLD | NEW |