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 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 location.AddProperty("type", "Location"); | 149 location.AddProperty("type", "Location"); |
150 | 150 |
151 const String& url = String::Handle(script.url()); | 151 const String& url = String::Handle(script.url()); |
152 location.AddProperty("script", url.ToCString()); | 152 location.AddProperty("script", url.ToCString()); |
153 location.AddProperty("tokenPos", token_pos); | 153 location.AddProperty("tokenPos", token_pos); |
154 } | 154 } |
155 } | 155 } |
156 | 156 |
157 | 157 |
158 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 158 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
159 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_)); | 159 visitor->VisitPointer(reinterpret_cast<RawObject**>(&code_)); |
160 } | 160 } |
161 | 161 |
162 | 162 |
163 ActivationFrame::ActivationFrame( | 163 ActivationFrame::ActivationFrame( |
164 uword pc, | 164 uword pc, |
165 uword fp, | 165 uword fp, |
166 uword sp, | 166 uword sp, |
167 const Code& code, | 167 const Code& code, |
168 const Array& deopt_frame, | 168 const Array& deopt_frame, |
169 intptr_t deopt_frame_offset) | 169 intptr_t deopt_frame_offset) |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 while (cbpt != NULL) { | 262 while (cbpt != NULL) { |
263 if (func.raw() == cbpt->function()) { | 263 if (func.raw() == cbpt->function()) { |
264 return true; | 264 return true; |
265 } | 265 } |
266 cbpt = cbpt->next_; | 266 cbpt = cbpt->next_; |
267 } | 267 } |
268 return false; | 268 return false; |
269 } | 269 } |
270 | 270 |
271 | 271 |
| 272 bool Debugger::HasBreakpoint(const Code& code) { |
| 273 CodeBreakpoint* cbpt = code_breakpoints_; |
| 274 while (cbpt != NULL) { |
| 275 if (code.raw() == cbpt->code_) { |
| 276 return true; |
| 277 } |
| 278 cbpt = cbpt->next_; |
| 279 } |
| 280 return false; |
| 281 } |
| 282 |
| 283 |
272 void Debugger::PrintBreakpointsToJSONArray(JSONArray* jsarr) const { | 284 void Debugger::PrintBreakpointsToJSONArray(JSONArray* jsarr) const { |
273 SourceBreakpoint* sbpt = src_breakpoints_; | 285 SourceBreakpoint* sbpt = src_breakpoints_; |
274 while (sbpt != NULL) { | 286 while (sbpt != NULL) { |
275 jsarr->AddValue(sbpt); | 287 jsarr->AddValue(sbpt); |
276 sbpt = sbpt->next_; | 288 sbpt = sbpt->next_; |
277 } | 289 } |
278 } | 290 } |
279 | 291 |
280 | 292 |
281 RawString* ActivationFrame::QualifiedFunctionName() { | 293 RawString* ActivationFrame::QualifiedFunctionName() { |
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
699 (kind == PcDescriptors::kRuntimeCall)); | 711 (kind == PcDescriptors::kRuntimeCall)); |
700 } | 712 } |
701 | 713 |
702 | 714 |
703 static bool IsSafePoint(const PcDescriptors& desc, intptr_t i) { | 715 static bool IsSafePoint(const PcDescriptors& desc, intptr_t i) { |
704 return IsSafeDescKind(desc.DescriptorKind(i)) && | 716 return IsSafeDescKind(desc.DescriptorKind(i)) && |
705 (desc.TokenPos(i) != Scanner::kNoSourcePos); | 717 (desc.TokenPos(i) != Scanner::kNoSourcePos); |
706 } | 718 } |
707 | 719 |
708 | 720 |
709 CodeBreakpoint::CodeBreakpoint(const Function& func, intptr_t pc_desc_index) | 721 CodeBreakpoint::CodeBreakpoint(const Code& code, intptr_t pc_desc_index) |
710 : function_(func.raw()), | 722 : code_(code.raw()), |
711 pc_desc_index_(pc_desc_index), | 723 pc_desc_index_(pc_desc_index), |
712 pc_(0), | 724 pc_(0), |
713 line_number_(-1), | 725 line_number_(-1), |
714 is_enabled_(false), | 726 is_enabled_(false), |
715 src_bpt_(NULL), | 727 src_bpt_(NULL), |
716 next_(NULL) { | 728 next_(NULL) { |
717 saved_value_ = 0; | 729 saved_value_ = 0; |
718 ASSERT(!func.HasOptimizedCode()); | 730 ASSERT(!code.IsNull()); |
719 Code& code = Code::Handle(func.unoptimized_code()); | |
720 ASSERT(!code.IsNull()); // Function must be compiled. | |
721 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 731 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
722 ASSERT(pc_desc_index < desc.Length()); | 732 ASSERT(pc_desc_index < desc.Length()); |
723 token_pos_ = desc.TokenPos(pc_desc_index); | 733 token_pos_ = desc.TokenPos(pc_desc_index); |
724 ASSERT(token_pos_ > 0); | 734 ASSERT(token_pos_ > 0); |
725 pc_ = desc.PC(pc_desc_index); | 735 pc_ = desc.PC(pc_desc_index); |
726 ASSERT(pc_ != 0); | 736 ASSERT(pc_ != 0); |
727 breakpoint_kind_ = desc.DescriptorKind(pc_desc_index); | 737 breakpoint_kind_ = desc.DescriptorKind(pc_desc_index); |
728 ASSERT(IsSafeDescKind(breakpoint_kind_)); | 738 ASSERT(IsSafeDescKind(breakpoint_kind_)); |
729 } | 739 } |
730 | 740 |
731 | 741 |
732 CodeBreakpoint::~CodeBreakpoint() { | 742 CodeBreakpoint::~CodeBreakpoint() { |
733 // Make sure we don't leave patched code behind. | 743 // Make sure we don't leave patched code behind. |
734 ASSERT(!IsEnabled()); | 744 ASSERT(!IsEnabled()); |
735 // Poison the data so we catch use after free errors. | 745 // Poison the data so we catch use after free errors. |
736 #ifdef DEBUG | 746 #ifdef DEBUG |
737 function_ = Function::null(); | 747 code_ = Code::null(); |
738 pc_ = 0ul; | 748 pc_ = 0ul; |
739 src_bpt_ = NULL; | 749 src_bpt_ = NULL; |
740 next_ = NULL; | 750 next_ = NULL; |
741 breakpoint_kind_ = PcDescriptors::kOther; | 751 breakpoint_kind_ = PcDescriptors::kOther; |
742 #endif | 752 #endif |
743 } | 753 } |
744 | 754 |
745 | 755 |
| 756 RawFunction* CodeBreakpoint::function() const { |
| 757 return Code::Handle(code_).function(); |
| 758 } |
| 759 |
| 760 |
746 RawScript* CodeBreakpoint::SourceCode() { | 761 RawScript* CodeBreakpoint::SourceCode() { |
747 const Function& func = Function::Handle(function_); | 762 const Function& func = Function::Handle(this->function()); |
748 return func.script(); | 763 return func.script(); |
749 } | 764 } |
750 | 765 |
751 | 766 |
752 RawString* CodeBreakpoint::SourceUrl() { | 767 RawString* CodeBreakpoint::SourceUrl() { |
753 const Script& script = Script::Handle(SourceCode()); | 768 const Script& script = Script::Handle(SourceCode()); |
754 return script.url(); | 769 return script.url(); |
755 } | 770 } |
756 | 771 |
757 | 772 |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
957 return; | 972 return; |
958 } | 973 } |
959 if (!target_function.HasCode()) { | 974 if (!target_function.HasCode()) { |
960 Compiler::CompileFunction(target_function); | 975 Compiler::CompileFunction(target_function); |
961 // If there were any errors, ignore them silently and return without | 976 // If there were any errors, ignore them silently and return without |
962 // adding breakpoints to target. | 977 // adding breakpoints to target. |
963 if (!target_function.HasCode()) { | 978 if (!target_function.HasCode()) { |
964 return; | 979 return; |
965 } | 980 } |
966 } | 981 } |
| 982 // Hang on to the code object before deoptimizing, in case deoptimization |
| 983 // might cause the GC to run. |
| 984 Code& code = Code::Handle(target_function.unoptimized_code()); |
| 985 ASSERT(!code.IsNull()); |
967 DeoptimizeWorld(); | 986 DeoptimizeWorld(); |
968 ASSERT(!target_function.HasOptimizedCode()); | 987 ASSERT(!target_function.HasOptimizedCode()); |
969 Code& code = Code::Handle(target_function.unoptimized_code()); | |
970 ASSERT(!code.IsNull()); | |
971 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 988 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
972 for (intptr_t i = 0; i < desc.Length(); i++) { | 989 for (intptr_t i = 0; i < desc.Length(); i++) { |
973 if (IsSafePoint(desc, i)) { | 990 if (IsSafePoint(desc, i)) { |
974 CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(i)); | 991 CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(i)); |
975 if (bpt != NULL) { | 992 if (bpt != NULL) { |
976 // There is already a breakpoint for this address. Make sure | 993 // There is already a breakpoint for this address. Make sure |
977 // it is enabled. | 994 // it is enabled. |
978 bpt->Enable(); | 995 bpt->Enable(); |
979 continue; | 996 continue; |
980 } | 997 } |
981 bpt = new CodeBreakpoint(target_function, i); | 998 bpt = new CodeBreakpoint(code, i); |
982 RegisterCodeBreakpoint(bpt); | 999 RegisterCodeBreakpoint(bpt); |
983 bpt->Enable(); | 1000 bpt->Enable(); |
984 } | 1001 } |
985 } | 1002 } |
986 } | 1003 } |
987 | 1004 |
988 | 1005 |
989 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { | 1006 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { |
990 if (event_handler_ != NULL) { | 1007 if (event_handler_ != NULL) { |
991 DebuggerEvent event(kBreakpointResolved); | 1008 DebuggerEvent event(kBreakpointResolved); |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1299 ASSERT(!func.HasOptimizedCode()); | 1316 ASSERT(!func.HasOptimizedCode()); |
1300 Code& code = Code::Handle(func.unoptimized_code()); | 1317 Code& code = Code::Handle(func.unoptimized_code()); |
1301 ASSERT(!code.IsNull()); | 1318 ASSERT(!code.IsNull()); |
1302 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 1319 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
1303 for (intptr_t i = 0; i < desc.Length(); i++) { | 1320 for (intptr_t i = 0; i < desc.Length(); i++) { |
1304 intptr_t desc_token_pos = desc.TokenPos(i); | 1321 intptr_t desc_token_pos = desc.TokenPos(i); |
1305 if ((desc_token_pos == bpt->token_pos_) && IsSafePoint(desc, i)) { | 1322 if ((desc_token_pos == bpt->token_pos_) && IsSafePoint(desc, i)) { |
1306 CodeBreakpoint* code_bpt = GetCodeBreakpoint(desc.PC(i)); | 1323 CodeBreakpoint* code_bpt = GetCodeBreakpoint(desc.PC(i)); |
1307 if (code_bpt == NULL) { | 1324 if (code_bpt == NULL) { |
1308 // No code breakpoint for this code exists; create one. | 1325 // No code breakpoint for this code exists; create one. |
1309 code_bpt = new CodeBreakpoint(func, i); | 1326 code_bpt = new CodeBreakpoint(code, i); |
1310 RegisterCodeBreakpoint(code_bpt); | 1327 RegisterCodeBreakpoint(code_bpt); |
1311 } | 1328 } |
1312 code_bpt->set_src_bpt(bpt); | 1329 code_bpt->set_src_bpt(bpt); |
1313 if (bpt->IsEnabled()) { | 1330 if (bpt->IsEnabled()) { |
1314 code_bpt->Enable(); | 1331 code_bpt->Enable(); |
1315 } | 1332 } |
1316 } | 1333 } |
1317 } | 1334 } |
1318 } | 1335 } |
1319 | 1336 |
(...skipping 920 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2240 } | 2257 } |
2241 | 2258 |
2242 | 2259 |
2243 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 2260 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
2244 ASSERT(bpt->next() == NULL); | 2261 ASSERT(bpt->next() == NULL); |
2245 bpt->set_next(code_breakpoints_); | 2262 bpt->set_next(code_breakpoints_); |
2246 code_breakpoints_ = bpt; | 2263 code_breakpoints_ = bpt; |
2247 } | 2264 } |
2248 | 2265 |
2249 } // namespace dart | 2266 } // namespace dart |
OLD | NEW |