Index: runtime/vm/flow_graph_builder.cc |
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc |
index ac1b47f0d1d4df6430059f500ad59b534d64539d..568450335f21e6a4ba1fce68c7353cd30ccea2c5 100644 |
--- a/runtime/vm/flow_graph_builder.cc |
+++ b/runtime/vm/flow_graph_builder.cc |
@@ -2707,31 +2707,61 @@ StaticCallInstr* EffectGraphVisitor::BuildStaticNoSuchMethodCall( |
AstNode* receiver, |
const String& method_name, |
ArgumentListNode* method_arguments) { |
- const String& no_such_method_name = |
- String::ZoneHandle(Symbols::NoSuchMethod()); |
- const Function& no_such_method_func = Function::ZoneHandle( |
- Resolver::ResolveDynamicAnyArgs(target_class, no_such_method_name)); |
- // We are guaranteed to find noSuchMethod of class Object. |
- ASSERT(!no_such_method_func.IsNull()); |
+ // Build the graph to allocate an InvocationMirror object by calling |
+ // the static allocation method. |
+ const String& mirror_name = String::Handle(Symbols::InvocationMirror()); |
+ const Library& corelib = Library::Handle(Library::CoreLibrary()); |
+ const Class& mirror_class = Class::Handle( |
+ corelib.LookupClassAllowPrivate(mirror_name)); |
+ ASSERT(!mirror_class.IsNull()); |
+ const String& function_name = String::Handle( |
+ Symbols::AllocateInvocationMirror()); |
+ const Function& allocation_function = Function::ZoneHandle( |
+ Resolver::ResolveStaticByName(mirror_class, |
+ function_name, |
+ Resolver::kIsQualified)); |
+ ASSERT(!allocation_function.IsNull()); |
+ |
+ // Evaluate the receiver before the arguments. This will be used |
+ // as an argument to the noSuchMethod call. |
+ ValueGraphVisitor for_receiver(owner(), temp_index()); |
+ receiver->Visit(&for_receiver); |
+ Append(for_receiver); |
+ PushArgumentInstr* push_receiver = PushArgument(for_receiver.value()); |
+ // Allocate the arguments and pass them into the construction |
+ // of the InvocationMirror. |
const intptr_t args_pos = method_arguments->token_pos(); |
ArgumentListNode* arguments = new ArgumentListNode(args_pos); |
- // The first argument is the receiver. |
- arguments->Add(receiver); |
- // The second argument is the original method name. |
- // TODO(regis): This will change once mirrors are supported. |
+ // The first argument is the original method name. |
arguments->Add(new LiteralNode(args_pos, method_name)); |
- // The third argument is an array containing the original method arguments. |
+ // The second argument is an array containing the original method arguments. |
ArrayNode* args_array = |
new ArrayNode(args_pos, Type::ZoneHandle(Type::ListInterface())); |
for (intptr_t i = 0; i < method_arguments->length(); i++) { |
args_array->AddElement(method_arguments->NodeAt(i)); |
} |
arguments->Add(args_array); |
- |
- ZoneGrowableArray<PushArgumentInstr*>* args = |
+ ZoneGrowableArray<PushArgumentInstr*>* allocation_args = |
new ZoneGrowableArray<PushArgumentInstr*>(arguments->length()); |
- BuildPushArguments(*arguments, args); |
+ BuildPushArguments(*arguments, allocation_args); |
+ StaticCallInstr* allocation = new StaticCallInstr(args_pos, |
+ allocation_function, |
+ Array::ZoneHandle(), |
+ allocation_args); |
+ Value* invocation_mirror = Bind(allocation); |
+ PushArgumentInstr* push_invocation_mirror = PushArgument(invocation_mirror); |
+ // Lookup noSuchMethod and call it with the receiver and the InvocationMirror. |
+ const String& no_such_method_name = |
+ String::ZoneHandle(Symbols::NoSuchMethod()); |
+ const Function& no_such_method_func = Function::ZoneHandle( |
+ Resolver::ResolveDynamicAnyArgs(target_class, no_such_method_name)); |
+ // We are guaranteed to find noSuchMethod of class Object. |
+ ASSERT(!no_such_method_func.IsNull()); |
+ ZoneGrowableArray<PushArgumentInstr*>* args = |
+ new ZoneGrowableArray<PushArgumentInstr*>(2); |
+ args->Add(push_receiver); |
+ args->Add(push_invocation_mirror); |
return new StaticCallInstr(args_pos, |
no_such_method_func, |
Array::ZoneHandle(), |