Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2776)

Unified Diff: runtime/vm/code_generator.cc

Issue 11316353: Refactor the InstanceFunctionLookupStub. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/code_generator.h ('k') | runtime/vm/stub_code_ia32.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/code_generator.cc
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 78f0625ae8ca6b2680d2004c0c5dc21c4bf45f4c..86fa1d941b8c88c1bef41af7b0c0f5a739516ff5 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -1090,275 +1090,267 @@ DEFINE_RUNTIME_ENTRY(UpdateICDataTwoArgs, 4) {
}
-static RawFunction* LookupDynamicFunction(Isolate* isolate,
- const Class& in_cls,
- const String& name) {
- Class& cls = Class::Handle();
- // For lookups treat null as an instance of class Object.
- if (in_cls.IsNullClass()) {
- cls = isolate->object_store()->object_class();
- } else {
- cls = in_cls.raw();
- }
-
- Function& function = Function::Handle();
- while (!cls.IsNull()) {
- // Check if function exists.
- function = cls.LookupDynamicFunction(name);
- if (!function.IsNull()) {
- break;
- }
- cls = cls.SuperClass();
- }
- return function.raw();
-}
-
-
-// Resolve an implicit closure by checking if an instance function
-// of the same name exists and creating a closure object of the function.
-// Arg0: receiver object.
-// Arg1: ic-data.
-// Returns: Closure object or NULL (instance function not found).
-// This is called by the megamorphic stub when it is unable to resolve an
-// instance method. This is done just before the call to noSuchMethod.
-DEFINE_RUNTIME_ENTRY(ResolveImplicitClosureFunction, 2) {
- ASSERT(arguments.ArgCount() ==
- kResolveImplicitClosureFunctionRuntimeEntry.argument_count());
- const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
- const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
- const String& original_function_name = String::Handle(ic_data.target_name());
- Instance& closure = Instance::Handle();
- if (!Field::IsGetterName(original_function_name)) {
- // This is not a getter so can't be the case where we are trying to
- // create an implicit closure of an instance function.
- arguments.SetReturn(closure);
- return;
- }
- const Class& receiver_class = Class::Handle(receiver.clazz());
- ASSERT(!receiver_class.IsNull());
- String& func_name = String::Handle();
- func_name = Field::NameFromGetter(original_function_name);
- func_name = Symbols::New(func_name);
+// An instance call could not be resolved by an IC miss handler. Check if
+// it was a getter call and if there is an instance function with the same
+// name. If so, create and return an implicit closure from the function.
+// Otherwise return null.
+static RawInstance* ResolveImplicitClosure(const Instance& receiver,
+ const Class& receiver_class,
+ const String& target_name) {
+ // 1. Check if was a getter call.
+ if (!Field::IsGetterName(target_name)) return Instance::null();
+
+ // 2. Check if there is an instance function with the same name.
+ String& function_name = String::Handle(Field::NameFromGetter(target_name));
+ function_name = Symbols::New(function_name);
const Function& function = Function::Handle(
- LookupDynamicFunction(isolate, receiver_class, func_name));
- if (function.IsNull()) {
- // There is no function of the same name so can't be the case where
- // we are trying to create an implicit closure of an instance function.
- arguments.SetReturn(closure);
- return;
- }
- Function& implicit_closure_function =
- Function::Handle(function.ImplicitClosureFunction());
+ Resolver::ResolveDynamicAnyArgs(receiver_class, function_name));
+ if (function.IsNull()) return Instance::null();
+
// Create a closure object for the implicit closure function.
+ const Function& closure_function =
+ Function::Handle(function.ImplicitClosureFunction());
const Context& context = Context::Handle(Context::New(1));
context.SetAt(0, receiver);
- closure = Closure::New(implicit_closure_function, context);
+ const Instance& closure =
+ Instance::Handle(Closure::New(closure_function, context));
if (receiver_class.HasTypeArguments()) {
const AbstractTypeArguments& type_arguments =
AbstractTypeArguments::Handle(receiver.GetTypeArguments());
closure.SetTypeArguments(type_arguments);
}
- arguments.SetReturn(closure);
-}
-
-
-// Resolve an implicit closure by invoking getter and checking if the return
-// value from getter is a closure.
-// Arg0: receiver object.
-// Arg1: ic-data.
-// Returns: Closure object or NULL (closure not found).
-// This is called by the megamorphic stub when it is unable to resolve an
-// instance method. This is done just before the call to noSuchMethod.
-DEFINE_RUNTIME_ENTRY(ResolveImplicitClosureThroughGetter, 2) {
- ASSERT(arguments.ArgCount() ==
- kResolveImplicitClosureThroughGetterRuntimeEntry.argument_count());
- const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
- const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
- const String& original_function_name = String::Handle(ic_data.target_name());
- const int kNumArguments = 1;
- const int kNumNamedArguments = 0;
- const String& getter_function_name =
- String::Handle(Field::GetterName(original_function_name));
- Function& function = Function::ZoneHandle(
- Resolver::ResolveDynamic(receiver,
- getter_function_name,
- kNumArguments,
- kNumNamedArguments));
- const Object& null_object = Object::Handle();
- if (function.IsNull()) {
- arguments.SetReturn(null_object);
- return; // No getter function found so can't be an implicit closure.
- }
- GrowableArray<const Object*> invoke_arguments(0);
- const Array& kNoArgumentNames = Array::Handle();
- const Object& result =
- Object::Handle(DartEntry::InvokeDynamic(receiver,
- function,
- invoke_arguments,
- kNoArgumentNames));
- if (result.IsError()) {
- if (result.IsUnhandledException()) {
- // If the getter throws an exception, treat as no such method.
- arguments.SetReturn(null_object);
- return;
- } else {
- Exceptions::PropagateError(Error::Cast(result));
- }
- }
- if (!result.IsSmi()) {
- const Class& cls = Class::Handle(result.clazz());
- ASSERT(!cls.IsNull());
- function = cls.signature_function();
- if (!function.IsNull()) {
- arguments.SetReturn(result);
- return; // Return closure object.
- }
- }
- // 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.
-
- 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();
+ return closure.raw();
}
-// Invoke Implicit Closure function.
-// Arg0: closure object.
-// Arg1: arguments descriptor (originally passed as dart instance invocation).
-// Arg2: arguments array (originally passed to dart instance invocation).
-DEFINE_RUNTIME_ENTRY(InvokeImplicitClosureFunction, 3) {
- ASSERT(arguments.ArgCount() ==
- kInvokeImplicitClosureFunctionRuntimeEntry.argument_count());
- const Instance& closure = Instance::CheckedHandle(arguments.ArgAt(0));
- 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());
+static RawInstructions* EnsureCompiled(const Function& function) {
if (!function.HasCode()) {
const Error& error = Error::Handle(Compiler::CompileFunction(function));
if (!error.IsNull()) {
Exceptions::PropagateError(error);
+ UNREACHABLE();
}
}
- const Context& context = Context::Handle(Closure::context(closure));
const Code& code = Code::Handle(function.CurrentCode());
ASSERT(!code.IsNull());
const Instructions& instrs = Instructions::Handle(code.instructions());
ASSERT(!instrs.IsNull());
+ return instrs.raw();
+}
+
+
+static RawObject* InvokeClosure(const Instance& closure,
+ const Array& arguments_descriptor,
+ const Array& arguments) {
+ const Function& function = Function::Handle(Closure::function(closure));
+ ASSERT(!function.IsNull());
+ const Instructions& instrs = Instructions::Handle(EnsureCompiled(function));
+ const Context& context = Context::Handle(Closure::context(closure));
// The closure object is passed as implicit first argument to closure
// functions, since it may be needed to throw a NoSuchMethodError, in case
// the wrong number of arguments is passed.
// Replace the original receiver in the arguments array by the closure.
- GrowableArray<const Object*> invoke_arguments(func_arguments.Length());
+ GrowableArray<const Object*> invoke_arguments(arguments.Length());
invoke_arguments.Add(&closure);
- for (intptr_t i = 1; i < func_arguments.Length(); i++) {
- const Object& value = Object::Handle(func_arguments.At(i));
+ for (intptr_t i = 1; i < arguments.Length(); i++) {
+ const Object& value = Object::Handle(arguments.At(i));
invoke_arguments.Add(&value);
}
-
// 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(),
- args_descriptor,
- invoke_arguments.data(),
- context));
+ const Object& result = Object::Handle(entrypoint(instrs.EntryPoint(),
+ arguments_descriptor,
+ invoke_arguments.data(),
+ context));
CheckResultError(result);
- arguments.SetReturn(result);
+ return result.raw();
}
-// Invoke appropriate noSuchMethod function.
-// Arg0: receiver.
-// Arg1: ic-data.
-// Arg2: original arguments descriptor array.
-// Arg3: original arguments array.
-DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodFunction, 4) {
- ASSERT(arguments.ArgCount() ==
- kInvokeNoSuchMethodFunctionRuntimeEntry.argument_count());
- const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
- const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
- const String& original_function_name = String::Handle(ic_data.target_name());
- const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(2));
- const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(3));
+static RawObject* InvokeNonClosure(const Instance& receiver,
+ const Class& receiver_class,
+ const Array& arguments_descriptor,
+ const Array& arguments) {
+ // Resolve and invoke the "call" method if it exists.
+ const String& call_symbol = String::Handle(Symbols::Call());
+
+ Class& current_class = Class::Handle(receiver_class.raw());
+ Function& call_function = Function::Handle();
+ do {
+ call_function = current_class.LookupDynamicFunction(call_symbol);
+
+ if (!call_function.IsNull()) {
+ const Instructions& instrs =
+ Instructions::Handle(EnsureCompiled(call_function));
+ // The non-closure object is passed as implicit first argument
+ // (receiver). It is already included in the arguments array.
+ GrowableArray<const Object*> invoke_arguments(arguments.Length());
+ for (intptr_t i = 0; i < arguments.Length(); i++) {
+ const Object& value = Object::Handle(arguments.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(),
+ arguments_descriptor,
+ invoke_arguments.data(),
+ context));
+ CheckResultError(result);
+ return result.raw();
+ }
+
+ current_class = current_class.SuperClass();
+ } while (!current_class.IsNull());
+
+ const Object& null_object = Object::Handle();
+ GrowableArray<const Object*> dart_arguments(5);
+ dart_arguments.Add(&receiver);
+ dart_arguments.Add(&call_symbol);
+ dart_arguments.Add(&arguments);
+ 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();
+ return Object::null();
+}
+
+
+// An instance call of the form o.f(...) could not be resolved. Check if
+// there is a getter with the same name. If so, invoke it. If the value is
+// a closure, invoke it with the given arguments. If the value is a
+// non-closure, attempt to invoke "call" on it.
+static bool ResolveCallThroughGetter(const Instance& receiver,
+ const Class& receiver_class,
+ const String& target_name,
+ const Array& arguments_descriptor,
+ const Array& arguments,
+ Object* result) {
+ // 1. Check if there is a getter with the same name.
+ const String& getter_name = String::Handle(Field::GetterName(target_name));
+ const int kNumArguments = 1;
+ const int kNumNamedArguments = 0;
+ const Function& getter = Function::ZoneHandle(
+ Resolver::ResolveDynamicForReceiverClass(receiver_class,
+ getter_name,
+ kNumArguments,
+ kNumNamedArguments));
+ if (getter.IsNull()) return false;
+
+ // 2. Invoke the getter.
+ GrowableArray<const Object*> invoke_arguments(0);
+ const Array& kNoArgumentNames = Array::Handle();
+ const Object& value =
+ Object::Handle(DartEntry::InvokeDynamic(receiver,
+ getter,
+ invoke_arguments,
+ kNoArgumentNames));
+
+ // 3. If the getter threw an exception, treat it as no such method.
+ if (value.IsUnhandledException()) return false;
+
+ // 4. If there was some other error, propagate it.
+ if (value.IsError()) {
+ Exceptions::PropagateError(Error::Cast(value));
+ UNREACHABLE();
+ }
+
+ // 5. If the value is a closure, invoke it and return the result. If it
+ // is a non-closure, invoke "call" on it and return the result.
+ Instance& instance = Instance::Handle();
+ instance ^= value.raw();
Kevin Millikin (Google) 2012/12/12 14:18:38 I'm not sure what compels value to be an Instance.
regis 2012/12/12 17:37:38 I am not sure it answers your question, but all va
+ const Class& instance_class = Class::Handle(instance.clazz());
+ ASSERT(!instance_class.IsNull());
+ // An object is a closure iff. its class has a non-null signature function.
+ if (instance_class.signature_function() != Function::null()) {
+ *result = InvokeClosure(instance, arguments_descriptor, arguments);
+ } else {
+ *result = InvokeNonClosure(instance,
+ instance_class,
+ arguments_descriptor,
+ arguments);
+ }
+ return true;
+}
+
+
+static RawObject* InvokeNoSuchMethod(const Instance& receiver,
+ const String& target_name,
+ const Array& arguments_descriptor,
+ const Array& arguments) {
// Allocate an InvocationMirror object.
const Library& core_lib = Library::Handle(Library::CoreLibrary());
- const String& invocation_mirror_name = String::Handle(
- Symbols::InvocationMirror());
- Class& invocation_mirror_class = Class::Handle(
- core_lib.LookupClassAllowPrivate(invocation_mirror_name));
+ const String& invocation_mirror_name =
+ String::Handle(Symbols::InvocationMirror());
+ Class& invocation_mirror_class =
+ Class::Handle(core_lib.LookupClassAllowPrivate(invocation_mirror_name));
ASSERT(!invocation_mirror_class.IsNull());
- const String& allocation_function_name = String::Handle(
- Symbols::AllocateInvocationMirror());
+ const String& allocation_function_name =
+ String::Handle(Symbols::AllocateInvocationMirror());
const Function& allocation_function = Function::ZoneHandle(
Resolver::ResolveStaticByName(invocation_mirror_class,
allocation_function_name,
Resolver::kIsQualified));
ASSERT(!allocation_function.IsNull());
GrowableArray<const Object*> allocation_arguments(3);
- allocation_arguments.Add(&original_function_name);
- allocation_arguments.Add(&orig_arguments_desc);
- allocation_arguments.Add(&orig_arguments);
+ allocation_arguments.Add(&target_name);
+ allocation_arguments.Add(&arguments_descriptor);
+ allocation_arguments.Add(&arguments);
const Array& kNoArgumentNames = Array::Handle();
- const Object& invocation_mirror = Object::Handle(
- DartEntry::InvokeStatic(allocation_function,
- allocation_arguments,
- kNoArgumentNames));
+ const Object& invocation_mirror =
+ Object::Handle(DartEntry::InvokeStatic(allocation_function,
+ allocation_arguments,
+ kNoArgumentNames));
+ const String& function_name = String::Handle(Symbols::NoSuchMethod());
const int kNumArguments = 2;
const int kNumNamedArguments = 0;
- const String& function_name = String::Handle(Symbols::NoSuchMethod());
- const Function& function = Function::ZoneHandle(
- Resolver::ResolveDynamic(receiver,
- function_name,
- kNumArguments,
- kNumNamedArguments));
+ const Function& function =
+ Function::ZoneHandle(Resolver::ResolveDynamic(receiver,
+ function_name,
+ kNumArguments,
+ kNumNamedArguments));
ASSERT(!function.IsNull());
GrowableArray<const Object*> invoke_arguments(1);
invoke_arguments.Add(&invocation_mirror);
- const Object& result = Object::Handle(
- DartEntry::InvokeDynamic(receiver,
- function,
- invoke_arguments,
- kNoArgumentNames));
+ const Object& result =
+ Object::Handle(DartEntry::InvokeDynamic(receiver,
+ function,
+ invoke_arguments,
+ kNoArgumentNames));
CheckResultError(result);
+ return result.raw();
+}
+
+
+// Invoke appropriate noSuchMethod function.
+// Arg0: receiver.
+// Arg1: ic-data.
+// Arg2: arguments descriptor array.
+// Arg3: arguments array.
+DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodFunction, 4) {
+ ASSERT(arguments.ArgCount() ==
+ kInvokeNoSuchMethodFunctionRuntimeEntry.argument_count());
+ const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
+ const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
+ const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(2));
+ const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(3));
+
+ const String& original_function_name = String::Handle(ic_data.target_name());
+ const Object& result =
+ Object::Handle(InvokeNoSuchMethod(receiver,
+ original_function_name,
+ orig_arguments_desc,
+ orig_arguments));
arguments.SetReturn(result);
}
@@ -1375,60 +1367,60 @@ DEFINE_RUNTIME_ENTRY(InvokeNonClosure, 3) {
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());
- 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()) {
- if (!function.HasCode()) {
- const Error& error = Error::Handle(Compiler::CompileFunction(function));
- if (!error.IsNull()) {
- Exceptions::PropagateError(error);
- }
- }
- 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);
- }
+ const Class& instance_class = Class::Handle(instance.clazz());
+ const Object& result = Object::Handle(InvokeNonClosure(instance,
+ instance_class,
+ args_descriptor,
+ function_args));
+ arguments.SetReturn(result);
+}
+
+
+// The IC miss handler has failed to find a (cacheable) instance function to
+// invoke. Handle three possibilities:
+//
+// 1. If the call was a getter o.f, there may be an instance function with
+// the same name. If so, create an implicit closure and return it.
+//
+// 2. If the call was an instance call o.f(...), there may be a getter with
+// the same name. If so, invoke it. If the value is a closure, invoke
+// it with the given arguments. If the value is a non-closure, attempt
+// to invoke "call" on it.
+//
+// 3. There is no such method.
+DEFINE_RUNTIME_ENTRY(InstanceFunctionLookup, 4) {
+ ASSERT(arguments.ArgCount() ==
+ kInstanceFunctionLookupRuntimeEntry.argument_count());
+ const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
+ const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
+ const Array& args_descriptor = Array::CheckedHandle(arguments.ArgAt(2));
+ const Array& args = Array::CheckedHandle(arguments.ArgAt(3));
+
+ Class& receiver_class = Class::Handle(receiver.clazz());
+ // For lookups treat null as an instance of class Object.
+ if (receiver_class.IsNullClass()) {
+ receiver_class = isolate->object_store()->object_class();
+ }
+ const String& target_name = String::Handle(ic_data.target_name());
- // 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);
+ Instance& closure = Instance::Handle(ResolveImplicitClosure(receiver,
+ receiver_class,
+ target_name));
+ if (!closure.IsNull()) {
+ arguments.SetReturn(closure);
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();
+
+ Object& result = Object::Handle();
+ if (!ResolveCallThroughGetter(receiver,
+ receiver_class,
+ target_name,
+ args_descriptor,
+ args,
+ &result)) {
+ result = InvokeNoSuchMethod(receiver, target_name, args_descriptor, args);
+ }
+ arguments.SetReturn(result);
}
« no previous file with comments | « runtime/vm/code_generator.h ('k') | runtime/vm/stub_code_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698