Index: runtime/vm/debugger.cc |
=================================================================== |
--- runtime/vm/debugger.cc (revision 22595) |
+++ runtime/vm/debugger.cc (working copy) |
@@ -603,6 +603,7 @@ |
breakpoint_kind_ = desc.DescriptorKind(pc_desc_index); |
ASSERT((breakpoint_kind_ == PcDescriptors::kIcCall) || |
(breakpoint_kind_ == PcDescriptors::kFuncCall) || |
+ (breakpoint_kind_ == PcDescriptors::kClosureCall) || |
(breakpoint_kind_ == PcDescriptors::kReturn)); |
} |
@@ -665,6 +666,15 @@ |
StubCode::BreakpointStaticEntryPoint()); |
break; |
} |
+ case PcDescriptors::kClosureCall: { |
+ const Code& code = |
+ Code::Handle(Function::Handle(function_).unoptimized_code()); |
+ saved_bytes_.target_address_ = |
+ CodePatcher::GetStaticCallTargetAt(pc_, code); |
+ CodePatcher::PatchStaticCallAt(pc_, code, |
+ StubCode::BreakpointClosureEntryPoint()); |
+ break; |
+ } |
case PcDescriptors::kReturn: |
PatchFunctionReturn(); |
break; |
@@ -685,7 +695,8 @@ |
saved_bytes_.target_address_); |
break; |
} |
- case PcDescriptors::kFuncCall: { |
+ case PcDescriptors::kFuncCall: |
+ case PcDescriptors::kClosureCall: { |
const Code& code = |
Code::Handle(Function::Handle(function_).unoptimized_code()); |
CodePatcher::PatchStaticCallAt(pc_, code, |
@@ -874,6 +885,7 @@ |
PcDescriptors::Kind kind = desc.DescriptorKind(i); |
if ((kind == PcDescriptors::kIcCall) || |
(kind == PcDescriptors::kFuncCall) || |
+ (kind == PcDescriptors::kClosureCall) || |
(kind == PcDescriptors::kReturn)) { |
bpt = new CodeBreakpoint(target_function, i); |
RegisterCodeBreakpoint(bpt); |
@@ -1041,6 +1053,7 @@ |
PcDescriptors::Kind kind = desc.DescriptorKind(i); |
if ((kind == PcDescriptors::kIcCall) || |
(kind == PcDescriptors::kFuncCall) || |
+ (kind == PcDescriptors::kClosureCall) || |
(kind == PcDescriptors::kReturn)) { |
if ((desc_token_pos - first_token_pos) < best_fit) { |
best_fit = desc_token_pos - first_token_pos; |
@@ -1573,6 +1586,25 @@ |
if (IsDebuggable(callee)) { |
func_to_instrument = callee.raw(); |
} |
+ } else if (bpt->breakpoint_kind_ == PcDescriptors::kClosureCall) { |
+ func_to_instrument = bpt->function(); |
+ const Code& code = Code::Handle(func_to_instrument.CurrentCode()); |
+ ArgumentsDescriptor args_desc(Array::Handle( |
+ CodePatcher::GetClosureArgDescAt(bpt->pc_, code))); |
+ ActivationFrame* top_frame = stack_trace->ActivationFrameAt(0); |
+ const Object& receiver = |
+ Object::Handle(top_frame->GetClosureObject(args_desc.Count())); |
+ if (!receiver.IsNull()) { |
+ // Verify that the class of receiver is a closure class |
+ // by checking that signature_function() is not null. |
+ const Class& receiver_class = Class::Handle(receiver.clazz()); |
+ if (receiver_class.IsSignatureClass()) { |
+ func_to_instrument = Closure::function(Instance::Cast(receiver)); |
+ } |
+ // If the receiver is not a closure, then the runtime will attempt |
+ // to invoke the "call" method on the object if one exists. |
+ // TODO(hausner): find call method and intrument it for stepping. |
+ } |
} else { |
ASSERT(bpt->breakpoint_kind_ == PcDescriptors::kReturn); |
// Treat like stepping out to caller. |