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 '../common.dart'; | 7 import '../common.dart'; |
8 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; | 8 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
9 import '../common/names.dart'; | 9 import '../common/names.dart'; |
10 import '../common/tasks.dart' show CompilerTask; | 10 import '../common/tasks.dart' show CompilerTask; |
11 import '../compiler.dart'; | 11 import '../compiler.dart'; |
12 import '../dart_types.dart'; | 12 import '../dart_types.dart'; |
13 import '../elements/elements.dart'; | 13 import '../elements/elements.dart'; |
14 import '../io/source_information.dart'; | 14 import '../io/source_information.dart'; |
15 import '../js_backend/backend.dart' show JavaScriptBackend; | 15 import '../js_backend/backend.dart' show JavaScriptBackend; |
16 import '../kernel/kernel.dart'; | 16 import '../kernel/kernel.dart'; |
17 import '../resolution/tree_elements.dart'; | 17 import '../resolution/tree_elements.dart'; |
18 import '../tree/dartstring.dart'; | 18 import '../tree/dartstring.dart'; |
19 import '../tree/nodes.dart' show FunctionExpression, Node; | |
19 import '../types/masks.dart'; | 20 import '../types/masks.dart'; |
20 import '../universe/selector.dart'; | 21 import '../universe/selector.dart'; |
21 import 'graph_builder.dart'; | 22 import 'graph_builder.dart'; |
22 import 'kernel_ast_adapter.dart'; | 23 import 'kernel_ast_adapter.dart'; |
23 import 'kernel_string_builder.dart'; | 24 import 'kernel_string_builder.dart'; |
24 import 'locals_handler.dart'; | 25 import 'locals_handler.dart'; |
25 import 'loop_handler.dart'; | 26 import 'loop_handler.dart'; |
26 import 'nodes.dart'; | 27 import 'nodes.dart'; |
27 import 'ssa_branch_builder.dart'; | 28 import 'ssa_branch_builder.dart'; |
28 | 29 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
120 | 121 |
121 @override | 122 @override |
122 HInstruction popBoolified() { | 123 HInstruction popBoolified() { |
123 HInstruction value = pop(); | 124 HInstruction value = pop(); |
124 // TODO(het): add boolean conversion type check | 125 // TODO(het): add boolean conversion type check |
125 HInstruction result = new HBoolify(value, backend.boolType); | 126 HInstruction result = new HBoolify(value, backend.boolType); |
126 add(result); | 127 add(result); |
127 return result; | 128 return result; |
128 } | 129 } |
129 | 130 |
131 /// Generative constructors are built in several stages. | |
Siggi Cherem (dart-lang)
2016/11/14 18:22:25
dartdoc nit: Consider making the first comment a d
Harry Terkelsen
2016/11/14 23:23:40
oops :) when I started that comment I thought ther
| |
132 /// | |
133 /// First, the field values for every instance field for every class in the | |
134 /// class hierarchy are collected. Then, create a function body that sets | |
135 /// all of the instance fields to the collected values and call the | |
136 /// constructor bodies for all constructors in the hierarchy. | |
130 void buildConstructor(ir.Constructor constructor) { | 137 void buildConstructor(ir.Constructor constructor) { |
131 // TODO(het): Actually handle this correctly | 138 openFunction(); |
132 HBasicBlock block = graph.addNewBlock(); | 139 |
133 open(graph.entry); | 140 // Collect field values for the current class. |
134 close(new HGoto()).addSuccessor(block); | 141 // TODO(het): Does kernel always put field initializers in the constructor |
Siggi Cherem (dart-lang)
2016/11/14 18:22:25
good question for tomorrow :)?
Harry Terkelsen
2016/11/14 23:23:40
Acknowledged.
| |
135 open(block); | 142 // initializer list? If so then this is unnecessary... |
136 closeAndGotoExit(new HGoto()); | 143 Map<ir.Field, HInstruction> fieldValues = |
137 graph.finalize(); | 144 _collectFieldValues(constructor.enclosingClass); |
145 | |
146 _buildInitializers(constructor, fieldValues); | |
147 | |
148 final constructorArguments = <HInstruction>[]; | |
149 astAdapter.getClass(constructor.enclosingClass).forEachInstanceField( | |
150 (ClassElement enclosingClass, FieldElement member) { | |
151 var value = fieldValues[astAdapter.getFieldFromNode(member)]; | |
152 constructorArguments.add(value); | |
153 }, includeSuperAndInjectedMembers: true); | |
154 | |
155 // TODO(het): If the class needs runtime type information, add it as a | |
156 // constructor argument. | |
157 HInstruction create = new HCreate( | |
158 astAdapter.getClass(constructor.enclosingClass), | |
159 constructorArguments, | |
160 new TypeMask.nonNullExact( | |
161 astAdapter.getClass(constructor.enclosingClass), | |
162 compiler.closedWorld), | |
163 instantiatedTypes: <DartType>[ | |
164 astAdapter.getClass(constructor.enclosingClass).thisType | |
165 ], | |
166 hasRtiInput: false); | |
Siggi Cherem (dart-lang)
2016/11/14 18:22:25
just checking - this might change when addressing
Harry Terkelsen
2016/11/14 23:23:40
yes
| |
167 | |
168 add(create); | |
169 | |
170 // Generate calls to the constructor bodies. | |
171 | |
172 closeAndGotoExit(new HReturn(create, null)); | |
173 closeFunction(); | |
174 } | |
175 | |
176 /// Maps the fields of a class to their SSA values. | |
177 Map<ir.Field, HInstruction> _collectFieldValues(ir.Class clazz) { | |
178 final fieldValues = <ir.Field, HInstruction>{}; | |
179 | |
180 for (var field in clazz.fields) { | |
181 if (field.initializer == null) { | |
182 fieldValues[field] = graph.addConstantNull(compiler); | |
183 } else { | |
184 field.initializer.accept(this); | |
185 fieldValues[field] = pop(); | |
186 } | |
187 } | |
188 | |
189 return fieldValues; | |
190 } | |
191 | |
192 /// Collects field initializers all the way up the inheritance chain. | |
193 void _buildInitializers( | |
194 ir.Constructor constructor, Map<ir.Field, HInstruction> fieldValues) { | |
195 var foundSuperCall = false; | |
196 for (var initializer in constructor.initializers) { | |
197 if (initializer is ir.SuperInitializer) { | |
198 foundSuperCall = true; | |
199 var superConstructor = initializer.target; | |
200 var arguments = _normalizeAndBuildArguments( | |
201 superConstructor.function, initializer.arguments); | |
202 _buildSuperConstructor(superConstructor, arguments, fieldValues); | |
203 } else if (initializer is ir.FieldInitializer) { | |
204 initializer.value.accept(this); | |
205 fieldValues[initializer.field] = pop(); | |
206 } | |
207 } | |
208 | |
209 // If there was no super-call initializer, then call the default constructor | |
210 // in the superclass. | |
211 if (!foundSuperCall) { | |
Siggi Cherem (dart-lang)
2016/11/14 18:22:25
I wonder if kernel injects this call always at the
Harry Terkelsen
2016/11/14 23:23:40
Done.
| |
212 if (constructor.enclosingClass != astAdapter.objectClass) { | |
213 var superclass = constructor.enclosingClass.superclass; | |
214 var defaultConstructor = superclass.constructors | |
215 .firstWhere((c) => c.name == '', orElse: () => null); | |
216 if (defaultConstructor == null) { | |
217 compiler.reporter.internalError( | |
218 NO_LOCATION_SPANNABLE, 'Could not find default constructor.'); | |
219 } | |
220 _buildSuperConstructor( | |
221 defaultConstructor, <HInstruction>[], fieldValues); | |
222 } | |
223 } | |
224 } | |
225 | |
226 List<HInstruction> _normalizeAndBuildArguments( | |
227 ir.FunctionNode function, ir.Arguments arguments) { | |
228 var signature = astAdapter.getFunctionSignature(function); | |
229 var builtArguments = <HInstruction>[]; | |
230 var positionalIndex = 0; | |
231 signature.forEachRequiredParameter((_) { | |
232 arguments.positional[positionalIndex++].accept(this); | |
233 builtArguments.add(pop()); | |
234 }); | |
235 if (!signature.optionalParametersAreNamed) { | |
236 signature.forEachOptionalParameter((ParameterElement element) { | |
237 if (positionalIndex < arguments.positional.length) { | |
238 arguments.positional[positionalIndex++].accept(this); | |
239 builtArguments.add(pop()); | |
240 } else { | |
241 var constantValue = | |
242 backend.constants.getConstantValue(element.constant); | |
243 assert(invariant(element, constantValue != null, | |
244 message: 'No constant computed for $element')); | |
245 builtArguments.add(graph.addConstant(constantValue, compiler)); | |
246 } | |
247 }); | |
248 } else { | |
249 signature.orderedOptionalParameters.forEach((ParameterElement element) { | |
250 var correspondingNamed = arguments.named.firstWhere( | |
251 (named) => named.name == element.name, | |
252 orElse: () => null); | |
253 if (correspondingNamed != null) { | |
254 correspondingNamed.value.accept(this); | |
255 builtArguments.add(pop()); | |
256 } else { | |
257 var constantValue = | |
258 backend.constants.getConstantValue(element.constant); | |
259 assert(invariant(element, constantValue != null, | |
260 message: 'No constant computed for $element')); | |
261 builtArguments.add(graph.addConstant(constantValue, compiler)); | |
262 } | |
263 }); | |
264 } | |
265 | |
266 return builtArguments; | |
267 } | |
268 | |
269 /// Builds the given super [constructor] by collecting it's field values and | |
270 /// building it's initializers. We build super constructors all the way up | |
271 /// to the [Object] constructor. | |
272 void _buildSuperConstructor(ir.Constructor constructor, | |
Siggi Cherem (dart-lang)
2016/11/14 18:22:25
Consider renaming this to avoid giving the impress
Harry Terkelsen
2016/11/14 23:23:40
Done.
| |
273 List<HInstruction> arguments, Map<ir.Field, HInstruction> fieldValues) { | |
274 // TODO(het): Handle RTI if class needs it | |
275 fieldValues.addAll(_collectFieldValues(constructor.enclosingClass)); | |
276 | |
277 var signature = astAdapter.getFunctionSignature(constructor.function); | |
278 var index = 0; | |
279 signature.orderedForEachParameter((ParameterElement parameter) { | |
280 HInstruction argument = arguments[index++]; | |
281 // Because we are inlining the initializer, we must update | |
282 // what was given as parameter. This will be used in case | |
283 // there is a parameter check expression in the initializer. | |
284 parameters[parameter] = argument; | |
285 localsHandler.updateLocal(parameter, argument); | |
286 }); | |
287 | |
288 // TODO(het): set the locals handler state as if we were inlining the | |
289 // constructor. | |
290 _buildInitializers(constructor, fieldValues); | |
138 } | 291 } |
139 | 292 |
140 /// Builds a SSA graph for [procedure]. | 293 /// Builds a SSA graph for [procedure]. |
141 void buildProcedure(ir.Procedure procedure) { | 294 void buildProcedure(ir.Procedure procedure) { |
142 openFunction(); | 295 openFunction(); |
143 procedure.function.body.accept(this); | 296 procedure.function.body.accept(this); |
144 closeFunction(); | 297 closeFunction(); |
145 } | 298 } |
146 | 299 |
147 void openFunction() { | 300 void openFunction() { |
148 HBasicBlock block = graph.addNewBlock(); | 301 HBasicBlock block = graph.addNewBlock(); |
149 open(graph.entry); | 302 open(graph.entry); |
150 localsHandler.startFunction(targetElement, resolvedAst.node); | 303 |
304 Node function; | |
305 if (resolvedAst.kind == ResolvedAstKind.PARSED) { | |
306 function = resolvedAst.node; | |
307 } | |
308 localsHandler.startFunction(targetElement, function); | |
151 close(new HGoto()).addSuccessor(block); | 309 close(new HGoto()).addSuccessor(block); |
152 | 310 |
153 open(block); | 311 open(block); |
154 } | 312 } |
155 | 313 |
156 void closeFunction() { | 314 void closeFunction() { |
157 if (!isAborted()) closeAndGotoExit(new HGoto()); | 315 if (!isAborted()) closeAndGotoExit(new HGoto()); |
158 graph.finalize(); | 316 graph.finalize(); |
159 } | 317 } |
160 | 318 |
(...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
817 push(new HNot(popBoolified(), backend.boolType)); | 975 push(new HNot(popBoolified(), backend.boolType)); |
818 } | 976 } |
819 | 977 |
820 @override | 978 @override |
821 void visitStringConcatenation(ir.StringConcatenation stringConcat) { | 979 void visitStringConcatenation(ir.StringConcatenation stringConcat) { |
822 KernelStringBuilder stringBuilder = new KernelStringBuilder(this); | 980 KernelStringBuilder stringBuilder = new KernelStringBuilder(this); |
823 stringConcat.accept(stringBuilder); | 981 stringConcat.accept(stringBuilder); |
824 stack.add(stringBuilder.result); | 982 stack.add(stringBuilder.result); |
825 } | 983 } |
826 } | 984 } |
OLD | NEW |