Chromium Code Reviews| 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 |