Index: runtime/vm/flow_graph_builder.cc |
=================================================================== |
--- runtime/vm/flow_graph_builder.cc (revision 14156) |
+++ runtime/vm/flow_graph_builder.cc (working copy) |
@@ -2002,7 +2002,7 @@ |
if (node->is_super_getter()) { |
// Statically resolved instance getter, i.e. "super getter". |
getter_function = |
- Resolver::ResolveDynamicAnyArgs(node->cls(), getter_name); |
+ Resolver::ResolveDynamicAnyArgs(node->cls(), getter_name); |
ASSERT(!getter_function.IsNull()); |
ASSERT(node->receiver() != NULL); |
ValueGraphVisitor receiver_value(owner(), temp_index()); |
@@ -2265,6 +2265,26 @@ |
void EffectGraphVisitor::VisitLoadIndexedNode(LoadIndexedNode* node) { |
+ Function* super_function = NULL; |
+ if (node->IsSuperLoad()) { |
+ // Resolve the load indexed operator in the super class. |
+ const String& index_operator_name = |
+ String::ZoneHandle(Symbols::IndexToken()); |
+ super_function = &Function::ZoneHandle( |
+ Resolver::ResolveDynamicAnyArgs(node->super_class(), |
+ index_operator_name)); |
+ if (super_function->IsNull()) { |
+ // Could not resolve super operator. Generate call noSuchMethod() of the |
+ // super class instead. |
+ ArgumentListNode* arguments = new ArgumentListNode(node->token_pos()); |
+ arguments->Add(node->index_expr()); |
+ BuildStaticNoSuchMethodCall(node->super_class(), |
+ node->array(), |
+ index_operator_name, |
+ arguments); |
+ return; |
+ } |
+ } |
ZoneGrowableArray<PushArgumentInstr*>* arguments = |
new ZoneGrowableArray<PushArgumentInstr*>(2); |
ValueGraphVisitor for_array(owner(), temp_index()); |
@@ -2277,22 +2297,67 @@ |
Append(for_index); |
arguments->Add(PushArgument(for_index.value())); |
- const intptr_t checked_argument_count = 1; |
- const String& name = |
- String::ZoneHandle(Symbols::New(Token::Str(Token::kINDEX))); |
- InstanceCallInstr* load = new InstanceCallInstr(node->token_pos(), |
- name, |
- Token::kINDEX, |
- arguments, |
- Array::ZoneHandle(), |
- checked_argument_count); |
- ReturnDefinition(load); |
+ if (super_function != NULL) { |
+ // Generate static call to super operator. |
+ StaticCallInstr* load = new StaticCallInstr(node->token_pos(), |
+ *super_function, |
+ Array::ZoneHandle(), |
+ arguments); |
+ ReturnDefinition(load); |
+ } else { |
+ // Generate dynamic call to index operator. |
+ const intptr_t checked_argument_count = 1; |
+ const String& name = String::ZoneHandle(Symbols::IndexToken()); |
+ InstanceCallInstr* load = new InstanceCallInstr(node->token_pos(), |
+ name, |
+ Token::kINDEX, |
+ arguments, |
+ Array::ZoneHandle(), |
+ checked_argument_count); |
+ ReturnDefinition(load); |
+ } |
} |
Definition* EffectGraphVisitor::BuildStoreIndexedValues( |
StoreIndexedNode* node, |
bool result_is_needed) { |
+ Function* super_function = NULL; |
+ if (node->IsSuperStore()) { |
+ // Resolve the store indexed operator in the super class. |
+ const String& store_index_op_name = |
+ String::ZoneHandle(Symbols::AssignIndexToken()); |
+ super_function = &Function::ZoneHandle( |
+ Resolver::ResolveDynamicAnyArgs(node->super_class(), |
+ store_index_op_name)); |
+ if (super_function->IsNull()) { |
+ // Could not resolve super operator. Generate call noSuchMethod() of the |
+ // super class instead. |
+ if (result_is_needed) { |
+ // Even though noSuchMethod most likely does not return, |
+ // we save the stored value if the result is needed. |
+ ValueGraphVisitor for_value(owner(), temp_index()); |
+ node->value()->Visit(&for_value); |
+ Append(for_value); |
+ Bind(BuildStoreExprTemp(for_value.value())); |
+ } |
+ ArgumentListNode* arguments = new ArgumentListNode(node->token_pos()); |
+ arguments->Add(node->index_expr()); |
+ arguments->Add(node->value()); |
+ StaticCallInstr* call = |
+ BuildStaticNoSuchMethodCall(node->super_class(), |
+ node->array(), |
+ store_index_op_name, |
+ arguments); |
+ if (result_is_needed) { |
+ Do(call); |
+ return BuildLoadExprTemp(); |
+ } else { |
+ return call; |
+ } |
+ } |
+ } |
+ |
ZoneGrowableArray<PushArgumentInstr*>* arguments = |
new ZoneGrowableArray<PushArgumentInstr*>(3); |
ValueGraphVisitor for_array(owner(), temp_index()); |
@@ -2316,20 +2381,38 @@ |
} |
arguments->Add(PushArgument(value)); |
- const intptr_t checked_argument_count = 3; |
- const String& name = |
- String::ZoneHandle(Symbols::New(Token::Str(Token::kASSIGN_INDEX))); |
- InstanceCallInstr* store = new InstanceCallInstr(node->token_pos(), |
- name, |
- Token::kASSIGN_INDEX, |
- arguments, |
- Array::ZoneHandle(), |
- checked_argument_count); |
- if (result_is_needed) { |
- Do(store); |
- return BuildLoadExprTemp(); |
+ if (super_function != NULL) { |
+ // Generate static call to super operator []=. |
+ |
+ StaticCallInstr* store = |
+ new StaticCallInstr(node->token_pos(), |
+ *super_function, |
+ Array::ZoneHandle(), |
+ arguments); |
+ if (result_is_needed) { |
+ Do(store); |
+ return BuildLoadExprTemp(); |
+ } else { |
+ return store; |
+ } |
} else { |
- return store; |
+ // Generate dynamic call to operator []=. |
+ const intptr_t checked_argument_count = 3; |
+ const String& name = |
+ String::ZoneHandle(Symbols::New(Token::Str(Token::kASSIGN_INDEX))); |
+ InstanceCallInstr* store = |
+ new InstanceCallInstr(node->token_pos(), |
+ name, |
+ Token::kASSIGN_INDEX, |
+ arguments, |
+ Array::ZoneHandle(), |
+ checked_argument_count); |
+ if (result_is_needed) { |
+ Do(store); |
+ return BuildLoadExprTemp(); |
+ } else { |
+ return store; |
+ } |
} |
} |
@@ -2583,6 +2666,45 @@ |
} |
+// Looks up dynamic method noSuchMethod in target_class |
+// (including its super class chain) and builds a static call to it. |
+StaticCallInstr* EffectGraphVisitor::BuildStaticNoSuchMethodCall( |
+ const Class& target_class, |
+ 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()); |
+ |
+ 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. |
+ arguments->Add(new LiteralNode(args_pos, method_name)); |
+ // The third 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 = |
+ new ZoneGrowableArray<PushArgumentInstr*>(arguments->length()); |
+ BuildPushArguments(*arguments, args); |
+ return new StaticCallInstr(args_pos, |
+ no_such_method_func, |
+ Array::ZoneHandle(), |
+ args); |
+} |
+ |
+ |
void EffectGraphVisitor::BuildThrowNode(ThrowNode* node) { |
// TODO(kmillikin) non-local control flow is not handled correctly |
// by the inliner. |