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 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
451 context_level_ = var_info.index(); | 451 context_level_ = var_info.index(); |
452 } | 452 } |
453 } | 453 } |
454 } | 454 } |
455 ASSERT(context_level_ >= 0); | 455 ASSERT(context_level_ >= 0); |
456 } | 456 } |
457 return context_level_; | 457 return context_level_; |
458 } | 458 } |
459 | 459 |
460 | 460 |
461 RawContext* ActivationFrame::GetSavedEntryContext() { | 461 // Get the saved current context of this activation. |
462 // Attempt to find a saved context. | |
463 GetVarDescriptors(); | |
464 intptr_t var_desc_len = var_descriptors_.Length(); | |
465 for (intptr_t i = 0; i < var_desc_len; i++) { | |
466 RawLocalVarDescriptors::VarInfo var_info; | |
467 var_descriptors_.GetInfo(i, &var_info); | |
468 const int8_t kind = var_info.kind(); | |
469 if (kind == RawLocalVarDescriptors::kSavedEntryContext) { | |
470 if (FLAG_trace_debugger_stacktrace) { | |
471 OS::PrintErr("\tFound saved entry ctx at index %d\n", var_info.index()); | |
472 } | |
473 return GetLocalContextVar(var_info.index()); | |
474 } | |
475 } | |
476 | |
477 // No saved context. Return the current context. | |
478 return ctx_.raw(); | |
479 } | |
480 | |
481 | |
482 // Get the saved context if the callee of this activation frame is a | |
483 // closure function. | |
484 RawContext* ActivationFrame::GetSavedCurrentContext() { | 462 RawContext* ActivationFrame::GetSavedCurrentContext() { |
485 GetVarDescriptors(); | 463 GetVarDescriptors(); |
486 intptr_t var_desc_len = var_descriptors_.Length(); | 464 intptr_t var_desc_len = var_descriptors_.Length(); |
487 for (intptr_t i = 0; i < var_desc_len; i++) { | 465 for (intptr_t i = 0; i < var_desc_len; i++) { |
488 RawLocalVarDescriptors::VarInfo var_info; | 466 RawLocalVarDescriptors::VarInfo var_info; |
489 var_descriptors_.GetInfo(i, &var_info); | 467 var_descriptors_.GetInfo(i, &var_info); |
490 const int8_t kind = var_info.kind(); | 468 const int8_t kind = var_info.kind(); |
491 if (kind == RawLocalVarDescriptors::kSavedCurrentContext) { | 469 if (kind == RawLocalVarDescriptors::kSavedCurrentContext) { |
492 if (FLAG_trace_debugger_stacktrace) { | 470 if (FLAG_trace_debugger_stacktrace) { |
493 OS::PrintErr("\tFound saved current ctx at index %d\n", | 471 OS::PrintErr("\tFound saved current ctx at index %d\n", |
494 var_info.index()); | 472 var_info.index()); |
495 } | 473 } |
496 return GetLocalContextVar(var_info.index()); | 474 ASSERT(Object::Handle(GetLocalVar(var_info.index())).IsContext()); |
475 return reinterpret_cast<RawContext*>(GetLocalVar(var_info.index())); | |
Vyacheslav Egorov (Google)
2014/10/30 15:05:35
We did not worry much in the previous code about H
Florian Schneider
2014/10/30 15:24:31
It's probably not performance critical here. I don
| |
497 } | 476 } |
498 } | 477 } |
499 UNREACHABLE(); | 478 UNREACHABLE(); |
500 return Context::null(); | 479 return Context::null(); |
501 } | 480 } |
502 | 481 |
503 | 482 |
504 const char* DebuggerEvent::EventTypeToCString(EventType type) { | 483 const char* DebuggerEvent::EventTypeToCString(EventType type) { |
505 switch (type) { | 484 switch (type) { |
506 case kBreakpointReached: | 485 case kBreakpointReached: |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
671 } | 650 } |
672 | 651 |
673 | 652 |
674 RawInstance* ActivationFrame::GetLocalInstanceVar(intptr_t slot_index) { | 653 RawInstance* ActivationFrame::GetLocalInstanceVar(intptr_t slot_index) { |
675 Instance& instance = Instance::Handle(); | 654 Instance& instance = Instance::Handle(); |
676 instance ^= GetLocalVar(slot_index); | 655 instance ^= GetLocalVar(slot_index); |
677 return instance.raw(); | 656 return instance.raw(); |
678 } | 657 } |
679 | 658 |
680 | 659 |
681 RawContext* ActivationFrame::GetLocalContextVar(intptr_t slot_index) { | |
682 Object& context = Object::Handle(GetLocalVar(slot_index)); | |
683 if (context.IsContext()) { | |
684 // We found a saved context. | |
685 return Context::Cast(context).raw(); | |
686 } else if (context.raw() == Symbols::OptimizedOut().raw()) { | |
687 // The optimizing compiler has eliminated the saved context. | |
688 return Context::null(); | |
689 } else { | |
690 UNREACHABLE(); | |
691 return Context::null(); | |
692 } | |
693 } | |
694 | |
695 | |
696 void ActivationFrame::PrintContextMismatchError( | 660 void ActivationFrame::PrintContextMismatchError( |
697 const String& var_name, | 661 const String& var_name, |
698 intptr_t ctx_slot, | 662 intptr_t ctx_slot, |
699 intptr_t frame_ctx_level, | 663 intptr_t frame_ctx_level, |
700 intptr_t var_ctx_level) { | 664 intptr_t var_ctx_level) { |
701 OS::PrintErr("-------------------------\n" | 665 OS::PrintErr("-------------------------\n" |
702 "Encountered context mismatch\n" | 666 "Encountered context mismatch\n" |
703 "\tvar name: %s\n" | 667 "\tvar name: %s\n" |
704 "\tctx_slot: %" Pd "\n" | 668 "\tctx_slot: %" Pd "\n" |
705 "\tframe_ctx_level: %" Pd "\n" | 669 "\tframe_ctx_level: %" Pd "\n" |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
754 ASSERT(token_pos != NULL); | 718 ASSERT(token_pos != NULL); |
755 *token_pos = var_info.begin_pos; | 719 *token_pos = var_info.begin_pos; |
756 ASSERT(end_pos != NULL); | 720 ASSERT(end_pos != NULL); |
757 *end_pos = var_info.end_pos; | 721 *end_pos = var_info.end_pos; |
758 ASSERT(value != NULL); | 722 ASSERT(value != NULL); |
759 const int8_t kind = var_info.kind(); | 723 const int8_t kind = var_info.kind(); |
760 if (kind == RawLocalVarDescriptors::kStackVar) { | 724 if (kind == RawLocalVarDescriptors::kStackVar) { |
761 *value = GetLocalInstanceVar(var_info.index()); | 725 *value = GetLocalInstanceVar(var_info.index()); |
762 } else { | 726 } else { |
763 ASSERT(kind == RawLocalVarDescriptors::kContextVar); | 727 ASSERT(kind == RawLocalVarDescriptors::kContextVar); |
764 if (ctx_.IsNull()) { | 728 ASSERT(!ctx_.IsNull()); |
765 // The context has been removed by the optimizing compiler. | |
766 // | |
767 // TODO(turnidge): This may be erroneous. Revisit. | |
768 *value = Symbols::OptimizedOut().raw(); | |
769 return; | |
770 } | |
771 | 729 |
772 // The context level at the PC/token index of this activation frame. | 730 // The context level at the PC/token index of this activation frame. |
773 intptr_t frame_ctx_level = ContextLevel(); | 731 intptr_t frame_ctx_level = ContextLevel(); |
774 | 732 |
775 // The context level of the variable. | 733 // The context level of the variable. |
776 intptr_t var_ctx_level = var_info.scope_id; | 734 intptr_t var_ctx_level = var_info.scope_id; |
777 intptr_t level_diff = frame_ctx_level - var_ctx_level; | 735 intptr_t level_diff = frame_ctx_level - var_ctx_level; |
778 intptr_t ctx_slot = var_info.index(); | 736 intptr_t ctx_slot = var_info.index(); |
779 if (level_diff == 0) { | 737 if (level_diff == 0) { |
780 if ((ctx_slot < 0) || | 738 if ((ctx_slot < 0) || |
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1227 InvokeEventHandler(&event); | 1185 InvokeEventHandler(&event); |
1228 } | 1186 } |
1229 } | 1187 } |
1230 | 1188 |
1231 | 1189 |
1232 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate, | 1190 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate, |
1233 uword pc, | 1191 uword pc, |
1234 StackFrame* frame, | 1192 StackFrame* frame, |
1235 const Code& code, | 1193 const Code& code, |
1236 const Array& deopt_frame, | 1194 const Array& deopt_frame, |
1237 intptr_t deopt_frame_offset, | 1195 intptr_t deopt_frame_offset) { |
1238 ActivationFrame* callee_activation, | |
1239 const Context& entry_ctx) { | |
1240 ASSERT(code.ContainsInstructionAt(pc)); | 1196 ASSERT(code.ContainsInstructionAt(pc)); |
1241 // We provide either a callee activation or an entry context. Not both. | |
1242 ASSERT(((callee_activation != NULL) && entry_ctx.IsNull()) || | |
1243 ((callee_activation == NULL) && !entry_ctx.IsNull())); | |
1244 ActivationFrame* activation = | 1197 ActivationFrame* activation = |
1245 new ActivationFrame(pc, frame->fp(), frame->sp(), code, | 1198 new ActivationFrame(pc, frame->fp(), frame->sp(), code, |
1246 deopt_frame, deopt_frame_offset); | 1199 deopt_frame, deopt_frame_offset); |
1247 | 1200 |
1248 // Is there a closure call at the current PC? | 1201 // Is there a closure call at the current PC? |
1249 // | |
1250 // We can't just check the callee_activation to see if it is a | |
1251 // closure function, because it may not be on the stack yet. | |
1252 bool is_closure_call = false; | 1202 bool is_closure_call = false; |
1253 const PcDescriptors& pc_desc = | 1203 const PcDescriptors& pc_desc = |
1254 PcDescriptors::Handle(isolate, code.pc_descriptors()); | 1204 PcDescriptors::Handle(isolate, code.pc_descriptors()); |
1255 PcDescriptors::Iterator iter(pc_desc, RawPcDescriptors::kClosureCall); | 1205 PcDescriptors::Iterator iter(pc_desc, RawPcDescriptors::kClosureCall); |
1256 while (iter.MoveNext()) { | 1206 while (iter.MoveNext()) { |
1257 if (iter.Pc() == pc) { | 1207 if (iter.Pc() == pc) { |
1258 is_closure_call = true; | 1208 is_closure_call = true; |
1259 break; | 1209 break; |
1260 } | 1210 } |
1261 } | 1211 } |
1262 | 1212 |
1263 // Recover the context for this frame. | 1213 // Recover the context for this frame. |
1264 if (is_closure_call) { | 1214 if (is_closure_call) { |
1265 // If the callee is a closure, we should have stored the context | 1215 // If the callee is a closure, we should have stored the context |
1266 // in the current frame before making the call. | 1216 // in the current frame before making the call. |
1267 const Context& closure_call_ctx = | 1217 const Context& closure_call_ctx = |
1268 Context::Handle(isolate, activation->GetSavedCurrentContext()); | 1218 Context::Handle(isolate, activation->GetSavedCurrentContext()); |
1269 ASSERT(!closure_call_ctx.IsNull()); | 1219 ASSERT(!closure_call_ctx.IsNull()); |
1270 activation->SetContext(closure_call_ctx); | 1220 activation->SetContext(closure_call_ctx); |
1271 if (FLAG_trace_debugger_stacktrace) { | 1221 if (FLAG_trace_debugger_stacktrace) { |
1272 OS::PrintErr("\tUsing closure call ctx: %s\n", | 1222 OS::PrintErr("\tUsing closure call ctx: %s\n", |
1273 closure_call_ctx.ToCString()); | 1223 closure_call_ctx.ToCString()); |
1274 } | 1224 } |
1275 } else if (callee_activation == NULL) { | 1225 } else { |
1276 // No callee available. Use incoming entry context. Could be from | 1226 const Context& ctx = |
1277 // isolate's top context or from an entry frame. | 1227 Context::Handle(isolate, activation->GetSavedCurrentContext()); |
1278 ASSERT(!entry_ctx.IsNull()); | 1228 ASSERT(!ctx.IsNull()); |
1279 activation->SetContext(entry_ctx); | 1229 activation->SetContext(ctx); |
1280 if (FLAG_trace_debugger_stacktrace) { | 1230 if (FLAG_trace_debugger_stacktrace) { |
1281 OS::PrintErr("\tUsing entry ctx: %s\n", entry_ctx.ToCString()); | 1231 OS::PrintErr("\tUsing entry ctx: %s\n", ctx.ToCString()); |
1282 } | |
1283 } else { | |
1284 // Use the context provided by our callee. This is either the | |
1285 // callee's context or a context that was saved in the callee's | |
1286 // frame. | |
1287 // | |
1288 // The callee's saved context may be NULL if it was eliminated by | |
1289 // the optimizing compiler. | |
1290 const Context& callee_ctx = | |
1291 Context::Handle(isolate, callee_activation->GetSavedEntryContext()); | |
1292 activation->SetContext(callee_ctx); | |
1293 if (FLAG_trace_debugger_stacktrace) { | |
1294 OS::PrintErr("\tUsing callee call ctx: %s\n", | |
1295 callee_ctx.ToCString()); | |
1296 } | 1232 } |
1297 } | 1233 } |
1298 if (FLAG_trace_debugger_stacktrace) { | 1234 if (FLAG_trace_debugger_stacktrace) { |
1299 OS::PrintErr("\tLine number: %" Pd "\n", activation->LineNumber()); | 1235 OS::PrintErr("\tLine number: %" Pd "\n", activation->LineNumber()); |
1300 } | 1236 } |
1301 return activation; | 1237 return activation; |
1302 } | 1238 } |
1303 | 1239 |
1304 | 1240 |
1305 RawArray* Debugger::DeoptimizeToArray(Isolate* isolate, | 1241 RawArray* Debugger::DeoptimizeToArray(Isolate* isolate, |
(...skipping 17 matching lines...) Expand all Loading... | |
1323 delete deopt_context; | 1259 delete deopt_context; |
1324 | 1260 |
1325 return dest_frame.raw(); | 1261 return dest_frame.raw(); |
1326 } | 1262 } |
1327 | 1263 |
1328 | 1264 |
1329 DebuggerStackTrace* Debugger::CollectStackTrace() { | 1265 DebuggerStackTrace* Debugger::CollectStackTrace() { |
1330 Isolate* isolate = Isolate::Current(); | 1266 Isolate* isolate = Isolate::Current(); |
1331 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8); | 1267 DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8); |
1332 StackFrameIterator iterator(false); | 1268 StackFrameIterator iterator(false); |
1333 ActivationFrame* current_activation = NULL; | |
1334 Context& entry_ctx = Context::Handle(isolate, isolate->top_context()); | |
1335 Code& code = Code::Handle(isolate); | 1269 Code& code = Code::Handle(isolate); |
1336 Code& inlined_code = Code::Handle(isolate); | 1270 Code& inlined_code = Code::Handle(isolate); |
1337 Array& deopt_frame = Array::Handle(isolate); | 1271 Array& deopt_frame = Array::Handle(isolate); |
1338 | 1272 |
1339 for (StackFrame* frame = iterator.NextFrame(); | 1273 for (StackFrame* frame = iterator.NextFrame(); |
1340 frame != NULL; | 1274 frame != NULL; |
1341 frame = iterator.NextFrame()) { | 1275 frame = iterator.NextFrame()) { |
1342 ASSERT(frame->IsValid()); | 1276 ASSERT(frame->IsValid()); |
1343 if (FLAG_trace_debugger_stacktrace) { | 1277 if (FLAG_trace_debugger_stacktrace) { |
1344 OS::PrintErr("CollectStackTrace: visiting frame:\n\t%s\n", | 1278 OS::PrintErr("CollectStackTrace: visiting frame:\n\t%s\n", |
1345 frame->ToCString()); | 1279 frame->ToCString()); |
1346 } | 1280 } |
1347 if (frame->IsEntryFrame()) { | 1281 if (frame->IsDartFrame()) { |
1348 current_activation = NULL; | |
1349 entry_ctx = reinterpret_cast<EntryFrame*>(frame)->SavedContext(); | |
1350 if (FLAG_trace_debugger_stacktrace) { | |
1351 OS::PrintErr("\tFound saved ctx in entry frame:\n\t%s\n", | |
1352 entry_ctx.ToCString()); | |
1353 } | |
1354 | |
1355 } else if (frame->IsDartFrame()) { | |
1356 code = frame->LookupDartCode(); | 1282 code = frame->LookupDartCode(); |
1357 if (code.is_optimized()) { | 1283 if (code.is_optimized()) { |
1358 deopt_frame = DeoptimizeToArray(isolate, frame, code); | 1284 deopt_frame = DeoptimizeToArray(isolate, frame, code); |
1359 for (InlinedFunctionsIterator it(code, frame->pc()); | 1285 for (InlinedFunctionsIterator it(code, frame->pc()); |
1360 !it.Done(); | 1286 !it.Done(); |
1361 it.Advance()) { | 1287 it.Advance()) { |
1362 inlined_code = it.code(); | 1288 inlined_code = it.code(); |
1363 if (FLAG_trace_debugger_stacktrace) { | 1289 if (FLAG_trace_debugger_stacktrace) { |
1364 const Function& function = | 1290 const Function& function = |
1365 Function::Handle(isolate, inlined_code.function()); | 1291 Function::Handle(isolate, inlined_code.function()); |
1366 ASSERT(!function.IsNull()); | 1292 ASSERT(!function.IsNull()); |
1367 OS::PrintErr("CollectStackTrace: visiting inlined function: %s\n", | 1293 OS::PrintErr("CollectStackTrace: visiting inlined function: %s\n", |
1368 function.ToFullyQualifiedCString()); | 1294 function.ToFullyQualifiedCString()); |
1369 } | 1295 } |
1370 intptr_t deopt_frame_offset = it.GetDeoptFpOffset(); | 1296 intptr_t deopt_frame_offset = it.GetDeoptFpOffset(); |
1371 current_activation = CollectDartFrame(isolate, | 1297 stack_trace->AddActivation(CollectDartFrame(isolate, |
1372 it.pc(), | 1298 it.pc(), |
1373 frame, | 1299 frame, |
1374 inlined_code, | 1300 inlined_code, |
1375 deopt_frame, | 1301 deopt_frame, |
1376 deopt_frame_offset, | 1302 deopt_frame_offset)); |
1377 current_activation, | |
1378 entry_ctx); | |
1379 stack_trace->AddActivation(current_activation); | |
1380 entry_ctx = Context::null(); // Only use entry context once. | |
1381 } | 1303 } |
1382 } else { | 1304 } else { |
1383 current_activation = CollectDartFrame(isolate, | 1305 stack_trace->AddActivation(CollectDartFrame(isolate, |
1384 frame->pc(), | 1306 frame->pc(), |
1385 frame, | 1307 frame, |
1386 code, | 1308 code, |
1387 Object::null_array(), | 1309 Object::null_array(), |
1388 0, | 1310 0)); |
1389 current_activation, | |
1390 entry_ctx); | |
1391 stack_trace->AddActivation(current_activation); | |
1392 entry_ctx = Context::null(); // Only use entry context once. | |
1393 } | 1311 } |
1394 } | 1312 } |
1395 } | 1313 } |
1396 return stack_trace; | 1314 return stack_trace; |
1397 } | 1315 } |
1398 | 1316 |
1399 | 1317 |
1400 ActivationFrame* Debugger::TopDartFrame() const { | 1318 ActivationFrame* Debugger::TopDartFrame() const { |
1401 StackFrameIterator iterator(false); | 1319 StackFrameIterator iterator(false); |
1402 StackFrame* frame = iterator.NextFrame(); | 1320 StackFrame* frame = iterator.NextFrame(); |
(...skipping 1189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2592 } | 2510 } |
2593 | 2511 |
2594 | 2512 |
2595 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 2513 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
2596 ASSERT(bpt->next() == NULL); | 2514 ASSERT(bpt->next() == NULL); |
2597 bpt->set_next(code_breakpoints_); | 2515 bpt->set_next(code_breakpoints_); |
2598 code_breakpoints_ = bpt; | 2516 code_breakpoints_ = bpt; |
2599 } | 2517 } |
2600 | 2518 |
2601 } // namespace dart | 2519 } // namespace dart |
OLD | NEW |