Index: runtime/vm/code_generator.cc |
=================================================================== |
--- runtime/vm/code_generator.cc (revision 24285) |
+++ runtime/vm/code_generator.cc (working copy) |
@@ -878,8 +878,9 @@ |
// Let the megamorphic stub handle special cases: NoSuchMethod, |
// closure calls. |
if (FLAG_trace_ic) { |
- OS::PrintErr("InlineCacheMissHandler NULL code for receiver: %s\n", |
- receiver.ToCString()); |
+ OS::PrintErr("InlineCacheMissHandler NULL code for %s receiver: %s\n", |
+ String::Handle(ic_data.target_name()).ToCString(), |
+ receiver.ToCString()); |
} |
return Function::null(); |
} |
@@ -1154,7 +1155,9 @@ |
getter_name, |
kNumArguments, |
kNumNamedArguments)); |
- if (getter.IsNull() || getter.IsMethodExtractor()) { |
+ if (getter.IsNull() || |
+ getter.IsMethodExtractor() || |
+ getter.IsNoSuchMethodDispatcher()) { |
return false; |
} |
@@ -1179,6 +1182,41 @@ |
} |
+// Create a method for noSuchMethod invocation and attach it to the receiver |
+// class. |
+static RawFunction* CreateNoSuchMethodDispatcher( |
+ const String& target_name, |
+ const Class& receiver_class, |
+ const Array& arguments_descriptor) { |
+ Function& invocation = Function::Handle( |
+ Function::New(String::Handle(Symbols::New(target_name)), |
+ RawFunction::kNoSuchMethodDispatcher, |
+ false, // Not static. |
+ false, // Not const. |
+ false, // Not abstract. |
+ false, // Not external. |
+ receiver_class, |
+ 0)); // No token position. |
+ |
+ // Initialize signature: receiver is a single fixed parameter. |
+ const intptr_t kNumParameters = 1; |
+ invocation.set_num_fixed_parameters(kNumParameters); |
+ invocation.SetNumOptionalParameters(0, 0); |
+ invocation.set_parameter_types(Array::Handle(Array::New(kNumParameters, |
+ Heap::kOld))); |
+ invocation.set_parameter_names(Array::Handle(Array::New(kNumParameters, |
+ Heap::kOld))); |
+ invocation.SetParameterTypeAt(0, Type::Handle(Type::DynamicType())); |
+ invocation.SetParameterNameAt(0, Symbols::This()); |
+ invocation.set_result_type(Type::Handle(Type::DynamicType())); |
+ invocation.set_is_visible(false); // Not visible in stack trace. |
+ |
+ receiver_class.AddFunction(invocation); |
+ |
+ return invocation.raw(); |
+} |
+ |
+ |
// The IC miss handler has failed to find a (cacheable) instance function to |
// invoke. Handle three possibilities: |
// |
@@ -1213,10 +1251,36 @@ |
args_descriptor, |
args, |
&result)) { |
- result = DartEntry::InvokeNoSuchMethod(receiver, |
- target_name, |
- args, |
- args_descriptor); |
+ ArgumentsDescriptor desc(args_descriptor); |
+ Function& target_function = Function::Handle( |
+ Resolver::ResolveDynamicAnyArgs(receiver_class, target_name)); |
+ // Check number of arguments and check that there is not already a method |
+ // with the same name present. |
+ // TODO(fschneider): Handle multiple arguments. |
+ if (target_function.IsNull() && |
+ (desc.Count() == 1) && (desc.PositionalCount() == 1)) { |
+ // Create Function for noSuchMethodInvocation and add it to the class. |
+ target_function ^= CreateNoSuchMethodDispatcher(target_name, |
+ receiver_class, |
+ args_descriptor); |
+ |
+ // Update IC data. |
+ ASSERT(!target_function.IsNull()); |
+ ic_data.AddReceiverCheck(receiver.GetClassId(), target_function); |
+ if (FLAG_trace_ic) { |
+ OS::PrintErr("NoSuchMethod IC miss: adding <%s> id:%"Pd" -> <%s>\n", |
+ Class::Handle(receiver.clazz()).ToCString(), |
+ receiver.GetClassId(), |
+ target_function.ToCString()); |
+ } |
+ result = |
+ DartEntry::InvokeFunction(target_function, args, args_descriptor); |
+ } else { |
+ result = DartEntry::InvokeNoSuchMethod(receiver, |
+ target_name, |
+ args, |
+ args_descriptor); |
+ } |
} |
CheckResultError(result); |
arguments.SetReturn(result); |