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

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

Issue 2498493003: kernel->ssa: get simple constructors working (Closed)
Patch Set: respond to comments 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
« no previous file with comments | « pkg/compiler/lib/src/ssa/builder.dart ('k') | pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/call_structure.dart' show CallStructure; 21 import '../universe/call_structure.dart' show CallStructure;
21 import '../universe/selector.dart'; 22 import '../universe/selector.dart';
22 import '../universe/use.dart' show TypeUse; 23 import '../universe/use.dart' show TypeUse;
23 import 'graph_builder.dart'; 24 import 'graph_builder.dart';
24 import 'kernel_ast_adapter.dart'; 25 import 'kernel_ast_adapter.dart';
25 import 'kernel_string_builder.dart'; 26 import 'kernel_string_builder.dart';
26 import 'locals_handler.dart'; 27 import 'locals_handler.dart';
27 import 'loop_handler.dart'; 28 import 'loop_handler.dart';
28 import 'nodes.dart'; 29 import 'nodes.dart';
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 if (typeBuilder.checkOrTrustTypes) { 133 if (typeBuilder.checkOrTrustTypes) {
133 return typeBuilder.potentiallyCheckOrTrustType( 134 return typeBuilder.potentiallyCheckOrTrustType(
134 value, compiler.coreTypes.boolType, 135 value, compiler.coreTypes.boolType,
135 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); 136 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK);
136 } 137 }
137 HInstruction result = new HBoolify(value, backend.boolType); 138 HInstruction result = new HBoolify(value, backend.boolType);
138 add(result); 139 add(result);
139 return result; 140 return result;
140 } 141 }
141 142
143 /// Builds generative constructors.
144 ///
145 /// Generative constructors are built in two stages.
146 ///
147 /// First, the field values for every instance field for every class in the
148 /// class hierarchy are collected. Then, create a function body that sets
149 /// all of the instance fields to the collected values and call the
150 /// constructor bodies for all constructors in the hierarchy.
142 void buildConstructor(ir.Constructor constructor) { 151 void buildConstructor(ir.Constructor constructor) {
143 // TODO(het): Actually handle this correctly 152 openFunction();
144 HBasicBlock block = graph.addNewBlock(); 153
145 open(graph.entry); 154 // Collect field values for the current class.
146 close(new HGoto()).addSuccessor(block); 155 // TODO(het): Does kernel always put field initializers in the constructor
147 open(block); 156 // initializer list? If so then this is unnecessary...
148 closeAndGotoExit(new HGoto()); 157 Map<ir.Field, HInstruction> fieldValues =
149 graph.finalize(); 158 _collectFieldValues(constructor.enclosingClass);
159
160 _buildInitializers(constructor, fieldValues);
161
162 final constructorArguments = <HInstruction>[];
163 astAdapter.getClass(constructor.enclosingClass).forEachInstanceField(
164 (ClassElement enclosingClass, FieldElement member) {
165 var value = fieldValues[astAdapter.getFieldFromElement(member)];
166 constructorArguments.add(value);
167 }, includeSuperAndInjectedMembers: true);
168
169 // TODO(het): If the class needs runtime type information, add it as a
170 // constructor argument.
171 HInstruction create = new HCreate(
172 astAdapter.getClass(constructor.enclosingClass),
173 constructorArguments,
174 new TypeMask.nonNullExact(
175 astAdapter.getClass(constructor.enclosingClass),
176 compiler.closedWorld),
177 instantiatedTypes: <DartType>[
178 astAdapter.getClass(constructor.enclosingClass).thisType
179 ],
180 hasRtiInput: false);
181
182 add(create);
183
184 // Generate calls to the constructor bodies.
185
186 closeAndGotoExit(new HReturn(create, null));
187 closeFunction();
188 }
189
190 /// Maps the fields of a class to their SSA values.
191 Map<ir.Field, HInstruction> _collectFieldValues(ir.Class clazz) {
192 final fieldValues = <ir.Field, HInstruction>{};
193
194 for (var field in clazz.fields) {
195 if (field.initializer == null) {
196 fieldValues[field] = graph.addConstantNull(compiler);
197 } else {
198 field.initializer.accept(this);
199 fieldValues[field] = pop();
200 }
201 }
202
203 return fieldValues;
204 }
205
206 /// Collects field initializers all the way up the inheritance chain.
207 void _buildInitializers(
208 ir.Constructor constructor, Map<ir.Field, HInstruction> fieldValues) {
209 var foundSuperCall = false;
210 for (var initializer in constructor.initializers) {
211 if (initializer is ir.SuperInitializer) {
212 foundSuperCall = true;
213 var superConstructor = initializer.target;
214 var arguments = _normalizeAndBuildArguments(
215 superConstructor.function, initializer.arguments);
216 _buildInlinedSuperInitializers(
217 superConstructor, arguments, fieldValues);
218 } else if (initializer is ir.FieldInitializer) {
219 initializer.value.accept(this);
220 fieldValues[initializer.field] = pop();
221 }
222 }
223
224 // TODO(het): does kernel always set the super initializer at the end?
225 // If there was no super-call initializer, then call the default constructor
226 // in the superclass.
227 if (!foundSuperCall) {
228 if (constructor.enclosingClass != astAdapter.objectClass) {
229 var superclass = constructor.enclosingClass.superclass;
230 var defaultConstructor = superclass.constructors
231 .firstWhere((c) => c.name == '', orElse: () => null);
232 if (defaultConstructor == null) {
233 compiler.reporter.internalError(
234 NO_LOCATION_SPANNABLE, 'Could not find default constructor.');
235 }
236 _buildInlinedSuperInitializers(
237 defaultConstructor, <HInstruction>[], fieldValues);
238 }
239 }
240 }
241
242 List<HInstruction> _normalizeAndBuildArguments(
243 ir.FunctionNode function, ir.Arguments arguments) {
244 var signature = astAdapter.getFunctionSignature(function);
245 var builtArguments = <HInstruction>[];
246 var positionalIndex = 0;
247 signature.forEachRequiredParameter((_) {
248 arguments.positional[positionalIndex++].accept(this);
249 builtArguments.add(pop());
250 });
251 if (!signature.optionalParametersAreNamed) {
252 signature.forEachOptionalParameter((ParameterElement element) {
253 if (positionalIndex < arguments.positional.length) {
254 arguments.positional[positionalIndex++].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 } else {
265 signature.orderedOptionalParameters.forEach((ParameterElement element) {
266 var correspondingNamed = arguments.named.firstWhere(
267 (named) => named.name == element.name,
268 orElse: () => null);
269 if (correspondingNamed != null) {
270 correspondingNamed.value.accept(this);
271 builtArguments.add(pop());
272 } else {
273 var constantValue =
274 backend.constants.getConstantValue(element.constant);
275 assert(invariant(element, constantValue != null,
276 message: 'No constant computed for $element'));
277 builtArguments.add(graph.addConstant(constantValue, compiler));
278 }
279 });
280 }
281
282 return builtArguments;
283 }
284
285 /// Inlines the given super [constructor]'s initializers by collecting it's
286 /// field values and building its constructor initializers. We visit super
287 /// constructors all the way up to the [Object] constructor.
288 void _buildInlinedSuperInitializers(ir.Constructor constructor,
289 List<HInstruction> arguments, Map<ir.Field, HInstruction> fieldValues) {
290 // TODO(het): Handle RTI if class needs it
291 fieldValues.addAll(_collectFieldValues(constructor.enclosingClass));
292
293 var signature = astAdapter.getFunctionSignature(constructor.function);
294 var index = 0;
295 signature.orderedForEachParameter((ParameterElement parameter) {
296 HInstruction argument = arguments[index++];
297 // Because we are inlining the initializer, we must update
298 // what was given as parameter. This will be used in case
299 // there is a parameter check expression in the initializer.
300 parameters[parameter] = argument;
301 localsHandler.updateLocal(parameter, argument);
302 });
303
304 // TODO(het): set the locals handler state as if we were inlining the
305 // constructor.
306 _buildInitializers(constructor, fieldValues);
150 } 307 }
151 308
152 HTypeConversion buildFunctionTypeConversion( 309 HTypeConversion buildFunctionTypeConversion(
153 HInstruction original, DartType type, int kind) { 310 HInstruction original, DartType type, int kind) {
154 String name = 311 String name =
155 kind == HTypeConversion.CAST_TYPE_CHECK ? '_asCheck' : '_assertCheck'; 312 kind == HTypeConversion.CAST_TYPE_CHECK ? '_asCheck' : '_assertCheck';
156 313
157 List<HInstruction> arguments = <HInstruction>[ 314 List<HInstruction> arguments = <HInstruction>[
158 buildFunctionType(type), 315 buildFunctionType(type),
159 original 316 original
160 ]; 317 ];
161 _pushDynamicInvocation(null, null, arguments, 318 _pushDynamicInvocation(null, null, arguments,
162 selector: new Selector.call( 319 selector: new Selector.call(
163 new Name(name, astAdapter.jsHelperLibrary), CallStructure.ONE_ARG)); 320 new Name(name, astAdapter.jsHelperLibrary), CallStructure.ONE_ARG));
164 321
165 return new HTypeConversion(type, kind, original.instructionType, pop()); 322 return new HTypeConversion(type, kind, original.instructionType, pop());
166 } 323 }
167 324
168 /// Builds a SSA graph for [procedure]. 325 /// Builds a SSA graph for [procedure].
169 void buildProcedure(ir.Procedure procedure) { 326 void buildProcedure(ir.Procedure procedure) {
170 openFunction(); 327 openFunction();
171 procedure.function.body.accept(this); 328 procedure.function.body.accept(this);
172 closeFunction(); 329 closeFunction();
173 } 330 }
174 331
175 void openFunction() { 332 void openFunction() {
176 HBasicBlock block = graph.addNewBlock(); 333 HBasicBlock block = graph.addNewBlock();
177 open(graph.entry); 334 open(graph.entry);
178 localsHandler.startFunction(targetElement, resolvedAst.node); 335
336 Node function;
337 if (resolvedAst.kind == ResolvedAstKind.PARSED) {
338 function = resolvedAst.node;
339 }
340 localsHandler.startFunction(targetElement, function);
179 close(new HGoto()).addSuccessor(block); 341 close(new HGoto()).addSuccessor(block);
180 342
181 open(block); 343 open(block);
182 } 344 }
183 345
184 void closeFunction() { 346 void closeFunction() {
185 if (!isAborted()) closeAndGotoExit(new HGoto()); 347 if (!isAborted()) closeAndGotoExit(new HGoto());
186 graph.finalize(); 348 graph.finalize();
187 } 349 }
188 350
(...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after
863 push(new HNot(popBoolified(), backend.boolType)); 1025 push(new HNot(popBoolified(), backend.boolType));
864 } 1026 }
865 1027
866 @override 1028 @override
867 void visitStringConcatenation(ir.StringConcatenation stringConcat) { 1029 void visitStringConcatenation(ir.StringConcatenation stringConcat) {
868 KernelStringBuilder stringBuilder = new KernelStringBuilder(this); 1030 KernelStringBuilder stringBuilder = new KernelStringBuilder(this);
869 stringConcat.accept(stringBuilder); 1031 stringConcat.accept(stringBuilder);
870 stack.add(stringBuilder.result); 1032 stack.add(stringBuilder.result);
871 } 1033 }
872 } 1034 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/builder.dart ('k') | pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698