Chromium Code Reviews| Index: runtime/vm/flow_graph_builder.cc |
| =================================================================== |
| --- runtime/vm/flow_graph_builder.cc (revision 7716) |
| +++ runtime/vm/flow_graph_builder.cc (working copy) |
| @@ -266,7 +266,7 @@ |
| owner()->parsed_function().function().result_type()); |
| const String& dst_name = |
| String::ZoneHandle(String::NewSymbol("function result")); |
| - return_value = BuildAssignableValue(node->value(), |
| + return_value = BuildAssignableValue(node->value()->token_index(), |
| return_value, |
| dst_type, |
| dst_name); |
| @@ -382,7 +382,7 @@ |
| ValueGraphVisitor for_value(owner(), temp_index()); |
| node->expr()->Visit(&for_value); |
| Append(for_value); |
| - ReturnValue(BuildAssignableValue(node->expr(), |
| + ReturnValue(BuildAssignableValue(node->expr()->token_index(), |
| for_value.value(), |
| node->type(), |
| node->dst_name())); |
| @@ -576,48 +576,78 @@ |
| } |
| -void EffectGraphVisitor::BuildAssertAssignable(intptr_t token_index, |
| - Value* value, |
| - const AbstractType& dst_type, |
| - const String& dst_name) { |
| +void EffectGraphVisitor::BuildTypecheckArguments( |
| + intptr_t token_index, |
| + Value** instantiator_result, |
| + Value** instantiator_type_arguments_result) { |
| + Value* instantiator = NULL; |
| + Value* instantiator_type_arguments = NULL; |
| + const Class& instantiator_class = Class::Handle( |
| + owner()->parsed_function().function().owner()); |
| + if (instantiator_class.NumTypeParameters() > 0) { |
|
regis
2012/05/18 00:41:38
This does not look correct. The instantiator may h
|
| + instantiator = BuildInstantiator(); |
| + if (instantiator == NULL) { |
| + instantiator_type_arguments = |
| + BuildInstantiatorTypeArguments(token_index, NULL); |
| + } else { |
| + // Preserve instantiator. |
| + const LocalVariable& expr_temp = |
| + *owner()->parsed_function().expression_temp_var(); |
| + Definition* saved = |
| + new BindInstr(BuildStoreLocal(expr_temp, instantiator)); |
| + AddInstruction(saved); |
| + instantiator = new UseVal(saved); |
| + Definition* loaded = new BindInstr(BuildLoadLocal(expr_temp)); |
| + AddInstruction(loaded); |
| + instantiator_type_arguments = |
| + BuildInstantiatorTypeArguments(token_index, new UseVal(loaded)); |
| + } |
| + } else { |
| + instantiator_type_arguments = |
| + BuildInstantiatorTypeArguments(token_index, NULL); |
| + } |
| + *instantiator_result = instantiator; |
| + *instantiator_type_arguments_result = instantiator_type_arguments; |
| +} |
| + |
| + |
| +// Used for testing incoming arguments. |
| +AssertAssignableComp* EffectGraphVisitor::BuildAssertAssignable( |
| + intptr_t token_index, |
| + Value* value, |
| + const AbstractType& dst_type, |
| + const String& dst_name) { |
| // Build the type check computation. |
| + Value* instantiator = NULL; |
| Value* instantiator_type_arguments = NULL; |
| if (!dst_type.IsInstantiated()) { |
| - instantiator_type_arguments = |
| - BuildInstantiatorTypeArguments(token_index); |
| + BuildTypecheckArguments(token_index, |
| + &instantiator, |
| + &instantiator_type_arguments); |
| } |
| - AssertAssignableComp* assert_assignable = |
| - new AssertAssignableComp(token_index, |
| - owner()->try_index(), |
| - value, |
| - instantiator_type_arguments, |
| - dst_type, |
| - dst_name); |
| - AddInstruction(new DoInstr(assert_assignable)); |
| + return new AssertAssignableComp(token_index, |
| + owner()->try_index(), |
| + value, |
| + instantiator, |
| + instantiator_type_arguments, |
| + dst_type, |
| + dst_name); |
| } |
| -Value* EffectGraphVisitor::BuildAssignableValue(AstNode* value_node, |
| +// Used to to test assignments. |
| +Value* EffectGraphVisitor::BuildAssignableValue(intptr_t token_index, |
| Value* value, |
| const AbstractType& dst_type, |
| const String& dst_name) { |
| if (CanSkipTypeCheck(value, dst_type)) { |
| return value; |
| } |
| - |
| - // Build the type check computation. |
| - Value* instantiator_type_arguments = NULL; |
| - if (!dst_type.IsInstantiated()) { |
| - instantiator_type_arguments = |
| - BuildInstantiatorTypeArguments(value_node->token_index()); |
| - } |
| - BindInstr* assert_assignable = |
| - new BindInstr(new AssertAssignableComp(value_node->token_index(), |
| - owner()->try_index(), |
| - value, |
| - instantiator_type_arguments, |
| - dst_type, |
| - dst_name)); |
| + AssertAssignableComp* comp = BuildAssertAssignable(token_index, |
| + value, |
| + dst_type, |
| + dst_name); |
| + Definition* assert_assignable = new BindInstr(comp); |
| AddInstruction(assert_assignable); |
| return new UseVal(assert_assignable); |
| } |
| @@ -683,15 +713,18 @@ |
| ValueGraphVisitor for_left_value(owner(), temp_index()); |
| node->left()->Visit(&for_left_value); |
| Append(for_left_value); |
| + Value* instantiator = NULL; |
| Value* type_arguments = NULL; |
| if (!type.IsInstantiated()) { |
| - type_arguments = |
| - BuildInstantiatorTypeArguments(node->token_index()); |
| + BuildTypecheckArguments(node->token_index(), |
| + &instantiator, |
| + &type_arguments); |
| } |
| InstanceOfComp* instance_of = |
| new InstanceOfComp(node->token_index(), |
| owner()->try_index(), |
| for_left_value.value(), |
| + instantiator, |
| type_arguments, |
| node->right()->AsTypeNode()->type(), |
| (node->kind() == Token::kISNOT)); |
| @@ -1285,8 +1318,7 @@ |
| Value* type_arguments = NULL; |
| if (requires_type_arguments) { |
| ASSERT(!function.IsImplicitStaticClosureFunction()); |
| - type_arguments = |
| - BuildInstantiatorTypeArguments(node->token_index()); |
| + type_arguments = BuildInstantiatorTypeArguments(node->token_index(), NULL); |
| } |
| CreateClosureComp* create = |
| @@ -1467,8 +1499,33 @@ |
| } |
| +Value* EffectGraphVisitor::BuildInstantiator() { |
| + const Class& instantiator_class = Class::Handle( |
| + owner()->parsed_function().function().owner()); |
| + if (instantiator_class.NumTypeParameters() == 0) { |
| + return NULL; |
| + } |
| + Function& outer_function = |
| + Function::Handle(owner()->parsed_function().function().raw()); |
| + while (outer_function.IsLocalFunction()) { |
| + outer_function = outer_function.parent_function(); |
| + } |
| + if (outer_function.IsFactory()) { |
| + return NULL; |
| + } |
| + |
| + ASSERT(owner()->parsed_function().instantiator() != NULL); |
| + ValueGraphVisitor for_instantiator(owner(), temp_index()); |
| + owner()->parsed_function().instantiator()->Visit(&for_instantiator); |
| + Append(for_instantiator); |
| + return for_instantiator.value(); |
| +} |
| + |
| + |
| +// 'expression_temp_var' may not be used inside this method if 'instantiator' |
| +// is not NULL. |
| Value* EffectGraphVisitor::BuildInstantiatorTypeArguments( |
| - intptr_t token_index) { |
| + intptr_t token_index, Value* instantiator) { |
| const Class& instantiator_class = Class::Handle( |
| owner()->parsed_function().function().owner()); |
| if (instantiator_class.NumTypeParameters() == 0) { |
| @@ -1484,20 +1541,23 @@ |
| AddInstruction(args); |
| return new UseVal(args); |
| } |
| - ASSERT(owner()->parsed_function().instantiator() != NULL); |
| - ValueGraphVisitor for_instantiator(owner(), temp_index()); |
| - owner()->parsed_function().instantiator()->Visit(&for_instantiator); |
| - Append(for_instantiator); |
| Function& outer_function = |
| Function::Handle(owner()->parsed_function().function().raw()); |
| while (outer_function.IsLocalFunction()) { |
| outer_function = outer_function.parent_function(); |
| } |
| if (outer_function.IsFactory()) { |
| - // All OK. |
| + // No instantiator for factories. |
| + ASSERT(instantiator == NULL); |
| + ASSERT(owner()->parsed_function().instantiator() != NULL); |
| + ValueGraphVisitor for_instantiator(owner(), temp_index()); |
| + owner()->parsed_function().instantiator()->Visit(&for_instantiator); |
| + Append(for_instantiator); |
| return for_instantiator.value(); |
| } |
| - |
| + if (instantiator == NULL) { |
| + instantiator = BuildInstantiator(); |
| + } |
| // The instantiator is the receiver of the caller, which is not a factory. |
| // The receiver cannot be null; extract its AbstractTypeArguments object. |
| // Note that in the factory case, the instantiator is the first parameter |
| @@ -1508,7 +1568,7 @@ |
| BindInstr* load = |
| new BindInstr(new NativeLoadFieldComp( |
| - for_instantiator.value(), |
| + instantiator, |
| type_arguments_instance_field_offset, |
| Type::ZoneHandle())); // Not an instance, no type. |
| AddInstruction(load); |
| @@ -1526,7 +1586,8 @@ |
| return type_args; |
| } |
| // The type arguments are uninstantiated. |
| - Value* instantiator_value = BuildInstantiatorTypeArguments(token_index); |
| + Value* instantiator_value = |
| + BuildInstantiatorTypeArguments(token_index, NULL); |
| BindInstr* instantiate = |
| new BindInstr(new InstantiateTypeArgumentsComp(token_index, |
| owner()->try_index(), |
| @@ -1568,10 +1629,11 @@ |
| ASSERT(owner()->parsed_function().expression_temp_var() != NULL); |
| const LocalVariable& t1 = *owner()->parsed_function().expression_temp_var(); |
| const LocalVariable& t2 = node->allocated_object_var(); |
| - Value* instantiator = BuildInstantiatorTypeArguments(node->token_index()); |
| - ASSERT(instantiator->IsUse()); |
| + Value* instantiator_type_arguments = BuildInstantiatorTypeArguments( |
| + node->token_index(), NULL); |
| + ASSERT(instantiator_type_arguments->IsUse()); |
| Definition* stored_instantiator = new BindInstr( |
| - BuildStoreLocal(t1, instantiator)); |
| + BuildStoreLocal(t1, instantiator_type_arguments)); |
| AddInstruction(stored_instantiator); |
| // t1: instantiator type arguments. |
| @@ -1740,7 +1802,7 @@ |
| Append(for_value); |
| Value* store_value = for_value.value(); |
| if (FLAG_enable_type_checks) { |
| - store_value = BuildAssignableValue(node->value(), |
| + store_value = BuildAssignableValue(node->value()->token_index(), |
| store_value, |
| node->local().type(), |
| node->local().name()); |
| @@ -1773,7 +1835,7 @@ |
| if (FLAG_enable_type_checks) { |
| const AbstractType& type = AbstractType::ZoneHandle(node->field().type()); |
| const String& dst_name = String::ZoneHandle(node->field().name()); |
| - store_value = BuildAssignableValue(node->value(), |
| + store_value = BuildAssignableValue(node->value()->token_index(), |
| store_value, |
| type, |
| dst_name); |
| @@ -1798,7 +1860,7 @@ |
| if (FLAG_enable_type_checks) { |
| const AbstractType& type = AbstractType::ZoneHandle(node->field().type()); |
| const String& dst_name = String::ZoneHandle(node->field().name()); |
| - store_value = BuildAssignableValue(node->value(), |
| + store_value = BuildAssignableValue(node->value()->token_index(), |
| store_value, |
| type, |
| dst_name); |
| @@ -1969,10 +2031,12 @@ |
| if (!CanSkipTypeCheck(NULL, parameter.type())) { |
| BindInstr* load = new BindInstr(BuildLoadLocal(parameter)); |
| AddInstruction(load); |
| - BuildAssertAssignable(parameter.token_index(), |
| - new UseVal(load), |
| - parameter.type(), |
| - parameter.name()); |
| + AssertAssignableComp* assert_assignable = |
| + BuildAssertAssignable(parameter.token_index(), |
| + new UseVal(load), |
| + parameter.type(), |
| + parameter.name()); |
| + AddInstruction(new DoInstr(assert_assignable)); |
| } |
| pos++; |
| } |