Index: runtime/vm/code_generator.cc |
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc |
index f48684a7217dc6ff94e584ca8b708316ed13a78f..6490c716ac95488f9e755b63e82fc699669d15a6 100644 |
--- a/runtime/vm/code_generator.cc |
+++ b/runtime/vm/code_generator.cc |
@@ -1146,6 +1146,81 @@ DEFINE_RUNTIME_ENTRY(SingleTargetMiss, 1) { |
} |
+DEFINE_RUNTIME_ENTRY(UnlinkedCall, 2) { |
+#if defined(TARGET_ARCH_DBC) |
+ // DBC does not use switchable calls. |
+ UNREACHABLE(); |
+#else |
+ const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
+ const UnlinkedCall& unlinked = |
+ UnlinkedCall::CheckedHandle(zone, arguments.ArgAt(1)); |
+ |
+ DartFrameIterator iterator; |
+ StackFrame* caller_frame = iterator.NextFrame(); |
+ ASSERT(caller_frame->IsDartFrame()); |
+ const Code& caller_code = |
+ Code::Handle(zone, caller_frame->LookupDartCode()); |
+ const Function& caller_function = |
+ Function::Handle(zone, caller_frame->LookupDartFunction()); |
+ |
+ const String& name = String::Handle(zone, unlinked.target_name()); |
+ const Array& descriptor = Array::Handle(zone, unlinked.args_descriptor()); |
+ const ICData& ic_data = |
+ ICData::Handle(zone, ICData::New(caller_function, |
+ name, |
+ descriptor, |
+ Thread::kNoDeoptId, |
+ 1, /* args_tested */ |
+ false /* static_call */)); |
+ |
+ Class& cls = Class::Handle(zone, receiver.clazz()); |
+ ArgumentsDescriptor args_desc(descriptor); |
+ Function& target_function = Function::Handle(zone, |
+ Resolver::ResolveDynamicForReceiverClass(cls, |
+ name, |
+ args_desc)); |
+ if (target_function.IsNull()) { |
+ target_function = InlineCacheMissHelper(receiver, descriptor, name); |
+ } |
+ if (target_function.IsNull()) { |
+ ASSERT(!FLAG_lazy_dispatchers); |
+ } else { |
+ ic_data.AddReceiverCheck(receiver.GetClassId(), target_function); |
+ } |
+ |
+ if (!target_function.IsNull() && |
+ !target_function.HasOptionalParameters()) { |
+ // Patch to monomorphic call. |
+ ASSERT(target_function.HasCode()); |
+ const Code& target_code = |
+ Code::Handle(zone, target_function.CurrentCode()); |
+ const Smi& expected_cid = |
+ Smi::Handle(zone, Smi::New(receiver.GetClassId())); |
+ CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, |
+ expected_cid, target_code); |
+ |
+ // Return the ICData. The miss stub will jump to continue in the IC call |
+ // stub. |
+ arguments.SetReturn(ic_data); |
+ return; |
+ } |
+ |
+ // Patch to call through stub. |
+ const Code& stub = |
+ Code::Handle(zone, StubCode::ICCallThroughCode_entry()->code()); |
+ ASSERT(!Isolate::Current()->compilation_allowed()); |
+ CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), |
+ caller_code, |
+ ic_data, |
+ stub); |
+ |
+ // Return the ICData. The miss stub will jump to continue in the IC lookup |
+ // stub. |
+ arguments.SetReturn(ic_data); |
+#endif // !DBC |
+} |
+ |
+ |
// Handle a miss of a megamorphic cache. |
// Arg0: Receiver. |
// Returns: the ICData used to continue with a polymorphic call. |