Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(587)

Side by Side Diff: runtime/vm/debugger.cc

Issue 2521413002: Revert "Implement rewind: drop one or more frames from the debugger." (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/debugger_api_impl.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "platform/address_sanitizer.h"
10
11 #include "vm/code_generator.h" 9 #include "vm/code_generator.h"
12 #include "vm/code_patcher.h" 10 #include "vm/code_patcher.h"
13 #include "vm/compiler.h" 11 #include "vm/compiler.h"
14 #include "vm/dart_entry.h" 12 #include "vm/dart_entry.h"
15 #include "vm/deopt_instructions.h" 13 #include "vm/deopt_instructions.h"
16 #include "vm/flags.h" 14 #include "vm/flags.h"
17 #include "vm/globals.h" 15 #include "vm/globals.h"
18 #include "vm/longjump.h" 16 #include "vm/longjump.h"
19 #include "vm/json_stream.h" 17 #include "vm/json_stream.h"
20 #include "vm/message_handler.h" 18 #include "vm/message_handler.h"
(...skipping 16 matching lines...) Expand all
37 namespace dart { 35 namespace dart {
38 36
39 DEFINE_FLAG(bool, 37 DEFINE_FLAG(bool,
40 show_invisible_frames, 38 show_invisible_frames,
41 false, 39 false,
42 "Show invisible frames in debugger stack traces"); 40 "Show invisible frames in debugger stack traces");
43 DEFINE_FLAG(bool, 41 DEFINE_FLAG(bool,
44 trace_debugger_stacktrace, 42 trace_debugger_stacktrace,
45 false, 43 false,
46 "Trace debugger stacktrace collection"); 44 "Trace debugger stacktrace collection");
47 DEFINE_FLAG(bool, trace_rewind, false, "Trace frame rewind");
48 DEFINE_FLAG(bool, verbose_debug, false, "Verbose debugger messages"); 45 DEFINE_FLAG(bool, verbose_debug, false, "Verbose debugger messages");
49 DEFINE_FLAG(bool, 46 DEFINE_FLAG(bool,
50 steal_breakpoints, 47 steal_breakpoints,
51 false, 48 false,
52 "Intercept breakpoints and other pause events before they " 49 "Intercept breakpoints and other pause events before they "
53 "are sent to the embedder and use a generic VM breakpoint " 50 "are sent to the embedder and use a generic VM breakpoint "
54 "handler instead. This handler dispatches breakpoints to " 51 "handler instead. This handler dispatches breakpoints to "
55 "the VM service."); 52 "the VM service.");
56 53
57 DECLARE_FLAG(bool, warn_on_pause_with_no_debugger); 54 DECLARE_FLAG(bool, warn_on_pause_with_no_debugger);
(...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after
846 843
847 RawObject* ActivationFrame::GetStackVar(intptr_t slot_index) { 844 RawObject* ActivationFrame::GetStackVar(intptr_t slot_index) {
848 if (deopt_frame_.IsNull()) { 845 if (deopt_frame_.IsNull()) {
849 return GetVariableValue(LocalVarAddress(fp(), slot_index)); 846 return GetVariableValue(LocalVarAddress(fp(), slot_index));
850 } else { 847 } else {
851 return deopt_frame_.At(LocalVarIndex(deopt_frame_offset_, slot_index)); 848 return deopt_frame_.At(LocalVarIndex(deopt_frame_offset_, slot_index));
852 } 849 }
853 } 850 }
854 851
855 852
856 bool ActivationFrame::IsRewindable() const {
857 if (deopt_frame_.IsNull()) {
858 return true;
859 }
860 // TODO(turnidge): This is conservative. It looks at all values in
861 // the deopt_frame_ even though some of them may correspond to other
862 // inlined frames.
863 Object& obj = Object::Handle();
864 for (int i = 0; i < deopt_frame_.Length(); i++) {
865 obj = deopt_frame_.At(i);
866 if (obj.raw() == Symbols::OptimizedOut().raw()) {
867 return false;
868 }
869 }
870 return true;
871 }
872
873
874 void ActivationFrame::PrintContextMismatchError(intptr_t ctx_slot, 853 void ActivationFrame::PrintContextMismatchError(intptr_t ctx_slot,
875 intptr_t frame_ctx_level, 854 intptr_t frame_ctx_level,
876 intptr_t var_ctx_level) { 855 intptr_t var_ctx_level) {
877 OS::PrintErr( 856 OS::PrintErr(
878 "-------------------------\n" 857 "-------------------------\n"
879 "Encountered context mismatch\n" 858 "Encountered context mismatch\n"
880 "\tctx_slot: %" Pd 859 "\tctx_slot: %" Pd
881 "\n" 860 "\n"
882 "\tframe_ctx_level: %" Pd 861 "\tframe_ctx_level: %" Pd
883 "\n" 862 "\n"
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
1122 jsvar.AddProperty("declarationTokenPos", declaration_token_pos); 1101 jsvar.AddProperty("declarationTokenPos", declaration_token_pos);
1123 // When the variable becomes visible to the scope. 1102 // When the variable becomes visible to the scope.
1124 jsvar.AddProperty("scopeStartTokenPos", visible_start_token_pos); 1103 jsvar.AddProperty("scopeStartTokenPos", visible_start_token_pos);
1125 // When the variable stops being visible to the scope. 1104 // When the variable stops being visible to the scope.
1126 jsvar.AddProperty("scopeEndTokenPos", visible_end_token_pos); 1105 jsvar.AddProperty("scopeEndTokenPos", visible_end_token_pos);
1127 } 1106 }
1128 } 1107 }
1129 } 1108 }
1130 } 1109 }
1131 1110
1132 static bool IsFunctionVisible(const Function& function) {
1133 return FLAG_show_invisible_frames || function.is_visible();
1134 }
1135
1136 1111
1137 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) { 1112 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) {
1138 if (IsFunctionVisible(frame->function())) { 1113 if (FLAG_show_invisible_frames || frame->function().is_visible()) {
1139 trace_.Add(frame); 1114 trace_.Add(frame);
1140 } 1115 }
1141 } 1116 }
1142 1117
1143 1118
1144 const uint8_t kSafepointKind = RawPcDescriptors::kIcCall | 1119 const uint8_t kSafepointKind = RawPcDescriptors::kIcCall |
1145 RawPcDescriptors::kUnoptStaticCall | 1120 RawPcDescriptors::kUnoptStaticCall |
1146 RawPcDescriptors::kRuntimeCall; 1121 RawPcDescriptors::kRuntimeCall;
1147 1122
1148 1123
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1255 1230
1256 Debugger::Debugger() 1231 Debugger::Debugger()
1257 : isolate_(NULL), 1232 : isolate_(NULL),
1258 isolate_id_(ILLEGAL_ISOLATE_ID), 1233 isolate_id_(ILLEGAL_ISOLATE_ID),
1259 initialized_(false), 1234 initialized_(false),
1260 next_id_(1), 1235 next_id_(1),
1261 latent_locations_(NULL), 1236 latent_locations_(NULL),
1262 breakpoint_locations_(NULL), 1237 breakpoint_locations_(NULL),
1263 code_breakpoints_(NULL), 1238 code_breakpoints_(NULL),
1264 resume_action_(kContinue), 1239 resume_action_(kContinue),
1265 resume_frame_index_(-1),
1266 post_deopt_frame_index_(-1),
1267 ignore_breakpoints_(false), 1240 ignore_breakpoints_(false),
1268 pause_event_(NULL), 1241 pause_event_(NULL),
1269 obj_cache_(NULL), 1242 obj_cache_(NULL),
1270 stack_trace_(NULL), 1243 stack_trace_(NULL),
1271 stepping_fp_(0), 1244 stepping_fp_(0),
1272 skip_next_step_(false), 1245 skip_next_step_(false),
1273 synthetic_async_breakpoint_(NULL), 1246 synthetic_async_breakpoint_(NULL),
1274 exc_pause_info_(kNoPauseOnExceptions) {} 1247 exc_pause_info_(kNoPauseOnExceptions) {}
1275 1248
1276 1249
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1320 const String& fname) { 1293 const String& fname) {
1321 ASSERT(!library.IsNull()); 1294 ASSERT(!library.IsNull());
1322 const Object& object = Object::Handle(library.ResolveName(fname)); 1295 const Object& object = Object::Handle(library.ResolveName(fname));
1323 if (!object.IsNull() && object.IsFunction()) { 1296 if (!object.IsNull() && object.IsFunction()) {
1324 return Function::Cast(object).raw(); 1297 return Function::Cast(object).raw();
1325 } 1298 }
1326 return Function::null(); 1299 return Function::null();
1327 } 1300 }
1328 1301
1329 1302
1330 bool Debugger::SetupStepOverAsyncSuspension(const char** error) { 1303 bool Debugger::SetupStepOverAsyncSuspension() {
1331 ActivationFrame* top_frame = TopDartFrame(); 1304 ActivationFrame* top_frame = TopDartFrame();
1332 if (!IsAtAsyncJump(top_frame)) { 1305 if (!IsAtAsyncJump(top_frame)) {
1333 // Not at an async operation. 1306 // Not at an async operation.
1334 if (error) {
1335 *error = "Isolate must be paused at an async suspension point";
1336 }
1337 return false; 1307 return false;
1338 } 1308 }
1339 Object& closure = Object::Handle(top_frame->GetAsyncOperation()); 1309 Object& closure = Object::Handle(top_frame->GetAsyncOperation());
1340 ASSERT(!closure.IsNull()); 1310 ASSERT(!closure.IsNull());
1341 ASSERT(closure.IsInstance()); 1311 ASSERT(closure.IsInstance());
1342 ASSERT(Instance::Cast(closure).IsClosure()); 1312 ASSERT(Instance::Cast(closure).IsClosure());
1343 Breakpoint* bpt = SetBreakpointAtActivation(Instance::Cast(closure), true); 1313 Breakpoint* bpt = SetBreakpointAtActivation(Instance::Cast(closure), true);
1344 if (bpt == NULL) { 1314 if (bpt == NULL) {
1345 // Unable to set the breakpoint. 1315 // Unable to set the breakpoint.
1346 if (error) {
1347 *error = "Unable to set breakpoint at async suspension point";
1348 }
1349 return false; 1316 return false;
1350 } 1317 }
1351 return true; 1318 return true;
1352 } 1319 }
1353 1320
1354 1321
1355 bool Debugger::SetResumeAction(ResumeAction action, 1322 void Debugger::SetSingleStep() {
1356 intptr_t frame_index, 1323 resume_action_ = kSingleStep;
1357 const char** error) {
1358 if (error) {
1359 *error = NULL;
1360 }
1361 resume_frame_index_ = -1;
1362 switch (action) {
1363 case kStepInto:
1364 case kStepOver:
1365 case kStepOut:
1366 case kContinue:
1367 resume_action_ = action;
1368 return true;
1369 case kStepRewind:
1370 if (!CanRewindFrame(frame_index, error)) {
1371 return false;
1372 }
1373 resume_action_ = kStepRewind;
1374 resume_frame_index_ = frame_index;
1375 return true;
1376 case kStepOverAsyncSuspension:
1377 return SetupStepOverAsyncSuspension(error);
1378 default:
1379 UNREACHABLE();
1380 return false;
1381 }
1382 } 1324 }
1383 1325
1384 1326
1327 void Debugger::SetStepOver() {
1328 resume_action_ = kStepOver;
1329 }
1330
1331
1332 void Debugger::SetStepOut() {
1333 resume_action_ = kStepOut;
1334 }
1335
1336
1385 RawFunction* Debugger::ResolveFunction(const Library& library, 1337 RawFunction* Debugger::ResolveFunction(const Library& library,
1386 const String& class_name, 1338 const String& class_name,
1387 const String& function_name) { 1339 const String& function_name) {
1388 ASSERT(!library.IsNull()); 1340 ASSERT(!library.IsNull());
1389 ASSERT(!class_name.IsNull()); 1341 ASSERT(!class_name.IsNull());
1390 ASSERT(!function_name.IsNull()); 1342 ASSERT(!function_name.IsNull());
1391 if (class_name.Length() == 0) { 1343 if (class_name.Length() == 0) {
1392 return ResolveLibraryFunction(library, function_name); 1344 return ResolveLibraryFunction(library, function_name);
1393 } 1345 }
1394 const Class& cls = Class::Handle(library.LookupClass(class_name)); 1346 const Class& cls = Class::Handle(library.LookupClass(class_name));
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
1663 return; 1615 return;
1664 } 1616 }
1665 ServiceEvent event(isolate_, ServiceEvent::kPauseException); 1617 ServiceEvent event(isolate_, ServiceEvent::kPauseException);
1666 event.set_exception(&exc); 1618 event.set_exception(&exc);
1667 if (stack_trace->Length() > 0) { 1619 if (stack_trace->Length() > 0) {
1668 event.set_top_frame(stack_trace->FrameAt(0)); 1620 event.set_top_frame(stack_trace->FrameAt(0));
1669 } 1621 }
1670 ASSERT(stack_trace_ == NULL); 1622 ASSERT(stack_trace_ == NULL);
1671 stack_trace_ = stack_trace; 1623 stack_trace_ = stack_trace;
1672 Pause(&event); 1624 Pause(&event);
1673 HandleSteppingRequest(stack_trace_); // we may get a rewind request
1674 stack_trace_ = NULL; 1625 stack_trace_ = NULL;
1675 } 1626 }
1676 1627
1677 1628
1678 static TokenPosition LastTokenOnLine(Zone* zone, 1629 static TokenPosition LastTokenOnLine(Zone* zone,
1679 const TokenStream& tokens, 1630 const TokenStream& tokens,
1680 TokenPosition pos) { 1631 TokenPosition pos) {
1681 TokenStream::Iterator iter(zone, tokens, pos, 1632 TokenStream::Iterator iter(zone, tokens, pos,
1682 TokenStream::Iterator::kAllTokens); 1633 TokenStream::Iterator::kAllTokens);
1683 ASSERT(iter.IsValid()); 1634 ASSERT(iter.IsValid());
(...skipping 905 matching lines...) Expand 10 before | Expand all | Expand 10 after
2589 void Debugger::EnterSingleStepMode() { 2540 void Debugger::EnterSingleStepMode() {
2590 stepping_fp_ = 0; 2541 stepping_fp_ = 0;
2591 DeoptimizeWorld(); 2542 DeoptimizeWorld();
2592 isolate_->set_single_step(true); 2543 isolate_->set_single_step(true);
2593 } 2544 }
2594 2545
2595 2546
2596 void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace, 2547 void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace,
2597 bool skip_next_step) { 2548 bool skip_next_step) {
2598 stepping_fp_ = 0; 2549 stepping_fp_ = 0;
2599 if (resume_action_ == kStepInto) { 2550 if (resume_action_ == kSingleStep) {
2600 // When single stepping, we need to deoptimize because we might be 2551 // When single stepping, we need to deoptimize because we might be
2601 // stepping into optimized code. This happens in particular if 2552 // stepping into optimized code. This happens in particular if
2602 // the isolate has been interrupted, but can happen in other cases 2553 // the isolate has been interrupted, but can happen in other cases
2603 // as well. We need to deoptimize the world in case we are about 2554 // as well. We need to deoptimize the world in case we are about
2604 // to call an optimized function. 2555 // to call an optimized function.
2605 DeoptimizeWorld(); 2556 DeoptimizeWorld();
2606 isolate_->set_single_step(true); 2557 isolate_->set_single_step(true);
2607 skip_next_step_ = skip_next_step; 2558 skip_next_step_ = skip_next_step;
2608 if (FLAG_verbose_debug) { 2559 if (FLAG_verbose_debug) {
2609 OS::Print("HandleSteppingRequest- kStepInto\n"); 2560 OS::Print("HandleSteppingRequest- kSingleStep\n");
2610 } 2561 }
2611 } else if (resume_action_ == kStepOver) { 2562 } else if (resume_action_ == kStepOver) {
2612 DeoptimizeWorld(); 2563 DeoptimizeWorld();
2613 isolate_->set_single_step(true); 2564 isolate_->set_single_step(true);
2614 skip_next_step_ = skip_next_step; 2565 skip_next_step_ = skip_next_step;
2615 ASSERT(stack_trace->Length() > 0); 2566 ASSERT(stack_trace->Length() > 0);
2616 stepping_fp_ = stack_trace->FrameAt(0)->fp(); 2567 stepping_fp_ = stack_trace->FrameAt(0)->fp();
2617 if (FLAG_verbose_debug) { 2568 if (FLAG_verbose_debug) {
2618 OS::Print("HandleSteppingRequest- kStepOver %" Px "\n", stepping_fp_); 2569 OS::Print("HandleSteppingRequest- kStepOver %" Px "\n", stepping_fp_);
2619 } 2570 }
2620 } else if (resume_action_ == kStepOut) { 2571 } else if (resume_action_ == kStepOut) {
2621 DeoptimizeWorld(); 2572 DeoptimizeWorld();
2622 isolate_->set_single_step(true); 2573 isolate_->set_single_step(true);
2623 // Find topmost caller that is debuggable. 2574 // Find topmost caller that is debuggable.
2624 for (intptr_t i = 1; i < stack_trace->Length(); i++) { 2575 for (intptr_t i = 1; i < stack_trace->Length(); i++) {
2625 ActivationFrame* frame = stack_trace->FrameAt(i); 2576 ActivationFrame* frame = stack_trace->FrameAt(i);
2626 if (frame->IsDebuggable()) { 2577 if (frame->IsDebuggable()) {
2627 stepping_fp_ = frame->fp(); 2578 stepping_fp_ = frame->fp();
2628 break; 2579 break;
2629 } 2580 }
2630 } 2581 }
2631 if (FLAG_verbose_debug) { 2582 if (FLAG_verbose_debug) {
2632 OS::Print("HandleSteppingRequest- kStepOut %" Px "\n", stepping_fp_); 2583 OS::Print("HandleSteppingRequest- kStepOut %" Px "\n", stepping_fp_);
2633 } 2584 }
2634 } else if (resume_action_ == kStepRewind) {
2635 if (FLAG_trace_rewind) {
2636 OS::PrintErr("Rewinding to frame %" Pd "\n", resume_frame_index_);
2637 OS::PrintErr(
2638 "-------------------------\n"
2639 "All frames...\n\n");
2640 StackFrameIterator iterator(false);
2641 StackFrame* frame = iterator.NextFrame();
2642 intptr_t num = 0;
2643 while ((frame != NULL)) {
2644 OS::PrintErr("#%04" Pd " %s\n", num++, frame->ToCString());
2645 frame = iterator.NextFrame();
2646 }
2647 }
2648 RewindToFrame(resume_frame_index_);
2649 UNREACHABLE();
2650 }
2651 }
2652
2653
2654 static intptr_t FindNextRewindFrameIndex(DebuggerStackTrace* stack,
2655 intptr_t frame_index) {
2656 for (intptr_t i = frame_index + 1; i < stack->Length(); i++) {
2657 ActivationFrame* frame = stack->FrameAt(i);
2658 if (frame->IsRewindable()) {
2659 return i;
2660 }
2661 }
2662 return -1;
2663 }
2664
2665
2666 // Can the top frame be rewound?
2667 bool Debugger::CanRewindFrame(intptr_t frame_index, const char** error) const {
2668 // check rewind pc is found
2669 DebuggerStackTrace* stack = Isolate::Current()->debugger()->StackTrace();
2670 intptr_t num_frames = stack->Length();
2671 if (frame_index < 1 || frame_index >= num_frames) {
2672 if (error) {
2673 *error = Thread::Current()->zone()->PrintToString(
2674 "Frame must be in bounds [1..%" Pd
2675 "]: "
2676 "saw %" Pd "",
2677 num_frames - 1, frame_index);
2678 }
2679 return false;
2680 }
2681 ActivationFrame* frame = stack->FrameAt(frame_index);
2682 if (!frame->IsRewindable()) {
2683 intptr_t next_index = FindNextRewindFrameIndex(stack, frame_index);
2684 if (next_index > 0) {
2685 *error = Thread::Current()->zone()->PrintToString(
2686 "Cannot rewind to frame %" Pd
2687 " due to conflicting compiler "
2688 "optimizations. "
2689 "Run the vm with --no-prune-dead-locals to disallow these "
2690 "optimizations. "
2691 "Next valid rewind frame is %" Pd ".",
2692 frame_index, next_index);
2693 } else {
2694 *error = Thread::Current()->zone()->PrintToString(
2695 "Cannot rewind to frame %" Pd
2696 " due to conflicting compiler "
2697 "optimizations. "
2698 "Run the vm with --no-prune-dead-locals to disallow these "
2699 "optimizations.",
2700 frame_index);
2701 }
2702 return false;
2703 }
2704 return true;
2705 }
2706
2707
2708 // Given a return address pc, find the "rewind" pc, which is the pc
2709 // before the corresponding call.
2710 static uword LookupRewindPc(const Code& code, uword pc) {
2711 ASSERT(!code.is_optimized());
2712 ASSERT(code.ContainsInstructionAt(pc));
2713
2714 uword pc_offset = pc - code.PayloadStart();
2715 const PcDescriptors& descriptors =
2716 PcDescriptors::Handle(code.pc_descriptors());
2717 PcDescriptors::Iterator iter(
2718 descriptors, RawPcDescriptors::kRewind | RawPcDescriptors::kIcCall |
2719 RawPcDescriptors::kUnoptStaticCall);
2720 intptr_t rewind_deopt_id = -1;
2721 uword rewind_pc = 0;
2722 while (iter.MoveNext()) {
2723 if (iter.Kind() == RawPcDescriptors::kRewind) {
2724 // Remember the last rewind so we don't need to iterator twice.
2725 rewind_pc = code.PayloadStart() + iter.PcOffset();
2726 rewind_deopt_id = iter.DeoptId();
2727 }
2728 if ((pc_offset == iter.PcOffset()) && (iter.DeoptId() == rewind_deopt_id)) {
2729 return rewind_pc;
2730 }
2731 }
2732 return 0;
2733 }
2734
2735
2736 void Debugger::RewindToFrame(intptr_t frame_index) {
2737 Thread* thread = Thread::Current();
2738 Zone* zone = thread->zone();
2739 Code& code = Code::Handle(zone);
2740 Function& function = Function::Handle(zone);
2741
2742 // Find the requested frame.
2743 StackFrameIterator iterator(false);
2744 intptr_t current_frame = 0;
2745 for (StackFrame* frame = iterator.NextFrame(); frame != NULL;
2746 frame = iterator.NextFrame()) {
2747 ASSERT(frame->IsValid());
2748 if (frame->IsDartFrame()) {
2749 code = frame->LookupDartCode();
2750 function = code.function();
2751 if (!IsFunctionVisible(function)) {
2752 continue;
2753 }
2754 if (code.is_optimized()) {
2755 intptr_t sub_index = 0;
2756 for (InlinedFunctionsIterator it(code, frame->pc()); !it.Done();
2757 it.Advance()) {
2758 if (current_frame == frame_index) {
2759 RewindToOptimizedFrame(frame, code, sub_index);
2760 UNREACHABLE();
2761 }
2762 current_frame++;
2763 sub_index++;
2764 }
2765 } else {
2766 if (current_frame == frame_index) {
2767 // We are rewinding to an unoptimized frame.
2768 RewindToUnoptimizedFrame(frame, code);
2769 UNREACHABLE();
2770 }
2771 current_frame++;
2772 }
2773 }
2774 }
2775 UNIMPLEMENTED();
2776 }
2777
2778
2779 void Debugger::RewindToUnoptimizedFrame(StackFrame* frame, const Code& code) {
2780 // We will be jumping out of the debugger rather than exiting this
2781 // function, so prepare the debugger state.
2782 stack_trace_ = NULL;
2783 resume_action_ = kContinue;
2784 resume_frame_index_ = -1;
2785 EnterSingleStepMode();
2786
2787 uword rewind_pc = LookupRewindPc(code, frame->pc());
2788 if (FLAG_trace_rewind && rewind_pc == 0) {
2789 OS::PrintErr("Unable to find rewind pc for pc(%" Px ")\n", frame->pc());
2790 }
2791 ASSERT(rewind_pc != 0);
2792 if (FLAG_trace_rewind) {
2793 OS::PrintErr(
2794 "===============================\n"
2795 "Rewinding to unoptimized frame:\n"
2796 " rewind_pc(0x%" Px ") sp(0x%" Px ") fp(0x%" Px
2797 ")\n"
2798 "===============================\n",
2799 rewind_pc, frame->sp(), frame->fp());
2800 }
2801 Exceptions::JumpToFrame(Thread::Current(), rewind_pc, frame->sp(),
2802 frame->fp(), true /* clear lazy deopt at target */);
2803 UNREACHABLE();
2804 }
2805
2806
2807 void Debugger::RewindToOptimizedFrame(StackFrame* frame,
2808 const Code& optimized_code,
2809 intptr_t sub_index) {
2810 post_deopt_frame_index_ = sub_index;
2811
2812 // We will be jumping out of the debugger rather than exiting this
2813 // function, so prepare the debugger state.
2814 stack_trace_ = NULL;
2815 resume_action_ = kContinue;
2816 resume_frame_index_ = -1;
2817 EnterSingleStepMode();
2818
2819 if (FLAG_trace_rewind) {
2820 OS::PrintErr(
2821 "===============================\n"
2822 "Deoptimizing frame for rewind:\n"
2823 " deopt_pc(0x%" Px ") sp(0x%" Px ") fp(0x%" Px
2824 ")\n"
2825 "===============================\n",
2826 frame->pc(), frame->sp(), frame->fp());
2827 }
2828 Thread* thread = Thread::Current();
2829 thread->set_resume_pc(frame->pc());
2830 uword deopt_stub_pc = StubCode::DeoptForRewind_entry()->EntryPoint();
2831 Exceptions::JumpToFrame(thread, deopt_stub_pc, frame->sp(), frame->fp(),
2832 true /* clear lazy deopt at target */);
2833 UNREACHABLE();
2834 }
2835
2836
2837 void Debugger::RewindPostDeopt() {
2838 intptr_t rewind_frame = post_deopt_frame_index_;
2839 post_deopt_frame_index_ = -1;
2840 if (FLAG_trace_rewind) {
2841 OS::PrintErr("Post deopt, jumping to frame %" Pd "\n", rewind_frame);
2842 OS::PrintErr(
2843 "-------------------------\n"
2844 "All frames...\n\n");
2845 StackFrameIterator iterator(false);
2846 StackFrame* frame = iterator.NextFrame();
2847 intptr_t num = 0;
2848 while ((frame != NULL)) {
2849 OS::PrintErr("#%04" Pd " %s\n", num++, frame->ToCString());
2850 frame = iterator.NextFrame();
2851 }
2852 }
2853
2854 Thread* thread = Thread::Current();
2855 Zone* zone = thread->zone();
2856 Code& code = Code::Handle(zone);
2857
2858 StackFrameIterator iterator(false);
2859 intptr_t current_frame = 0;
2860 for (StackFrame* frame = iterator.NextFrame(); frame != NULL;
2861 frame = iterator.NextFrame()) {
2862 ASSERT(frame->IsValid());
2863 if (frame->IsDartFrame()) {
2864 code = frame->LookupDartCode();
2865 ASSERT(!code.is_optimized());
2866 if (current_frame == rewind_frame) {
2867 RewindToUnoptimizedFrame(frame, code);
2868 UNREACHABLE();
2869 }
2870 current_frame++;
2871 }
2872 } 2585 }
2873 } 2586 }
2874 2587
2875 2588
2876 // static 2589 // static
2877 bool Debugger::IsDebuggable(const Function& func) { 2590 bool Debugger::IsDebuggable(const Function& func) {
2878 if (!func.is_debuggable()) { 2591 if (!func.is_debuggable()) {
2879 return false; 2592 return false;
2880 } 2593 }
2881 const Class& cls = Class::Handle(func.Owner()); 2594 const Class& cls = Class::Handle(func.Owner());
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
3073 cbpt->LineNumber(), cbpt->token_pos().ToCString(), 2786 cbpt->LineNumber(), cbpt->token_pos().ToCString(),
3074 top_frame->pc()); 2787 top_frame->pc());
3075 } 2788 }
3076 2789
3077 ASSERT(synthetic_async_breakpoint_ == NULL); 2790 ASSERT(synthetic_async_breakpoint_ == NULL);
3078 synthetic_async_breakpoint_ = bpt_hit; 2791 synthetic_async_breakpoint_ = bpt_hit;
3079 bpt_hit = NULL; 2792 bpt_hit = NULL;
3080 2793
3081 // We are at the entry of an async function. 2794 // We are at the entry of an async function.
3082 // We issue a step over to resume at the point after the await statement. 2795 // We issue a step over to resume at the point after the await statement.
3083 SetResumeAction(kStepOver); 2796 SetStepOver();
3084 // When we single step from a user breakpoint, our next stepping 2797 // When we single step from a user breakpoint, our next stepping
3085 // point will be at the exact same pc. Skip it. 2798 // point will be at the exact same pc. Skip it.
3086 HandleSteppingRequest(stack_trace_, true /* skip next step */); 2799 HandleSteppingRequest(stack_trace_, true /* skip next step */);
3087 stack_trace_ = NULL; 2800 stack_trace_ = NULL;
3088 return Error::null(); 2801 return Error::null();
3089 } 2802 }
3090 2803
3091 if (FLAG_verbose_debug) { 2804 if (FLAG_verbose_debug) {
3092 OS::Print(">>> hit %s breakpoint at %s:%" Pd 2805 OS::Print(">>> hit %s breakpoint at %s:%" Pd
3093 " " 2806 " "
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3126 DebuggerStackTrace* stack_trace = CollectStackTrace(); 2839 DebuggerStackTrace* stack_trace = CollectStackTrace();
3127 ASSERT(stack_trace->Length() > 0); 2840 ASSERT(stack_trace->Length() > 0);
3128 ASSERT(stack_trace_ == NULL); 2841 ASSERT(stack_trace_ == NULL);
3129 stack_trace_ = stack_trace; 2842 stack_trace_ = stack_trace;
3130 2843
3131 // TODO(johnmccutchan): Send |msg| to Observatory. 2844 // TODO(johnmccutchan): Send |msg| to Observatory.
3132 2845
3133 // We are in the native call to Developer_debugger. the developer 2846 // We are in the native call to Developer_debugger. the developer
3134 // gets a better experience by not seeing this call. To accomplish 2847 // gets a better experience by not seeing this call. To accomplish
3135 // this, we continue execution until the call exits (step out). 2848 // this, we continue execution until the call exits (step out).
3136 SetResumeAction(kStepOut); 2849 SetStepOut();
3137 HandleSteppingRequest(stack_trace_); 2850 HandleSteppingRequest(stack_trace_);
3138 2851
3139 stack_trace_ = NULL; 2852 stack_trace_ = NULL;
3140 } 2853 }
3141 2854
3142 2855
3143 void Debugger::Initialize(Isolate* isolate) { 2856 void Debugger::Initialize(Isolate* isolate) {
3144 if (initialized_) { 2857 if (initialized_) {
3145 return; 2858 return;
3146 } 2859 }
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after
3579 3292
3580 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 3293 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
3581 ASSERT(bpt->next() == NULL); 3294 ASSERT(bpt->next() == NULL);
3582 bpt->set_next(code_breakpoints_); 3295 bpt->set_next(code_breakpoints_);
3583 code_breakpoints_ = bpt; 3296 code_breakpoints_ = bpt;
3584 } 3297 }
3585 3298
3586 #endif // !PRODUCT 3299 #endif // !PRODUCT
3587 3300
3588 } // namespace dart 3301 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/debugger_api_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698