Index: runtime/vm/code_generator.cc |
=================================================================== |
--- runtime/vm/code_generator.cc (revision 16007) |
+++ runtime/vm/code_generator.cc (working copy) |
@@ -1264,7 +1264,7 @@ |
ASSERT(arguments.ArgCount() == |
kInvokeImplicitClosureFunctionRuntimeEntry.argument_count()); |
const Instance& closure = Instance::CheckedHandle(arguments.ArgAt(0)); |
- const Array& arg_descriptor = Array::CheckedHandle(arguments.ArgAt(1)); |
+ const Array& args_descriptor = Array::CheckedHandle(arguments.ArgAt(1)); |
const Array& func_arguments = Array::CheckedHandle(arguments.ArgAt(2)); |
const Function& function = Function::Handle(Closure::function(closure)); |
ASSERT(!function.IsNull()); |
@@ -1291,13 +1291,13 @@ |
invoke_arguments.Add(&value); |
} |
- // Now Call the invoke stub which will invoke the closure. |
+ // Now call the invoke stub which will invoke the closure. |
DartEntry::invokestub entrypoint = reinterpret_cast<DartEntry::invokestub>( |
StubCode::InvokeDartCodeEntryPoint()); |
ASSERT(context.isolate() == Isolate::Current()); |
const Object& result = Object::Handle( |
entrypoint(instrs.EntryPoint(), |
- arg_descriptor, |
+ args_descriptor, |
invoke_arguments.data(), |
context)); |
CheckResultError(result); |
@@ -1366,25 +1366,17 @@ |
// A non-closure object was invoked as a closure, so call the "call" method |
// on it. |
// Arg0: non-closure object. |
-// Arg1: arguments array, including non-closure object. |
-// TODO(regis): Rename this entry? |
-DEFINE_RUNTIME_ENTRY(ReportObjectNotClosure, 2) { |
+// Arg1: arguments descriptor. |
+// Arg2: arguments array, including non-closure object. |
+DEFINE_RUNTIME_ENTRY(InvokeNonClosure, 3) { |
ASSERT(arguments.ArgCount() == |
- kReportObjectNotClosureRuntimeEntry.argument_count()); |
+ kInvokeNonClosureRuntimeEntry.argument_count()); |
const Instance& instance = Instance::CheckedHandle(arguments.ArgAt(0)); |
- const Array& function_args = Array::CheckedHandle(arguments.ArgAt(1)); |
+ const Array& args_descriptor = Array::CheckedHandle(arguments.ArgAt(1)); |
+ const Array& function_args = Array::CheckedHandle(arguments.ArgAt(2)); |
+ |
+ // Resolve and invoke "call" method, if existing. |
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(&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)); |
@@ -1394,14 +1386,47 @@ |
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))); |
+ if (!function.HasCode()) { |
+ const Error& error = Error::Handle(Compiler::CompileFunction(function)); |
+ if (!error.IsNull()) { |
+ Exceptions::PropagateError(error); |
+ } |
} |
- dart_arguments.Add(&array); |
+ const Code& code = Code::Handle(function.CurrentCode()); |
+ ASSERT(!code.IsNull()); |
+ const Instructions& instrs = Instructions::Handle(code.instructions()); |
+ ASSERT(!instrs.IsNull()); |
+ |
+ // The non-closure object is passed as implicit first argument (receiver). |
+ // It is already included in the arguments array. |
+ GrowableArray<const Object*> invoke_arguments(function_args.Length()); |
+ for (intptr_t i = 0; i < function_args.Length(); i++) { |
+ const Object& value = Object::Handle(function_args.At(i)); |
+ invoke_arguments.Add(&value); |
+ } |
+ |
+ // Now call the invoke stub which will invoke the call method. |
+ DartEntry::invokestub entrypoint = reinterpret_cast<DartEntry::invokestub>( |
+ StubCode::InvokeDartCodeEntryPoint()); |
+ const Context& context = Context::ZoneHandle( |
+ Isolate::Current()->object_store()->empty_context()); |
+ const Object& result = Object::Handle( |
+ entrypoint(instrs.EntryPoint(), |
+ args_descriptor, |
+ invoke_arguments.data(), |
+ context)); |
+ CheckResultError(result); |
+ arguments.SetReturn(result); |
+ return; |
} |
+ const Object& null_object = Object::Handle(); |
+ GrowableArray<const Object*> dart_arguments(5); |
+ dart_arguments.Add(&instance); |
+ dart_arguments.Add(&function_name); |
+ dart_arguments.Add(&function_args); |
+ dart_arguments.Add(&null_object); |
+ // If a function "call" with different arguments exists, it will have been |
+ // invoked above, so no need to handle this case here. |
Exceptions::ThrowByType(Exceptions::kNoSuchMethod, dart_arguments); |
UNREACHABLE(); |
} |