Chromium Code Reviews| 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() && |
|
Florian Schneider
2013/06/24 12:25:44
Added the check if a function with that name alrea
|
| + (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); |