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

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

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

Powered by Google App Engine
This is Rietveld 408576698