| 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);
|
|
|