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 |