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

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

Issue 14858033: Implement breakpoint for closure calls (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/debugger.h ('k') | runtime/vm/debugger_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 585 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 ASSERT(!code.IsNull()); // Function must be compiled. 596 ASSERT(!code.IsNull()); // Function must be compiled.
597 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); 597 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
598 ASSERT(pc_desc_index < desc.Length()); 598 ASSERT(pc_desc_index < desc.Length());
599 token_pos_ = desc.TokenPos(pc_desc_index); 599 token_pos_ = desc.TokenPos(pc_desc_index);
600 ASSERT(token_pos_ >= 0); 600 ASSERT(token_pos_ >= 0);
601 pc_ = desc.PC(pc_desc_index); 601 pc_ = desc.PC(pc_desc_index);
602 ASSERT(pc_ != 0); 602 ASSERT(pc_ != 0);
603 breakpoint_kind_ = desc.DescriptorKind(pc_desc_index); 603 breakpoint_kind_ = desc.DescriptorKind(pc_desc_index);
604 ASSERT((breakpoint_kind_ == PcDescriptors::kIcCall) || 604 ASSERT((breakpoint_kind_ == PcDescriptors::kIcCall) ||
605 (breakpoint_kind_ == PcDescriptors::kFuncCall) || 605 (breakpoint_kind_ == PcDescriptors::kFuncCall) ||
606 (breakpoint_kind_ == PcDescriptors::kClosureCall) ||
606 (breakpoint_kind_ == PcDescriptors::kReturn)); 607 (breakpoint_kind_ == PcDescriptors::kReturn));
607 } 608 }
608 609
609 610
610 CodeBreakpoint::~CodeBreakpoint() { 611 CodeBreakpoint::~CodeBreakpoint() {
611 // Make sure we don't leave patched code behind. 612 // Make sure we don't leave patched code behind.
612 ASSERT(!IsEnabled()); 613 ASSERT(!IsEnabled());
613 // Poison the data so we catch use after free errors. 614 // Poison the data so we catch use after free errors.
614 #ifdef DEBUG 615 #ifdef DEBUG
615 function_ = Function::null(); 616 function_ = Function::null();
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
658 } 659 }
659 case PcDescriptors::kFuncCall: { 660 case PcDescriptors::kFuncCall: {
660 const Code& code = 661 const Code& code =
661 Code::Handle(Function::Handle(function_).unoptimized_code()); 662 Code::Handle(Function::Handle(function_).unoptimized_code());
662 saved_bytes_.target_address_ = 663 saved_bytes_.target_address_ =
663 CodePatcher::GetStaticCallTargetAt(pc_, code); 664 CodePatcher::GetStaticCallTargetAt(pc_, code);
664 CodePatcher::PatchStaticCallAt(pc_, code, 665 CodePatcher::PatchStaticCallAt(pc_, code,
665 StubCode::BreakpointStaticEntryPoint()); 666 StubCode::BreakpointStaticEntryPoint());
666 break; 667 break;
667 } 668 }
669 case PcDescriptors::kClosureCall: {
670 const Code& code =
671 Code::Handle(Function::Handle(function_).unoptimized_code());
672 saved_bytes_.target_address_ =
673 CodePatcher::GetStaticCallTargetAt(pc_, code);
674 CodePatcher::PatchStaticCallAt(pc_, code,
675 StubCode::BreakpointClosureEntryPoint());
676 break;
677 }
668 case PcDescriptors::kReturn: 678 case PcDescriptors::kReturn:
669 PatchFunctionReturn(); 679 PatchFunctionReturn();
670 break; 680 break;
671 default: 681 default:
672 UNREACHABLE(); 682 UNREACHABLE();
673 } 683 }
674 is_enabled_ = true; 684 is_enabled_ = true;
675 } 685 }
676 686
677 687
678 void CodeBreakpoint::RestoreCode() { 688 void CodeBreakpoint::RestoreCode() {
679 ASSERT(is_enabled_); 689 ASSERT(is_enabled_);
680 switch (breakpoint_kind_) { 690 switch (breakpoint_kind_) {
681 case PcDescriptors::kIcCall: { 691 case PcDescriptors::kIcCall: {
682 const Code& code = 692 const Code& code =
683 Code::Handle(Function::Handle(function_).unoptimized_code()); 693 Code::Handle(Function::Handle(function_).unoptimized_code());
684 CodePatcher::PatchInstanceCallAt(pc_, code, 694 CodePatcher::PatchInstanceCallAt(pc_, code,
685 saved_bytes_.target_address_); 695 saved_bytes_.target_address_);
686 break; 696 break;
687 } 697 }
688 case PcDescriptors::kFuncCall: { 698 case PcDescriptors::kFuncCall:
699 case PcDescriptors::kClosureCall: {
689 const Code& code = 700 const Code& code =
690 Code::Handle(Function::Handle(function_).unoptimized_code()); 701 Code::Handle(Function::Handle(function_).unoptimized_code());
691 CodePatcher::PatchStaticCallAt(pc_, code, 702 CodePatcher::PatchStaticCallAt(pc_, code,
692 saved_bytes_.target_address_); 703 saved_bytes_.target_address_);
693 break; 704 break;
694 } 705 }
695 case PcDescriptors::kReturn: 706 case PcDescriptors::kReturn:
696 RestoreFunctionReturn(); 707 RestoreFunctionReturn();
697 break; 708 break;
698 default: 709 default:
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
867 CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(i)); 878 CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(i));
868 if (bpt != NULL) { 879 if (bpt != NULL) {
869 // There is already a breakpoint for this address. Make sure 880 // There is already a breakpoint for this address. Make sure
870 // it is enabled. 881 // it is enabled.
871 bpt->Enable(); 882 bpt->Enable();
872 continue; 883 continue;
873 } 884 }
874 PcDescriptors::Kind kind = desc.DescriptorKind(i); 885 PcDescriptors::Kind kind = desc.DescriptorKind(i);
875 if ((kind == PcDescriptors::kIcCall) || 886 if ((kind == PcDescriptors::kIcCall) ||
876 (kind == PcDescriptors::kFuncCall) || 887 (kind == PcDescriptors::kFuncCall) ||
888 (kind == PcDescriptors::kClosureCall) ||
877 (kind == PcDescriptors::kReturn)) { 889 (kind == PcDescriptors::kReturn)) {
878 bpt = new CodeBreakpoint(target_function, i); 890 bpt = new CodeBreakpoint(target_function, i);
879 RegisterCodeBreakpoint(bpt); 891 RegisterCodeBreakpoint(bpt);
880 bpt->Enable(); 892 bpt->Enable();
881 } 893 }
882 } 894 }
883 } 895 }
884 896
885 897
886 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { 898 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) {
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
1034 intptr_t lowest_pc_index = -1; 1046 intptr_t lowest_pc_index = -1;
1035 for (int i = 0; i < desc.Length(); i++) { 1047 for (int i = 0; i < desc.Length(); i++) {
1036 intptr_t desc_token_pos = desc.TokenPos(i); 1048 intptr_t desc_token_pos = desc.TokenPos(i);
1037 ASSERT(desc_token_pos >= 0); 1049 ASSERT(desc_token_pos >= 0);
1038 if (desc_token_pos < first_token_pos) { 1050 if (desc_token_pos < first_token_pos) {
1039 continue; 1051 continue;
1040 } 1052 }
1041 PcDescriptors::Kind kind = desc.DescriptorKind(i); 1053 PcDescriptors::Kind kind = desc.DescriptorKind(i);
1042 if ((kind == PcDescriptors::kIcCall) || 1054 if ((kind == PcDescriptors::kIcCall) ||
1043 (kind == PcDescriptors::kFuncCall) || 1055 (kind == PcDescriptors::kFuncCall) ||
1056 (kind == PcDescriptors::kClosureCall) ||
1044 (kind == PcDescriptors::kReturn)) { 1057 (kind == PcDescriptors::kReturn)) {
1045 if ((desc_token_pos - first_token_pos) < best_fit) { 1058 if ((desc_token_pos - first_token_pos) < best_fit) {
1046 best_fit = desc_token_pos - first_token_pos; 1059 best_fit = desc_token_pos - first_token_pos;
1047 ASSERT(best_fit >= 0); 1060 ASSERT(best_fit >= 0);
1048 best_fit_index = i; 1061 best_fit_index = i;
1049 } 1062 }
1050 if ((first_token_pos <= desc_token_pos) && 1063 if ((first_token_pos <= desc_token_pos) &&
1051 (desc_token_pos <= last_token_pos) && 1064 (desc_token_pos <= last_token_pos) &&
1052 (desc.PC(i) < lowest_pc)) { 1065 (desc.PC(i) < lowest_pc)) {
1053 lowest_pc = desc.PC(i); 1066 lowest_pc = desc.PC(i);
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after
1566 } 1579 }
1567 } else if (bpt->breakpoint_kind_ == PcDescriptors::kFuncCall) { 1580 } else if (bpt->breakpoint_kind_ == PcDescriptors::kFuncCall) {
1568 func_to_instrument = bpt->function(); 1581 func_to_instrument = bpt->function();
1569 const Code& code = Code::Handle(func_to_instrument.CurrentCode()); 1582 const Code& code = Code::Handle(func_to_instrument.CurrentCode());
1570 const Function& callee = 1583 const Function& callee =
1571 Function::Handle(code.GetStaticCallTargetFunctionAt(bpt->pc_)); 1584 Function::Handle(code.GetStaticCallTargetFunctionAt(bpt->pc_));
1572 ASSERT(!callee.IsNull()); 1585 ASSERT(!callee.IsNull());
1573 if (IsDebuggable(callee)) { 1586 if (IsDebuggable(callee)) {
1574 func_to_instrument = callee.raw(); 1587 func_to_instrument = callee.raw();
1575 } 1588 }
1589 } else if (bpt->breakpoint_kind_ == PcDescriptors::kClosureCall) {
1590 func_to_instrument = bpt->function();
1591 const Code& code = Code::Handle(func_to_instrument.CurrentCode());
1592 ArgumentsDescriptor args_desc(Array::Handle(
1593 CodePatcher::GetClosureArgDescAt(bpt->pc_, code)));
1594 ActivationFrame* top_frame = stack_trace->ActivationFrameAt(0);
1595 const Object& receiver =
1596 Object::Handle(top_frame->GetClosureObject(args_desc.Count()));
1597 if (!receiver.IsNull()) {
1598 // Verify that the class of receiver is a closure class
1599 // by checking that signature_function() is not null.
1600 const Class& receiver_class = Class::Handle(receiver.clazz());
1601 if (receiver_class.IsSignatureClass()) {
1602 func_to_instrument = Closure::function(Instance::Cast(receiver));
1603 }
1604 // If the receiver is not a closure, then the runtime will attempt
1605 // to invoke the "call" method on the object if one exists.
1606 // TODO(hausner): find call method and intrument it for stepping.
1607 }
1576 } else { 1608 } else {
1577 ASSERT(bpt->breakpoint_kind_ == PcDescriptors::kReturn); 1609 ASSERT(bpt->breakpoint_kind_ == PcDescriptors::kReturn);
1578 // Treat like stepping out to caller. 1610 // Treat like stepping out to caller.
1579 if (stack_trace->Length() > 1) { 1611 if (stack_trace->Length() > 1) {
1580 ActivationFrame* caller_frame = stack_trace->ActivationFrameAt(1); 1612 ActivationFrame* caller_frame = stack_trace->ActivationFrameAt(1);
1581 func_to_instrument = caller_frame->function().raw(); 1613 func_to_instrument = caller_frame->function().raw();
1582 } 1614 }
1583 } 1615 }
1584 } else { 1616 } else {
1585 ASSERT(resume_action_ == kStepOut); 1617 ASSERT(resume_action_ == kStepOut);
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
1779 } 1811 }
1780 1812
1781 1813
1782 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 1814 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
1783 ASSERT(bpt->next() == NULL); 1815 ASSERT(bpt->next() == NULL);
1784 bpt->set_next(code_breakpoints_); 1816 bpt->set_next(code_breakpoints_);
1785 code_breakpoints_ = bpt; 1817 code_breakpoints_ = bpt;
1786 } 1818 }
1787 1819
1788 } // namespace dart 1820 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/debugger_arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698