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