| Index: runtime/vm/code_generator.cc
|
| ===================================================================
|
| --- runtime/vm/code_generator.cc (revision 14360)
|
| +++ runtime/vm/code_generator.cc (working copy)
|
| @@ -1190,7 +1190,46 @@
|
| return; // Return closure object.
|
| }
|
| }
|
| - Exceptions::ThrowByType(Exceptions::kObjectNotClosure, invoke_arguments);
|
| + // The result instance is not a closure, try to invoke method "call" before
|
| + // throwing a NoSuchMethodError.
|
| +
|
| + // TODO(regis): Factorize the following code.
|
| +
|
| + // TODO(regis): Args should be passed.
|
| + const Array& function_args = Array::Handle();
|
| + const String& function_name = String::Handle(Symbols::Call());
|
| + GrowableArray<const Object*> dart_arguments(5);
|
| +
|
| + // TODO(regis): Resolve and invoke "call" method, if existing.
|
| +
|
| + const Object& null_object = Object::Handle();
|
| + dart_arguments.Add(&result);
|
| + dart_arguments.Add(&function_name);
|
| + dart_arguments.Add(&function_args);
|
| + dart_arguments.Add(&null_object);
|
| +
|
| + // Report if a function "call" with different arguments has been found.
|
| + {
|
| + Class& instance_class = Class::Handle(result.clazz());
|
| + Function& function =
|
| + Function::Handle(instance_class.LookupDynamicFunction(function_name));
|
| + while (function.IsNull()) {
|
| + instance_class = instance_class.SuperClass();
|
| + if (instance_class.IsNull()) break;
|
| + function = instance_class.LookupDynamicFunction(function_name);
|
| + }
|
| + if (!function.IsNull()) {
|
| + const int total_num_parameters = function.NumParameters();
|
| + const Array& array = Array::Handle(Array::New(total_num_parameters - 1));
|
| + // Skip receiver.
|
| + for (int i = 1; i < total_num_parameters; i++) {
|
| + array.SetAt(i - 1, String::Handle(function.ParameterNameAt(i)));
|
| + }
|
| + dart_arguments.Add(&array);
|
| + }
|
| + }
|
| + Exceptions::ThrowByType(Exceptions::kNoSuchMethod, dart_arguments);
|
| + UNREACHABLE();
|
| }
|
|
|
|
|
| @@ -1244,7 +1283,7 @@
|
| named_arg_pos = Smi::New(named_arg_pos.Value() - 1);
|
| adjusted_arg_descriptor.SetAt(index + 1, named_arg_pos);
|
| }
|
| - adjusted_arg_descriptor.SetAt(len - 1, Object::Handle(Object::null()));
|
| + adjusted_arg_descriptor.SetAt(len - 1, Object::Handle());
|
| // It is too late to share the descriptor by canonicalizing it. However, it is
|
| // important that the argument names are canonicalized (i.e. are symbols).
|
|
|
| @@ -1329,27 +1368,73 @@
|
| }
|
|
|
|
|
| -// Report that an object is not a closure.
|
| +// A non-closure object was invoked as a closure, so call the "call" method
|
| +// on it.
|
| // Arg0: non-closure object.
|
| // Arg1: arguments array.
|
| +// TODO(regis): Rename this entry?
|
| DEFINE_RUNTIME_ENTRY(ReportObjectNotClosure, 2) {
|
| ASSERT(arguments.Count() ==
|
| kReportObjectNotClosureRuntimeEntry.argument_count());
|
| - const Instance& bad_closure = Instance::CheckedHandle(arguments.At(0));
|
| - if (bad_closure.IsNull()) {
|
| - GrowableArray<const Object*> args;
|
| - Exceptions::ThrowByType(Exceptions::kObjectNotClosure, args);
|
| + const Instance& instance = Instance::CheckedHandle(arguments.At(0));
|
| + const Array& function_args = Array::CheckedHandle(arguments.At(1));
|
| + const String& function_name = String::Handle(Symbols::Call());
|
| + GrowableArray<const Object*> dart_arguments(5);
|
| + if (instance.IsNull()) {
|
| + dart_arguments.Add(&function_name);
|
| + dart_arguments.Add(&function_args);
|
| + Exceptions::ThrowByType(Exceptions::kNullPointer, dart_arguments);
|
| + UNREACHABLE();
|
| }
|
| - GrowableArray<const Object*> args;
|
| - Exceptions::ThrowByType(Exceptions::kObjectNotClosure, args);
|
| +
|
| + // TODO(regis): Resolve and invoke "call" method, if existing.
|
| +
|
| + const Object& null_object = Object::Handle();
|
| + dart_arguments.Add(&instance);
|
| + dart_arguments.Add(&function_name);
|
| + dart_arguments.Add(&function_args);
|
| + dart_arguments.Add(&null_object);
|
| +
|
| + // Report if a function "call" with different arguments has been found.
|
| + Class& instance_class = Class::Handle(instance.clazz());
|
| + Function& function =
|
| + Function::Handle(instance_class.LookupDynamicFunction(function_name));
|
| + while (function.IsNull()) {
|
| + instance_class = instance_class.SuperClass();
|
| + if (instance_class.IsNull()) break;
|
| + function = instance_class.LookupDynamicFunction(function_name);
|
| + }
|
| + if (!function.IsNull()) {
|
| + const int total_num_parameters = function.NumParameters();
|
| + const Array& array = Array::Handle(Array::New(total_num_parameters - 1));
|
| + // Skip receiver.
|
| + for (int i = 1; i < total_num_parameters; i++) {
|
| + array.SetAt(i - 1, String::Handle(function.ParameterNameAt(i)));
|
| + }
|
| + dart_arguments.Add(&array);
|
| + }
|
| + Exceptions::ThrowByType(Exceptions::kNoSuchMethod, dart_arguments);
|
| + UNREACHABLE();
|
| }
|
|
|
|
|
| +// A closure object was invoked with incompatible arguments.
|
| +// TODO(regis): Deprecated. This case should be handled by a noSuchMethod call.
|
| DEFINE_RUNTIME_ENTRY(ClosureArgumentMismatch, 0) {
|
| ASSERT(arguments.Count() ==
|
| kClosureArgumentMismatchRuntimeEntry.argument_count());
|
| - GrowableArray<const Object*> args;
|
| - Exceptions::ThrowByType(Exceptions::kClosureArgumentMismatch, args);
|
| + const Instance& instance = Instance::Handle(); // Incorrect. OK for now.
|
| + const Array& function_args = Array::Handle(); // Incorrect. OK for now.
|
| + const String& function_name = String::Handle(Symbols::Call());
|
| + GrowableArray<const Object*> dart_arguments(5);
|
| +
|
| + const Object& null_object = Object::Handle();
|
| + dart_arguments.Add(&instance);
|
| + dart_arguments.Add(&function_name);
|
| + dart_arguments.Add(&function_args);
|
| + dart_arguments.Add(&null_object);
|
| + Exceptions::ThrowByType(Exceptions::kNoSuchMethod, dart_arguments);
|
| + UNREACHABLE();
|
| }
|
|
|
|
|
|
|