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