| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dart2js.ir_builder_task; | 5 library dart2js.ir_builder_task; |
| 6 | 6 |
| 7 import '../closure.dart' as closurelib; | 7 import '../closure.dart' as closurelib; |
| 8 import '../closure.dart' hide ClosureScope; | 8 import '../closure.dart' hide ClosureScope; |
| 9 import '../constants/expressions.dart'; | 9 import '../constants/expressions.dart'; |
| 10 import '../dart_types.dart'; | 10 import '../dart_types.dart'; |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 /// Normalizes the argument list of a dynamic invocation (i.e. where the | 215 /// Normalizes the argument list of a dynamic invocation (i.e. where the |
| 216 /// target element is unknown). | 216 /// target element is unknown). |
| 217 /// | 217 /// |
| 218 /// For the JS backend, normalizes order of named arguments. | 218 /// For the JS backend, normalizes order of named arguments. |
| 219 /// | 219 /// |
| 220 /// For the Dart backend, returns [arguments]. | 220 /// For the Dart backend, returns [arguments]. |
| 221 List<ir.Primitive> normalizeDynamicArguments( | 221 List<ir.Primitive> normalizeDynamicArguments( |
| 222 CallStructure callStructure, | 222 CallStructure callStructure, |
| 223 List<ir.Primitive> arguments); | 223 List<ir.Primitive> arguments); |
| 224 | 224 |
| 225 /// Read the value of [field]. |
| 226 ir.Primitive buildStaticFieldGet(FieldElement field, SourceInformation src); |
| 227 |
| 225 /// Creates a [TypedSelector] variant of [newSelector] using the type of | 228 /// Creates a [TypedSelector] variant of [newSelector] using the type of |
| 226 /// [oldSelector], if available. | 229 /// [oldSelector], if available. |
| 227 /// | 230 /// |
| 228 /// This is needed to preserve inferred receiver types when creating new | 231 /// This is needed to preserve inferred receiver types when creating new |
| 229 /// selectors. | 232 /// selectors. |
| 230 Selector useSelectorType(Selector newSelector, Selector oldSelector) { | 233 Selector useSelectorType(Selector newSelector, Selector oldSelector) { |
| 231 // TODO(asgerf,johnniwinther): This works but it is brittle. | 234 // TODO(asgerf,johnniwinther): This works but it is brittle. |
| 232 // We should decouple selectors from inferred receiver type masks. | 235 // We should decouple selectors from inferred receiver type masks. |
| 233 // TODO(asgerf): Use this whenever we create a selector for a dynamic call. | 236 // TODO(asgerf): Use this whenever we create a selector for a dynamic call. |
| 234 if (oldSelector is TypedSelector) { | 237 if (oldSelector is TypedSelector) { |
| (...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 748 | 751 |
| 749 @override | 752 @override |
| 750 ir.Primitive visitLocalFunctionGet( | 753 ir.Primitive visitLocalFunctionGet( |
| 751 ast.Send node, | 754 ast.Send node, |
| 752 LocalFunctionElement function, | 755 LocalFunctionElement function, |
| 753 _) { | 756 _) { |
| 754 return irBuilder.buildLocalFunctionGet(function); | 757 return irBuilder.buildLocalFunctionGet(function); |
| 755 } | 758 } |
| 756 | 759 |
| 757 @override | 760 @override |
| 758 ir.Primitive handleStaticFieldGet(ast.Send node, FieldElement field, _) { | |
| 759 return field.isConst | |
| 760 ? irBuilder.buildConstant(getConstantForVariable(field)) | |
| 761 : irBuilder.buildStaticFieldGet(field, | |
| 762 sourceInformation: sourceInformationBuilder.buildGet(node)); | |
| 763 } | |
| 764 | |
| 765 @override | |
| 766 ir.Primitive handleStaticFunctionGet( | 761 ir.Primitive handleStaticFunctionGet( |
| 767 ast.Send node, | 762 ast.Send node, |
| 768 MethodElement function, | 763 MethodElement function, |
| 769 _) { | 764 _) { |
| 770 // TODO(karlklose): support foreign functions. | 765 // TODO(karlklose): support foreign functions. |
| 771 if (function.isForeign(compiler.backend)) { | 766 if (function.isForeign(compiler.backend)) { |
| 772 return giveup(node, 'handleStaticFunctionGet: foreign: $function'); | 767 return giveup(node, 'handleStaticFunctionGet: foreign: $function'); |
| 773 } | 768 } |
| 774 return irBuilder.buildStaticFunctionGet(function); | 769 return irBuilder.buildStaticFunctionGet(function); |
| 775 } | 770 } |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1081 ast.Send node, | 1076 ast.Send node, |
| 1082 LocalFunctionElement function, | 1077 LocalFunctionElement function, |
| 1083 ast.NodeList arguments, | 1078 ast.NodeList arguments, |
| 1084 CallStructure callStructure, | 1079 CallStructure callStructure, |
| 1085 _) { | 1080 _) { |
| 1086 return irBuilder.buildLocalFunctionInvocation(function, callStructure, | 1081 return irBuilder.buildLocalFunctionInvocation(function, callStructure, |
| 1087 translateDynamicArguments(arguments, callStructure)); | 1082 translateDynamicArguments(arguments, callStructure)); |
| 1088 } | 1083 } |
| 1089 | 1084 |
| 1090 @override | 1085 @override |
| 1086 ir.Primitive handleStaticFieldGet(ast.Send node, FieldElement field, _) { |
| 1087 return buildStaticFieldGet(field, sourceInformationBuilder.buildGet(node)); |
| 1088 } |
| 1089 |
| 1090 @override |
| 1091 ir.Primitive handleStaticFieldInvoke( | 1091 ir.Primitive handleStaticFieldInvoke( |
| 1092 ast.Send node, | 1092 ast.Send node, |
| 1093 FieldElement field, | 1093 FieldElement field, |
| 1094 ast.NodeList arguments, | 1094 ast.NodeList arguments, |
| 1095 CallStructure callStructure, | 1095 CallStructure callStructure, |
| 1096 _) { | 1096 _) { |
| 1097 ir.Primitive target = irBuilder.buildStaticFieldGet(field); | 1097 SourceInformation src = sourceInformationBuilder.buildGet(node); |
| 1098 ir.Primitive target = buildStaticFieldGet(field, src); |
| 1098 return irBuilder.buildCallInvocation(target, | 1099 return irBuilder.buildCallInvocation(target, |
| 1099 callStructure, | 1100 callStructure, |
| 1100 translateDynamicArguments(arguments, callStructure)); | 1101 translateDynamicArguments(arguments, callStructure)); |
| 1101 } | 1102 } |
| 1102 | 1103 |
| 1103 @override | 1104 @override |
| 1104 ir.Primitive handleStaticFunctionInvoke( | 1105 ir.Primitive handleStaticFunctionInvoke( |
| 1105 ast.Send node, | 1106 ast.Send node, |
| 1106 MethodElement function, | 1107 MethodElement function, |
| 1107 ast.NodeList arguments, | 1108 ast.NodeList arguments, |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1418 return irBuilder.buildLocalVariableSet(element, visit(rhs)); | 1419 return irBuilder.buildLocalVariableSet(element, visit(rhs)); |
| 1419 } | 1420 } |
| 1420 | 1421 |
| 1421 @override | 1422 @override |
| 1422 ir.Primitive handleStaticFieldCompound( | 1423 ir.Primitive handleStaticFieldCompound( |
| 1423 ast.Send node, | 1424 ast.Send node, |
| 1424 FieldElement field, | 1425 FieldElement field, |
| 1425 op.AssignmentOperator operator, | 1426 op.AssignmentOperator operator, |
| 1426 ast.Node rhs, | 1427 ast.Node rhs, |
| 1427 _) { | 1428 _) { |
| 1429 SourceInformation src = sourceInformationBuilder.buildGet(node); |
| 1428 return translateCompound( | 1430 return translateCompound( |
| 1429 getValue: () => irBuilder.buildStaticFieldGet(field), | 1431 getValue: () => buildStaticFieldGet(field, src), |
| 1430 operator: operator, | 1432 operator: operator, |
| 1431 rhs: rhs, | 1433 rhs: rhs, |
| 1432 setValue: (ir.Primitive result) { | 1434 setValue: (ir.Primitive result) { |
| 1433 irBuilder.buildStaticFieldSet(field, result); | 1435 irBuilder.buildStaticFieldSet(field, result); |
| 1434 }); | 1436 }); |
| 1435 } | 1437 } |
| 1436 | 1438 |
| 1437 @override | 1439 @override |
| 1438 ir.Primitive handleStaticFieldPostfixPrefix( | 1440 ir.Primitive handleStaticFieldPostfixPrefix( |
| 1439 ast.Send node, | 1441 ast.Send node, |
| 1440 FieldElement field, | 1442 FieldElement field, |
| 1441 op.IncDecOperator operator, | 1443 op.IncDecOperator operator, |
| 1442 arg, | 1444 arg, |
| 1443 {bool isPrefix}) { | 1445 {bool isPrefix}) { |
| 1446 SourceInformation src = sourceInformationBuilder.buildGet(node); |
| 1444 return translatePrefixPostfix( | 1447 return translatePrefixPostfix( |
| 1445 getValue: () => irBuilder.buildStaticFieldGet(field), | 1448 getValue: () => buildStaticFieldGet(field, src), |
| 1446 operator: operator, | 1449 operator: operator, |
| 1447 setValue: (ir.Primitive result) { | 1450 setValue: (ir.Primitive result) { |
| 1448 irBuilder.buildStaticFieldSet(field, result); | 1451 irBuilder.buildStaticFieldSet(field, result); |
| 1449 }, | 1452 }, |
| 1450 isPrefix: isPrefix); | 1453 isPrefix: isPrefix); |
| 1451 } | 1454 } |
| 1452 | 1455 |
| 1453 @override | 1456 @override |
| 1454 ir.Primitive handleStaticFieldSet( | 1457 ir.Primitive handleStaticFieldSet( |
| 1455 ast.SendSet node, | 1458 ast.SendSet node, |
| (...skipping 863 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2319 Selector selector = new Selector.setter(parameter.name, null); | 2322 Selector selector = new Selector.setter(parameter.name, null); |
| 2320 return buildStaticNoSuchMethod(selector, [visit(rhs)]); | 2323 return buildStaticNoSuchMethod(selector, [visit(rhs)]); |
| 2321 } | 2324 } |
| 2322 | 2325 |
| 2323 @override | 2326 @override |
| 2324 ir.Primitive errorFinalStaticFieldCompound( | 2327 ir.Primitive errorFinalStaticFieldCompound( |
| 2325 ast.Send node, | 2328 ast.Send node, |
| 2326 FieldElement field, | 2329 FieldElement field, |
| 2327 op.AssignmentOperator operator, | 2330 op.AssignmentOperator operator, |
| 2328 ast.Node rhs, _) { | 2331 ast.Node rhs, _) { |
| 2332 SourceInformation src = sourceInformationBuilder.buildGet(node); |
| 2329 return translateCompound( | 2333 return translateCompound( |
| 2330 getValue: () => irBuilder.buildStaticFieldGet(field), | 2334 getValue: () => buildStaticFieldGet(field, src), |
| 2331 operator: operator, | 2335 operator: operator, |
| 2332 rhs: rhs, | 2336 rhs: rhs, |
| 2333 setValue: (value) => buildStaticNoSuchMethod( | 2337 setValue: (value) => buildStaticNoSuchMethod( |
| 2334 new Selector.setter(field.name, field.library), [value])); | 2338 new Selector.setter(field.name, field.library), [value])); |
| 2335 } | 2339 } |
| 2336 | 2340 |
| 2337 @override | 2341 @override |
| 2338 ir.Primitive errorFinalStaticFieldSet( | 2342 ir.Primitive errorFinalStaticFieldSet( |
| 2339 ast.SendSet node, | 2343 ast.SendSet node, |
| 2340 FieldElement field, | 2344 FieldElement field, |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2371 node); | 2375 node); |
| 2372 return buildInstanceNoSuchMethod(selector, [visit(rhs)]); | 2376 return buildInstanceNoSuchMethod(selector, [visit(rhs)]); |
| 2373 } | 2377 } |
| 2374 | 2378 |
| 2375 @override | 2379 @override |
| 2376 ir.Primitive errorFinalTopLevelFieldCompound( | 2380 ir.Primitive errorFinalTopLevelFieldCompound( |
| 2377 ast.Send node, | 2381 ast.Send node, |
| 2378 FieldElement field, | 2382 FieldElement field, |
| 2379 op.AssignmentOperator operator, | 2383 op.AssignmentOperator operator, |
| 2380 ast.Node rhs, _) { | 2384 ast.Node rhs, _) { |
| 2385 SourceInformation src = sourceInformationBuilder.buildGet(node); |
| 2381 return translateCompound( | 2386 return translateCompound( |
| 2382 getValue: () => irBuilder.buildStaticFieldGet(field), | 2387 getValue: () => buildStaticFieldGet(field, src), |
| 2383 operator: operator, | 2388 operator: operator, |
| 2384 rhs: rhs, | 2389 rhs: rhs, |
| 2385 setValue: (value) => buildStaticNoSuchMethod( | 2390 setValue: (value) => buildStaticNoSuchMethod( |
| 2386 new Selector.setter(field.name, field.library), [value])); | 2391 new Selector.setter(field.name, field.library), [value])); |
| 2387 } | 2392 } |
| 2388 | 2393 |
| 2389 @override | 2394 @override |
| 2390 ir.Primitive errorFinalTopLevelFieldSet( | 2395 ir.Primitive errorFinalTopLevelFieldSet( |
| 2391 ast.SendSet node, | 2396 ast.SendSet node, |
| 2392 FieldElement field, | 2397 FieldElement field, |
| (...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2967 | 2972 |
| 2968 @override | 2973 @override |
| 2969 ir.Primitive buildRuntimeError(String message) { | 2974 ir.Primitive buildRuntimeError(String message) { |
| 2970 return giveup(null, 'Build runtime error: $message'); | 2975 return giveup(null, 'Build runtime error: $message'); |
| 2971 } | 2976 } |
| 2972 | 2977 |
| 2973 @override | 2978 @override |
| 2974 ir.Primitive buildAbstractClassInstantiationError(ClassElement element) { | 2979 ir.Primitive buildAbstractClassInstantiationError(ClassElement element) { |
| 2975 return giveup(null, 'Abstract class instantiation: ${element.name}'); | 2980 return giveup(null, 'Abstract class instantiation: ${element.name}'); |
| 2976 } | 2981 } |
| 2982 |
| 2983 ir.Primitive buildStaticFieldGet(FieldElement field, SourceInformation src) { |
| 2984 return irBuilder.buildStaticFieldLazyGet(field, src); |
| 2985 } |
| 2977 } | 2986 } |
| 2978 | 2987 |
| 2979 /// The [IrBuilder]s view on the information about the program that has been | 2988 /// The [IrBuilder]s view on the information about the program that has been |
| 2980 /// computed in resolution and and type interence. | 2989 /// computed in resolution and and type interence. |
| 2981 class GlobalProgramInformation { | 2990 class GlobalProgramInformation { |
| 2982 final Compiler _compiler; | 2991 final Compiler _compiler; |
| 2983 JavaScriptBackend get _backend => _compiler.backend; | 2992 JavaScriptBackend get _backend => _compiler.backend; |
| 2984 | 2993 |
| 2985 GlobalProgramInformation(this._compiler); | 2994 GlobalProgramInformation(this._compiler); |
| 2986 | 2995 |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3105 case ElementKind.GENERATIVE_CONSTRUCTOR_BODY: | 3114 case ElementKind.GENERATIVE_CONSTRUCTOR_BODY: |
| 3106 root = buildConstructorBody(element); | 3115 root = buildConstructorBody(element); |
| 3107 break; | 3116 break; |
| 3108 | 3117 |
| 3109 case ElementKind.FUNCTION: | 3118 case ElementKind.FUNCTION: |
| 3110 case ElementKind.GETTER: | 3119 case ElementKind.GETTER: |
| 3111 case ElementKind.SETTER: | 3120 case ElementKind.SETTER: |
| 3112 root = buildFunction(element); | 3121 root = buildFunction(element); |
| 3113 break; | 3122 break; |
| 3114 | 3123 |
| 3124 case ElementKind.FIELD: |
| 3125 if (Elements.isStaticOrTopLevel(element)) { |
| 3126 root = buildStaticFieldInitializer(element); |
| 3127 } else { |
| 3128 // Instance field initializers are inlined in the constructor, |
| 3129 // so we shouldn't need to build anything here. |
| 3130 // TODO(asgerf): But what should we return? |
| 3131 return null; |
| 3132 } |
| 3133 break; |
| 3134 |
| 3115 default: | 3135 default: |
| 3116 compiler.internalError(element, "Unexpected element type $element"); | 3136 compiler.internalError(element, "Unexpected element type $element"); |
| 3117 } | 3137 } |
| 3118 new CleanupPass().visit(root); | 3138 new CleanupPass().visit(root); |
| 3119 return root; | 3139 return root; |
| 3120 }); | 3140 }); |
| 3121 } | 3141 } |
| 3122 | 3142 |
| 3143 ir.FunctionDefinition buildStaticFieldInitializer(FieldElement element) { |
| 3144 if (!backend.constants.lazyStatics.contains(element)) { |
| 3145 return null; // Nothing to do. |
| 3146 } |
| 3147 closureClassMap = |
| 3148 compiler.closureToClassMapper.computeClosureToClassMapping( |
| 3149 element, |
| 3150 element.node, |
| 3151 elements); |
| 3152 IrBuilder builder = getBuilderFor(element); |
| 3153 return withBuilder(builder, () { |
| 3154 ir.Primitive initialValue = visit(element.initializer); |
| 3155 irBuilder.buildReturn(initialValue); |
| 3156 return irBuilder.makeLazyFieldInitializer(); |
| 3157 }); |
| 3158 } |
| 3159 |
| 3123 /// Builds the IR for an [expression] taken from a different [context]. | 3160 /// Builds the IR for an [expression] taken from a different [context]. |
| 3124 /// | 3161 /// |
| 3125 /// Such expressions need to be compiled with a different [sourceFile] and | 3162 /// Such expressions need to be compiled with a different [sourceFile] and |
| 3126 /// [elements] mapping. | 3163 /// [elements] mapping. |
| 3127 ir.Primitive inlineExpression(AstElement context, ast.Expression expression) { | 3164 ir.Primitive inlineExpression(AstElement context, ast.Expression expression) { |
| 3128 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor( | 3165 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor( |
| 3129 context.resolvedAst.elements, | 3166 context.resolvedAst.elements, |
| 3130 compiler, | 3167 compiler, |
| 3131 sourceInformationBuilder.forContext(context)); | 3168 sourceInformationBuilder.forContext(context)); |
| 3132 return visitor.withBuilder(irBuilder, () => visitor.visit(expression)); | 3169 return visitor.withBuilder(irBuilder, () => visitor.visit(expression)); |
| (...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3630 [irBuilder.buildStringConstant(message)]); | 3667 [irBuilder.buildStringConstant(message)]); |
| 3631 } | 3668 } |
| 3632 | 3669 |
| 3633 @override | 3670 @override |
| 3634 ir.Primitive buildAbstractClassInstantiationError(ClassElement element) { | 3671 ir.Primitive buildAbstractClassInstantiationError(ClassElement element) { |
| 3635 return irBuilder.buildStaticFunctionInvocation( | 3672 return irBuilder.buildStaticFunctionInvocation( |
| 3636 backend.getThrowAbstractClassInstantiationError(), | 3673 backend.getThrowAbstractClassInstantiationError(), |
| 3637 new CallStructure.unnamed(1), | 3674 new CallStructure.unnamed(1), |
| 3638 [irBuilder.buildStringConstant(element.name)]); | 3675 [irBuilder.buildStringConstant(element.name)]); |
| 3639 } | 3676 } |
| 3677 |
| 3678 @override |
| 3679 ir.Primitive handleStaticFieldGet(ast.Send node, FieldElement field, _) { |
| 3680 SourceInformation src = sourceInformationBuilder.buildGet(node); |
| 3681 return buildStaticFieldGet(field, src); |
| 3682 } |
| 3683 |
| 3684 ir.Primitive buildStaticFieldGet(FieldElement field, SourceInformation src) { |
| 3685 ConstantExpression constant = |
| 3686 backend.constants.getConstantForVariable(field); |
| 3687 if (constant != null && !field.isAssignable) { |
| 3688 return irBuilder.buildConstant(constant); |
| 3689 } else if (backend.constants.lazyStatics.contains(field)) { |
| 3690 return irBuilder.buildStaticFieldLazyGet(field, src); |
| 3691 } else { |
| 3692 return irBuilder.buildStaticFieldGet(field, src); |
| 3693 } |
| 3694 } |
| 3640 } | 3695 } |
| 3641 | 3696 |
| 3642 /// Perform simple post-processing on the initial CPS-translated root term. | 3697 /// Perform simple post-processing on the initial CPS-translated root term. |
| 3643 /// | 3698 /// |
| 3644 /// This pass performs backend-independent post-processing on the translated | 3699 /// This pass performs backend-independent post-processing on the translated |
| 3645 /// term. It is implemented separately from the optimization passes because | 3700 /// term. It is implemented separately from the optimization passes because |
| 3646 /// it is required for correctness of the implementation. | 3701 /// it is required for correctness of the implementation. |
| 3647 /// | 3702 /// |
| 3648 /// It performs the following translations: | 3703 /// It performs the following translations: |
| 3649 /// - Replace [ir.LetPrim] binding a [ir.NonTailThrow] with a [ir.Throw] | 3704 /// - Replace [ir.LetPrim] binding a [ir.NonTailThrow] with a [ir.Throw] |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3702 node.body = replacementFor(node.body); | 3757 node.body = replacementFor(node.body); |
| 3703 } | 3758 } |
| 3704 } | 3759 } |
| 3705 | 3760 |
| 3706 /// Visit a just-deleted subterm and unlink all [Reference]s in it. | 3761 /// Visit a just-deleted subterm and unlink all [Reference]s in it. |
| 3707 class RemovalVisitor extends ir.RecursiveVisitor { | 3762 class RemovalVisitor extends ir.RecursiveVisitor { |
| 3708 processReference(ir.Reference reference) { | 3763 processReference(ir.Reference reference) { |
| 3709 reference.unlink(); | 3764 reference.unlink(); |
| 3710 } | 3765 } |
| 3711 } | 3766 } |
| OLD | NEW |