OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
6 | 6 |
7 import '../closure.dart'; | 7 import '../closure.dart'; |
8 import '../common.dart'; | 8 import '../common.dart'; |
9 import '../common/codegen.dart' show CodegenRegistry; | 9 import '../common/codegen.dart' show CodegenRegistry; |
10 import '../common/names.dart'; | 10 import '../common/names.dart'; |
(...skipping 14 matching lines...) Expand all Loading... |
25 import '../io/source_information.dart'; | 25 import '../io/source_information.dart'; |
26 import '../js/js.dart' as js; | 26 import '../js/js.dart' as js; |
27 import '../js_backend/backend.dart' show JavaScriptBackend; | 27 import '../js_backend/backend.dart' show JavaScriptBackend; |
28 import '../kernel/element_map.dart'; | 28 import '../kernel/element_map.dart'; |
29 import '../native/native.dart' as native; | 29 import '../native/native.dart' as native; |
30 import '../resolution/tree_elements.dart'; | 30 import '../resolution/tree_elements.dart'; |
31 import '../tree/nodes.dart' show Node; | 31 import '../tree/nodes.dart' show Node; |
32 import '../types/masks.dart'; | 32 import '../types/masks.dart'; |
33 import '../universe/selector.dart'; | 33 import '../universe/selector.dart'; |
34 import '../universe/side_effects.dart' show SideEffects; | 34 import '../universe/side_effects.dart' show SideEffects; |
35 import '../universe/use.dart' show DynamicUse; | 35 import '../universe/use.dart' show ConstantUse, DynamicUse; |
36 import '../universe/world_builder.dart' show CodegenWorldBuilder; | 36 import '../universe/world_builder.dart' show CodegenWorldBuilder; |
37 import '../world.dart'; | 37 import '../world.dart'; |
38 import 'graph_builder.dart'; | 38 import 'graph_builder.dart'; |
39 import 'jump_handler.dart'; | 39 import 'jump_handler.dart'; |
40 import 'kernel_ast_adapter.dart'; | 40 import 'kernel_ast_adapter.dart'; |
41 import 'kernel_string_builder.dart'; | 41 import 'kernel_string_builder.dart'; |
42 import 'locals_handler.dart'; | 42 import 'locals_handler.dart'; |
43 import 'loop_handler.dart'; | 43 import 'loop_handler.dart'; |
44 import 'nodes.dart'; | 44 import 'nodes.dart'; |
45 import 'ssa.dart'; | 45 import 'ssa.dart'; |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 } else if (target is ir.Field) { | 138 } else if (target is ir.Field) { |
139 if (handleConstantField(targetElement, registry, closedWorld)) { | 139 if (handleConstantField(targetElement, registry, closedWorld)) { |
140 // No code is generated for `targetElement`: All references inline the | 140 // No code is generated for `targetElement`: All references inline the |
141 // constant value. | 141 // constant value. |
142 return null; | 142 return null; |
143 } else if (targetElement.isStatic || targetElement.isTopLevel) { | 143 } else if (targetElement.isStatic || targetElement.isTopLevel) { |
144 backend.constants.registerLazyStatic(targetElement); | 144 backend.constants.registerLazyStatic(targetElement); |
145 } | 145 } |
146 buildField(target); | 146 buildField(target); |
147 } else if (target is ir.Constructor) { | 147 } else if (target is ir.Constructor) { |
| 148 _targetFunction = (target as ir.Constructor).function; |
148 if (targetElement is ConstructorBodyEntity) { | 149 if (targetElement is ConstructorBodyEntity) { |
149 buildConstructorBody(target); | 150 buildConstructorBody(target); |
150 } else { | 151 } else { |
151 buildConstructor(target); | 152 buildConstructor(target); |
152 } | 153 } |
153 } else if (target is ir.FunctionExpression) { | 154 } else if (target is ir.FunctionExpression) { |
154 _targetFunction = (target as ir.FunctionExpression).function; | 155 _targetFunction = (target as ir.FunctionExpression).function; |
155 buildFunctionNode(_targetFunction); | 156 buildFunctionNode(_targetFunction); |
156 } else if (target is ir.FunctionDeclaration) { | 157 } else if (target is ir.FunctionDeclaration) { |
157 _targetFunction = (target as ir.FunctionDeclaration).function; | 158 _targetFunction = (target as ir.FunctionDeclaration).function; |
158 buildFunctionNode(_targetFunction); | 159 buildFunctionNode(_targetFunction); |
159 } else { | 160 } else { |
160 throw 'No case implemented to handle target: ' | 161 throw 'No case implemented to handle target: ' |
161 '$target for $targetElement'; | 162 '$target for $targetElement'; |
162 } | 163 } |
163 assert(graph.isValid()); | 164 assert(graph.isValid()); |
| 165 if (_targetFunction != null) { |
| 166 _ensureDefaultArgumentValues(_targetFunction); |
| 167 } |
164 return graph; | 168 return graph; |
165 }); | 169 }); |
166 } | 170 } |
167 | 171 |
| 172 void _ensureDefaultArgumentValues(ir.FunctionNode function) { |
| 173 // Register all [function]'s default argument values. |
| 174 // |
| 175 // Default values might be (or contain) functions that are not referenced |
| 176 // from anywhere else so we need to ensure these are enqueued. Stubs and |
| 177 // `Function.apply` data are created after the codegen queue is closed, so |
| 178 // we force these functions into the queue by registering the constants as |
| 179 // used in advance. See language/cyclic_default_values_test.dart for an |
| 180 // example. |
| 181 // |
| 182 // TODO(sra): We could be more precise if stubs and `Function.apply` data |
| 183 // were generated by the codegen enqueuer. In practice even in huge programs |
| 184 // there are only very small number of constants created here that are not |
| 185 // actually used. |
| 186 void registerDefaultValue(ir.VariableDeclaration node) { |
| 187 ConstantValue constantValue = |
| 188 _elementMap.getConstantValue(node.initializer, implicitNull: true); |
| 189 assert( |
| 190 constantValue != null, |
| 191 failedAt(_elementMap.getMethod(function.parent), |
| 192 'No constant computed for $node')); |
| 193 registry?.registerConstantUse(new ConstantUse.init(constantValue)); |
| 194 } |
| 195 |
| 196 function.positionalParameters |
| 197 .skip(function.requiredParameterCount) |
| 198 .forEach(registerDefaultValue); |
| 199 function.namedParameters.forEach(registerDefaultValue); |
| 200 } |
| 201 |
168 @override | 202 @override |
169 ConstantValue getFieldInitialConstantValue(FieldEntity field) { | 203 ConstantValue getFieldInitialConstantValue(FieldEntity field) { |
170 assert(field == targetElement); | 204 assert(field == targetElement); |
171 return _elementMap.getFieldConstantValue(target); | 205 return _elementMap.getFieldConstantValue(target); |
172 } | 206 } |
173 | 207 |
174 void buildField(ir.Field field) { | 208 void buildField(ir.Field field) { |
175 openFunction(); | 209 openFunction(); |
176 if (field.initializer != null) { | 210 if (field.initializer != null) { |
177 field.initializer.accept(this); | 211 field.initializer.accept(this); |
(...skipping 3338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3516 enterBlock.setBlockFlow( | 3550 enterBlock.setBlockFlow( |
3517 new HTryBlockInformation( | 3551 new HTryBlockInformation( |
3518 kernelBuilder.wrapStatementGraph(bodyGraph), | 3552 kernelBuilder.wrapStatementGraph(bodyGraph), |
3519 exception, | 3553 exception, |
3520 kernelBuilder.wrapStatementGraph(catchGraph), | 3554 kernelBuilder.wrapStatementGraph(catchGraph), |
3521 kernelBuilder.wrapStatementGraph(finallyGraph)), | 3555 kernelBuilder.wrapStatementGraph(finallyGraph)), |
3522 exitBlock); | 3556 exitBlock); |
3523 kernelBuilder.inTryStatement = previouslyInTryStatement; | 3557 kernelBuilder.inTryStatement = previouslyInTryStatement; |
3524 } | 3558 } |
3525 } | 3559 } |
OLD | NEW |