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

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

Issue 14991010: Make breakpoints on == fire reliably (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 7 months 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/code_generator.cc ('k') | runtime/vm/intermediate_language_arm.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 "vm/code_generator.h" 9 #include "vm/code_generator.h"
10 #include "vm/code_patcher.h" 10 #include "vm/code_patcher.h"
(...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after
576 OS::SNPrint(chars, len, kFormat, func_name, url.ToCString(), line); 576 OS::SNPrint(chars, len, kFormat, func_name, url.ToCString(), line);
577 return chars; 577 return chars;
578 } 578 }
579 579
580 580
581 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) { 581 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) {
582 trace_.Add(frame); 582 trace_.Add(frame);
583 } 583 }
584 584
585 585
586 static bool IsSafePoint(PcDescriptors::Kind kind) {
587 return ((kind == PcDescriptors::kIcCall) ||
588 (kind == PcDescriptors::kFuncCall) ||
589 (kind == PcDescriptors::kClosureCall) ||
590 (kind == PcDescriptors::kReturn) ||
591 (kind == PcDescriptors::kEqualNull));
592 }
593
594
586 CodeBreakpoint::CodeBreakpoint(const Function& func, intptr_t pc_desc_index) 595 CodeBreakpoint::CodeBreakpoint(const Function& func, intptr_t pc_desc_index)
587 : function_(func.raw()), 596 : function_(func.raw()),
588 pc_desc_index_(pc_desc_index), 597 pc_desc_index_(pc_desc_index),
589 pc_(0), 598 pc_(0),
590 line_number_(-1), 599 line_number_(-1),
591 is_enabled_(false), 600 is_enabled_(false),
592 src_bpt_(NULL), 601 src_bpt_(NULL),
593 next_(NULL) { 602 next_(NULL) {
594 ASSERT(!func.HasOptimizedCode()); 603 ASSERT(!func.HasOptimizedCode());
595 Code& code = Code::Handle(func.unoptimized_code()); 604 Code& code = Code::Handle(func.unoptimized_code());
596 ASSERT(!code.IsNull()); // Function must be compiled. 605 ASSERT(!code.IsNull()); // Function must be compiled.
597 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); 606 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
598 ASSERT(pc_desc_index < desc.Length()); 607 ASSERT(pc_desc_index < desc.Length());
599 token_pos_ = desc.TokenPos(pc_desc_index); 608 token_pos_ = desc.TokenPos(pc_desc_index);
600 ASSERT(token_pos_ >= 0); 609 ASSERT(token_pos_ >= 0);
601 pc_ = desc.PC(pc_desc_index); 610 pc_ = desc.PC(pc_desc_index);
602 ASSERT(pc_ != 0); 611 ASSERT(pc_ != 0);
603 breakpoint_kind_ = desc.DescriptorKind(pc_desc_index); 612 breakpoint_kind_ = desc.DescriptorKind(pc_desc_index);
604 ASSERT((breakpoint_kind_ == PcDescriptors::kIcCall) || 613 ASSERT(IsSafePoint(breakpoint_kind_));
605 (breakpoint_kind_ == PcDescriptors::kFuncCall) ||
606 (breakpoint_kind_ == PcDescriptors::kClosureCall) ||
607 (breakpoint_kind_ == PcDescriptors::kReturn));
608 } 614 }
609 615
610 616
611 CodeBreakpoint::~CodeBreakpoint() { 617 CodeBreakpoint::~CodeBreakpoint() {
612 // Make sure we don't leave patched code behind. 618 // Make sure we don't leave patched code behind.
613 ASSERT(!IsEnabled()); 619 ASSERT(!IsEnabled());
614 // Poison the data so we catch use after free errors. 620 // Poison the data so we catch use after free errors.
615 #ifdef DEBUG 621 #ifdef DEBUG
616 function_ = Function::null(); 622 function_ = Function::null();
617 pc_ = 0ul; 623 pc_ = 0ul;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
668 } 674 }
669 case PcDescriptors::kClosureCall: { 675 case PcDescriptors::kClosureCall: {
670 const Code& code = 676 const Code& code =
671 Code::Handle(Function::Handle(function_).unoptimized_code()); 677 Code::Handle(Function::Handle(function_).unoptimized_code());
672 saved_bytes_.target_address_ = 678 saved_bytes_.target_address_ =
673 CodePatcher::GetStaticCallTargetAt(pc_, code); 679 CodePatcher::GetStaticCallTargetAt(pc_, code);
674 CodePatcher::PatchStaticCallAt(pc_, code, 680 CodePatcher::PatchStaticCallAt(pc_, code,
675 StubCode::BreakpointClosureEntryPoint()); 681 StubCode::BreakpointClosureEntryPoint());
676 break; 682 break;
677 } 683 }
684 case PcDescriptors::kEqualNull: {
685 const Code& code =
686 Code::Handle(Function::Handle(function_).unoptimized_code());
687 saved_bytes_.target_address_ =
688 CodePatcher::GetStaticCallTargetAt(pc_, code);
689 CodePatcher::PatchStaticCallAt(pc_, code,
690 StubCode::BreakpointEqNullEntryPoint());
691 break;
692 }
678 case PcDescriptors::kReturn: 693 case PcDescriptors::kReturn:
679 PatchFunctionReturn(); 694 PatchFunctionReturn();
680 break; 695 break;
681 default: 696 default:
682 UNREACHABLE(); 697 UNREACHABLE();
683 } 698 }
684 is_enabled_ = true; 699 is_enabled_ = true;
685 } 700 }
686 701
687 702
688 void CodeBreakpoint::RestoreCode() { 703 void CodeBreakpoint::RestoreCode() {
689 ASSERT(is_enabled_); 704 ASSERT(is_enabled_);
690 switch (breakpoint_kind_) { 705 switch (breakpoint_kind_) {
691 case PcDescriptors::kIcCall: { 706 case PcDescriptors::kIcCall: {
692 const Code& code = 707 const Code& code =
693 Code::Handle(Function::Handle(function_).unoptimized_code()); 708 Code::Handle(Function::Handle(function_).unoptimized_code());
694 CodePatcher::PatchInstanceCallAt(pc_, code, 709 CodePatcher::PatchInstanceCallAt(pc_, code,
695 saved_bytes_.target_address_); 710 saved_bytes_.target_address_);
696 break; 711 break;
697 } 712 }
698 case PcDescriptors::kFuncCall: 713 case PcDescriptors::kFuncCall:
699 case PcDescriptors::kClosureCall: { 714 case PcDescriptors::kClosureCall:
715 case PcDescriptors::kEqualNull: {
700 const Code& code = 716 const Code& code =
701 Code::Handle(Function::Handle(function_).unoptimized_code()); 717 Code::Handle(Function::Handle(function_).unoptimized_code());
702 CodePatcher::PatchStaticCallAt(pc_, code, 718 CodePatcher::PatchStaticCallAt(pc_, code,
703 saved_bytes_.target_address_); 719 saved_bytes_.target_address_);
704 break; 720 break;
705 } 721 }
706 case PcDescriptors::kReturn: 722 case PcDescriptors::kReturn:
707 RestoreFunctionReturn(); 723 RestoreFunctionReturn();
708 break; 724 break;
709 default: 725 default:
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
853 ASSERT(!function.IsNull()); 869 ASSERT(!function.IsNull());
854 if (function.HasOptimizedCode()) { 870 if (function.HasOptimizedCode()) {
855 function.SwitchToUnoptimizedCode(); 871 function.SwitchToUnoptimizedCode();
856 } 872 }
857 } 873 }
858 } 874 }
859 } 875 }
860 } 876 }
861 877
862 878
863 static bool IsSafePoint(PcDescriptors::Kind kind) {
864 return ((kind == PcDescriptors::kIcCall) ||
865 (kind == PcDescriptors::kFuncCall) ||
866 (kind == PcDescriptors::kClosureCall) ||
867 (kind == PcDescriptors::kReturn));
868 }
869
870
871 void Debugger::InstrumentForStepping(const Function& target_function) { 879 void Debugger::InstrumentForStepping(const Function& target_function) {
872 if (!target_function.HasCode()) { 880 if (!target_function.HasCode()) {
873 Compiler::CompileFunction(target_function); 881 Compiler::CompileFunction(target_function);
874 // If there were any errors, ignore them silently and return without 882 // If there were any errors, ignore them silently and return without
875 // adding breakpoints to target. 883 // adding breakpoints to target.
876 if (!target_function.HasCode()) { 884 if (!target_function.HasCode()) {
877 return; 885 return;
878 } 886 }
879 } 887 }
880 DeoptimizeWorld(); 888 DeoptimizeWorld();
(...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after
1608 ArgumentsDescriptor args_desc(Array::Handle( 1616 ArgumentsDescriptor args_desc(Array::Handle(
1609 CodePatcher::GetClosureArgDescAt(bpt->pc_, code))); 1617 CodePatcher::GetClosureArgDescAt(bpt->pc_, code)));
1610 ActivationFrame* top_frame = stack_trace->ActivationFrameAt(0); 1618 ActivationFrame* top_frame = stack_trace->ActivationFrameAt(0);
1611 const Object& receiver = 1619 const Object& receiver =
1612 Object::Handle(top_frame->GetClosureObject(args_desc.Count())); 1620 Object::Handle(top_frame->GetClosureObject(args_desc.Count()));
1613 if (!receiver.IsNull()) { 1621 if (!receiver.IsNull()) {
1614 // Verify that the class of receiver is a closure class 1622 // Verify that the class of receiver is a closure class
1615 // by checking that signature_function() is not null. 1623 // by checking that signature_function() is not null.
1616 const Class& receiver_class = Class::Handle(receiver.clazz()); 1624 const Class& receiver_class = Class::Handle(receiver.clazz());
1617 if (receiver_class.IsSignatureClass()) { 1625 if (receiver_class.IsSignatureClass()) {
1618 func_to_instrument = Closure::function(Instance::Cast(receiver)); 1626 Function& closure_func =
1627 Function::Handle(Closure::function(Instance::Cast(receiver)));
1628 if (IsDebuggable(closure_func)) {
1629 func_to_instrument = closure_func.raw();
1630 }
1619 } 1631 }
1620 // If the receiver is not a closure, then the runtime will attempt 1632 // If the receiver is not a closure, then the runtime will attempt
1621 // to invoke the "call" method on the object if one exists. 1633 // to invoke the "call" method on the object if one exists.
1622 // TODO(hausner): find call method and intrument it for stepping. 1634 // TODO(hausner): find call method and intrument it for stepping.
1623 } 1635 }
1636 } else if (bpt->breakpoint_kind_ == PcDescriptors::kEqualNull) {
1637 // This is just a call to the runtime, not Dart code. Stepping
1638 // into not possible, just treat like StepOver.
1639 func_to_instrument = bpt->function();
1624 } else { 1640 } else {
1625 ASSERT(bpt->breakpoint_kind_ == PcDescriptors::kReturn); 1641 ASSERT(bpt->breakpoint_kind_ == PcDescriptors::kReturn);
1626 // Treat like stepping out to caller. 1642 // Treat like stepping out to caller.
1627 if (stack_trace->Length() > 1) { 1643 if (stack_trace->Length() > 1) {
1628 ActivationFrame* caller_frame = stack_trace->ActivationFrameAt(1); 1644 ActivationFrame* caller_frame = stack_trace->ActivationFrameAt(1);
1629 func_to_instrument = caller_frame->function().raw(); 1645 func_to_instrument = caller_frame->function().raw();
1630 } 1646 }
1631 } 1647 }
1632 } else { 1648 } else {
1633 ASSERT(resume_action_ == kStepOut); 1649 ASSERT(resume_action_ == kStepOut);
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
1825 } 1841 }
1826 1842
1827 1843
1828 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 1844 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
1829 ASSERT(bpt->next() == NULL); 1845 ASSERT(bpt->next() == NULL);
1830 bpt->set_next(code_breakpoints_); 1846 bpt->set_next(code_breakpoints_);
1831 code_breakpoints_ = bpt; 1847 code_breakpoints_ = bpt;
1832 } 1848 }
1833 1849
1834 } // namespace dart 1850 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/code_generator.cc ('k') | runtime/vm/intermediate_language_arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698