| 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 341 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 PcDescriptors::Iterator iter(pc_desc_); | 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_; |
| (...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 914 | 914 |
| 915 | 915 |
| 916 | 916 |
| 917 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) { | 917 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) { |
| 918 if (FLAG_show_invisible_frames || frame->function().is_visible()) { | 918 if (FLAG_show_invisible_frames || frame->function().is_visible()) { |
| 919 trace_.Add(frame); | 919 trace_.Add(frame); |
| 920 } | 920 } |
| 921 } | 921 } |
| 922 | 922 |
| 923 | 923 |
| 924 static bool IsSafeDescKind(int8_t kind) { | 924 const uint8_t kSafepointKind = |
| 925 return ((kind == RawPcDescriptors::kIcCall) || | 925 RawPcDescriptors::kIcCall | RawPcDescriptors::kOptStaticCall | |
| 926 (kind == RawPcDescriptors::kOptStaticCall) || | 926 RawPcDescriptors::kUnoptStaticCall | RawPcDescriptors::kClosureCall | |
| 927 (kind == RawPcDescriptors::kUnoptStaticCall) || | 927 RawPcDescriptors::kRuntimeCall; |
| 928 (kind == RawPcDescriptors::kClosureCall) || | 928 |
| 929 (kind == RawPcDescriptors::kRuntimeCall)); | 929 |
| 930 static bool HasTokenPos(const RawPcDescriptors::PcDescriptorRec& rec) { |
| 931 return rec.token_pos != Scanner::kNoSourcePos; |
| 930 } | 932 } |
| 931 | 933 |
| 932 | 934 |
| 933 static bool IsSafePoint(const RawPcDescriptors::PcDescriptorRec& rec) { | |
| 934 return IsSafeDescKind(rec.kind()) && (rec.token_pos != Scanner::kNoSourcePos); | |
| 935 } | |
| 936 | |
| 937 | |
| 938 CodeBreakpoint::CodeBreakpoint(const Code& code, | 935 CodeBreakpoint::CodeBreakpoint(const Code& code, |
| 939 const RawPcDescriptors::PcDescriptorRec& rec) | 936 const RawPcDescriptors::PcDescriptorRec& rec) |
| 940 : code_(code.raw()), | 937 : code_(code.raw()), |
| 941 token_pos_(rec.token_pos), | 938 token_pos_(rec.token_pos), |
| 942 pc_(rec.pc), | 939 pc_(rec.pc), |
| 943 line_number_(-1), | 940 line_number_(-1), |
| 944 is_enabled_(false), | 941 is_enabled_(false), |
| 945 src_bpt_(NULL), | 942 src_bpt_(NULL), |
| 946 next_(NULL), | 943 next_(NULL), |
| 947 breakpoint_kind_(rec.kind()), | 944 breakpoint_kind_(rec.kind()), |
| 948 saved_value_(0) { | 945 saved_value_(0) { |
| 949 ASSERT(!code.IsNull()); | 946 ASSERT(!code.IsNull()); |
| 950 ASSERT(token_pos_ > 0); | 947 ASSERT(token_pos_ > 0); |
| 951 ASSERT(pc_ != 0); | 948 ASSERT(pc_ != 0); |
| 952 ASSERT(IsSafeDescKind(breakpoint_kind_)); | 949 ASSERT((breakpoint_kind_ & kSafepointKind) != 0); |
| 953 } | 950 } |
| 954 | 951 |
| 955 | 952 |
| 956 CodeBreakpoint::~CodeBreakpoint() { | 953 CodeBreakpoint::~CodeBreakpoint() { |
| 957 // Make sure we don't leave patched code behind. | 954 // Make sure we don't leave patched code behind. |
| 958 ASSERT(!IsEnabled()); | 955 ASSERT(!IsEnabled()); |
| 959 // Poison the data so we catch use after free errors. | 956 // Poison the data so we catch use after free errors. |
| 960 #ifdef DEBUG | 957 #ifdef DEBUG |
| 961 code_ = Code::null(); | 958 code_ = Code::null(); |
| 962 pc_ = 0ul; | 959 pc_ = 0ul; |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1195 return; | 1192 return; |
| 1196 } | 1193 } |
| 1197 } | 1194 } |
| 1198 // Hang on to the code object before deoptimizing, in case deoptimization | 1195 // Hang on to the code object before deoptimizing, in case deoptimization |
| 1199 // might cause the GC to run. | 1196 // might cause the GC to run. |
| 1200 Code& code = Code::Handle(isolate, target_function.unoptimized_code()); | 1197 Code& code = Code::Handle(isolate, target_function.unoptimized_code()); |
| 1201 ASSERT(!code.IsNull()); | 1198 ASSERT(!code.IsNull()); |
| 1202 DeoptimizeWorld(); | 1199 DeoptimizeWorld(); |
| 1203 ASSERT(!target_function.HasOptimizedCode()); | 1200 ASSERT(!target_function.HasOptimizedCode()); |
| 1204 PcDescriptors& desc = PcDescriptors::Handle(isolate, code.pc_descriptors()); | 1201 PcDescriptors& desc = PcDescriptors::Handle(isolate, code.pc_descriptors()); |
| 1205 PcDescriptors::Iterator iter(desc); | 1202 PcDescriptors::Iterator iter(desc, kSafepointKind); |
| 1206 while (iter.HasNext()) { | 1203 while (iter.HasNext()) { |
| 1207 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); | 1204 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
| 1208 if (IsSafePoint(rec)) { | 1205 if (HasTokenPos(rec)) { |
| 1209 CodeBreakpoint* bpt = GetCodeBreakpoint(rec.pc); | 1206 CodeBreakpoint* bpt = GetCodeBreakpoint(rec.pc); |
| 1210 if (bpt != NULL) { | 1207 if (bpt != NULL) { |
| 1211 // There is already a breakpoint for this address. Make sure | 1208 // There is already a breakpoint for this address. Make sure |
| 1212 // it is enabled. | 1209 // it is enabled. |
| 1213 bpt->Enable(); | 1210 bpt->Enable(); |
| 1214 continue; | 1211 continue; |
| 1215 } | 1212 } |
| 1216 bpt = new CodeBreakpoint(code, rec); | 1213 bpt = new CodeBreakpoint(code, rec); |
| 1217 RegisterCodeBreakpoint(bpt); | 1214 RegisterCodeBreakpoint(bpt); |
| 1218 bpt->Enable(); | 1215 bpt->Enable(); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1246 new ActivationFrame(pc, frame->fp(), frame->sp(), code, | 1243 new ActivationFrame(pc, frame->fp(), frame->sp(), code, |
| 1247 deopt_frame, deopt_frame_offset); | 1244 deopt_frame, deopt_frame_offset); |
| 1248 | 1245 |
| 1249 // Is there a closure call at the current PC? | 1246 // Is there a closure call at the current PC? |
| 1250 // | 1247 // |
| 1251 // 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 |
| 1252 // closure function, because it may not be on the stack yet. | 1249 // closure function, because it may not be on the stack yet. |
| 1253 bool is_closure_call = false; | 1250 bool is_closure_call = false; |
| 1254 const PcDescriptors& pc_desc = | 1251 const PcDescriptors& pc_desc = |
| 1255 PcDescriptors::Handle(isolate, code.pc_descriptors()); | 1252 PcDescriptors::Handle(isolate, code.pc_descriptors()); |
| 1256 PcDescriptors::Iterator iter(pc_desc); | 1253 PcDescriptors::Iterator iter(pc_desc, RawPcDescriptors::kClosureCall); |
| 1257 while (iter.HasNext()) { | 1254 while (iter.HasNext()) { |
| 1258 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); | 1255 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
| 1259 if ((rec.pc == pc) && (rec.kind() == RawPcDescriptors::kClosureCall)) { | 1256 if (rec.pc == pc) { |
| 1260 is_closure_call = true; | 1257 is_closure_call = true; |
| 1261 break; | 1258 break; |
| 1262 } | 1259 } |
| 1263 } | 1260 } |
| 1264 | 1261 |
| 1265 // Recover the context for this frame. | 1262 // Recover the context for this frame. |
| 1266 if (is_closure_call) { | 1263 if (is_closure_call) { |
| 1267 // 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 |
| 1268 // in the current frame before making the call. | 1265 // in the current frame before making the call. |
| 1269 const Context& closure_call_ctx = | 1266 const Context& closure_call_ctx = |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1545 | 1542 |
| 1546 Code& code = Code::Handle(func.unoptimized_code()); | 1543 Code& code = Code::Handle(func.unoptimized_code()); |
| 1547 ASSERT(!code.IsNull()); | 1544 ASSERT(!code.IsNull()); |
| 1548 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 1545 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
| 1549 intptr_t best_fit_pos = INT_MAX; | 1546 intptr_t best_fit_pos = INT_MAX; |
| 1550 const RawPcDescriptors::PcDescriptorRec* best_fit_rec = NULL; | 1547 const RawPcDescriptors::PcDescriptorRec* best_fit_rec = NULL; |
| 1551 uword lowest_pc = kUwordMax; | 1548 uword lowest_pc = kUwordMax; |
| 1552 const RawPcDescriptors::PcDescriptorRec* lowest_pc_rec = NULL; | 1549 const RawPcDescriptors::PcDescriptorRec* lowest_pc_rec = NULL; |
| 1553 | 1550 |
| 1554 const RawPcDescriptors::PcDescriptorRec* rec = NULL; | 1551 const RawPcDescriptors::PcDescriptorRec* rec = NULL; |
| 1555 PcDescriptors::Iterator iter(desc); | 1552 PcDescriptors::Iterator iter(desc, kSafepointKind); |
| 1556 while (iter.HasNext()) { | 1553 while (iter.HasNext()) { |
| 1557 rec = &iter.Next(); | 1554 rec = &iter.Next(); |
| 1558 intptr_t desc_token_pos = rec->token_pos; | 1555 intptr_t desc_token_pos = rec->token_pos; |
| 1559 ASSERT(desc_token_pos >= 0); | 1556 ASSERT(desc_token_pos >= 0); |
| 1560 if (IsSafePoint(*rec)) { | 1557 if (HasTokenPos(*rec)) { |
| 1561 if ((desc_token_pos < requested_token_pos) || | 1558 if ((desc_token_pos < requested_token_pos) || |
| 1562 (desc_token_pos > last_token_pos)) { | 1559 (desc_token_pos > last_token_pos)) { |
| 1563 // This descriptor is outside the desired token range. | 1560 // This descriptor is outside the desired token range. |
| 1564 continue; | 1561 continue; |
| 1565 } | 1562 } |
| 1566 if (desc_token_pos < best_fit_pos) { | 1563 if (desc_token_pos < best_fit_pos) { |
| 1567 // So far, this descriptor has the lowest token position after | 1564 // So far, this descriptor has the lowest token position after |
| 1568 // the first acceptable token position. | 1565 // the first acceptable token position. |
| 1569 best_fit_pos = desc_token_pos; | 1566 best_fit_pos = desc_token_pos; |
| 1570 best_fit_rec = rec; | 1567 best_fit_rec = rec; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1598 void Debugger::MakeCodeBreakpointAt(const Function& func, | 1595 void Debugger::MakeCodeBreakpointAt(const Function& func, |
| 1599 SourceBreakpoint* bpt) { | 1596 SourceBreakpoint* bpt) { |
| 1600 ASSERT((bpt != NULL) && bpt->IsResolved()); | 1597 ASSERT((bpt != NULL) && bpt->IsResolved()); |
| 1601 ASSERT(!func.HasOptimizedCode()); | 1598 ASSERT(!func.HasOptimizedCode()); |
| 1602 Code& code = Code::Handle(func.unoptimized_code()); | 1599 Code& code = Code::Handle(func.unoptimized_code()); |
| 1603 ASSERT(!code.IsNull()); | 1600 ASSERT(!code.IsNull()); |
| 1604 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 1601 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
| 1605 uword lowest_pc = kUwordMax; | 1602 uword lowest_pc = kUwordMax; |
| 1606 // Find the safe point with the lowest compiled code address | 1603 // Find the safe point with the lowest compiled code address |
| 1607 // that maps to the token position of the source breakpoint. | 1604 // that maps to the token position of the source breakpoint. |
| 1608 PcDescriptors::Iterator iter(desc); | 1605 PcDescriptors::Iterator iter(desc, kSafepointKind); |
| 1609 const RawPcDescriptors::PcDescriptorRec* lowest_rec = NULL; | 1606 const RawPcDescriptors::PcDescriptorRec* lowest_rec = NULL; |
| 1610 while (iter.HasNext()) { | 1607 while (iter.HasNext()) { |
| 1611 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); | 1608 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
| 1612 intptr_t desc_token_pos = rec.token_pos; | 1609 intptr_t desc_token_pos = rec.token_pos; |
| 1613 if ((desc_token_pos == bpt->token_pos_) && IsSafePoint(rec)) { | 1610 if ((desc_token_pos == bpt->token_pos_) && HasTokenPos(rec)) { |
| 1614 if (rec.pc < lowest_pc) { | 1611 if (rec.pc < lowest_pc) { |
| 1615 lowest_pc = rec.pc; | 1612 lowest_pc = rec.pc; |
| 1616 lowest_rec = &rec; | 1613 lowest_rec = &rec; |
| 1617 } | 1614 } |
| 1618 } | 1615 } |
| 1619 } | 1616 } |
| 1620 if (lowest_rec == NULL) { | 1617 if (lowest_rec == NULL) { |
| 1621 return; | 1618 return; |
| 1622 } | 1619 } |
| 1623 CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_rec->pc); | 1620 CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_rec->pc); |
| (...skipping 954 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2578 } | 2575 } |
| 2579 | 2576 |
| 2580 | 2577 |
| 2581 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 2578 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
| 2582 ASSERT(bpt->next() == NULL); | 2579 ASSERT(bpt->next() == NULL); |
| 2583 bpt->set_next(code_breakpoints_); | 2580 bpt->set_next(code_breakpoints_); |
| 2584 code_breakpoints_ = bpt; | 2581 code_breakpoints_ = bpt; |
| 2585 } | 2582 } |
| 2586 | 2583 |
| 2587 } // namespace dart | 2584 } // namespace dart |
| OLD | NEW |