Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: pkg/compiler/lib/src/ssa/builder_kernel.dart

Issue 2498493003: kernel->ssa: get simple constructors working (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698