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

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

Issue 2637533003: dart2js-kernel: Call generative constructor body functions (Closed)
Patch Set: fix analyzer warning Created 3 years, 11 months 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 '../closure.dart'; 7 import '../closure.dart';
8 import '../common.dart'; 8 import '../common.dart';
9 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; 9 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
10 import '../common/names.dart'; 10 import '../common/names.dart';
11 import '../common/tasks.dart' show CompilerTask; 11 import '../common/tasks.dart' show CompilerTask;
12 import '../compiler.dart'; 12 import '../compiler.dart';
13 import '../constants/values.dart' 13 import '../constants/values.dart'
14 show 14 show
15 ConstantValue, 15 ConstantValue,
16 InterceptorConstantValue, 16 InterceptorConstantValue,
17 StringConstantValue, 17 StringConstantValue,
18 TypeConstantValue; 18 TypeConstantValue;
19 import '../elements/resolution_types.dart'; 19 import '../elements/resolution_types.dart';
20 import '../elements/elements.dart'; 20 import '../elements/elements.dart';
21 import '../elements/entities.dart' show MemberEntity;
21 import '../io/source_information.dart'; 22 import '../io/source_information.dart';
22 import '../js/js.dart' as js; 23 import '../js/js.dart' as js;
23 import '../js_backend/backend.dart' show JavaScriptBackend; 24 import '../js_backend/backend.dart' show JavaScriptBackend;
24 import '../kernel/kernel.dart'; 25 import '../kernel/kernel.dart';
25 import '../native/native.dart' as native; 26 import '../native/native.dart' as native;
26 import '../resolution/tree_elements.dart'; 27 import '../resolution/tree_elements.dart';
27 import '../tree/dartstring.dart'; 28 import '../tree/dartstring.dart';
28 import '../tree/nodes.dart' show Node, BreakStatement; 29 import '../tree/nodes.dart' show Node, BreakStatement;
29 import '../types/masks.dart'; 30 import '../types/masks.dart';
30 import '../universe/call_structure.dart' show CallStructure; 31 import '../universe/call_structure.dart' show CallStructure;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 backend.tracer.traceGraph('builder', graph); 85 backend.tracer.traceGraph('builder', graph);
85 } 86 }
86 87
87 return graph; 88 return graph;
88 }); 89 });
89 } 90 }
90 } 91 }
91 92
92 class KernelSsaBuilder extends ir.Visitor with GraphBuilder { 93 class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
93 ir.Node target; 94 ir.Node target;
95 bool _targetIsConstructorBody = false;
94 final AstElement targetElement; 96 final AstElement targetElement;
95 final ResolvedAst resolvedAst; 97 final ResolvedAst resolvedAst;
96 final ClosedWorld closedWorld; 98 final ClosedWorld closedWorld;
97 final CodegenRegistry registry; 99 final CodegenRegistry registry;
98 100
99 /// Helper accessor for all kernel function-like targets (Procedure, 101 /// Helper accessor for all kernel function-like targets (Procedure,
100 /// FunctionExpression, FunctionDeclaration) of the inner FunctionNode itself. 102 /// FunctionExpression, FunctionDeclaration) of the inner FunctionNode itself.
101 /// If the current target is not a function-like target, _targetFunction will 103 /// If the current target is not a function-like target, _targetFunction will
102 /// be null. 104 /// be null.
103 ir.FunctionNode _targetFunction; 105 ir.FunctionNode _targetFunction;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 graph.sourceInformation = 151 graph.sourceInformation =
150 sourceInformationBuilder.buildVariableDeclaration(); 152 sourceInformationBuilder.buildVariableDeclaration();
151 this.localsHandler = new LocalsHandler(this, targetElement, null, compiler); 153 this.localsHandler = new LocalsHandler(this, targetElement, null, compiler);
152 this.astAdapter = new KernelAstAdapter(kernel, compiler.backend, 154 this.astAdapter = new KernelAstAdapter(kernel, compiler.backend,
153 resolvedAst, kernel.nodeToAst, kernel.nodeToElement); 155 resolvedAst, kernel.nodeToAst, kernel.nodeToElement);
154 Element originTarget = targetElement; 156 Element originTarget = targetElement;
155 if (originTarget.isPatch) { 157 if (originTarget.isPatch) {
156 originTarget = originTarget.origin; 158 originTarget = originTarget.origin;
157 } 159 }
158 if (originTarget is FunctionElement) { 160 if (originTarget is FunctionElement) {
161 if (originTarget is ConstructorBodyElement) {
162 ConstructorBodyElement body = originTarget;
163 _targetIsConstructorBody = true;
164 originTarget = body.constructor;
165 }
159 target = kernel.functions[originTarget]; 166 target = kernel.functions[originTarget];
160 // Closures require a lookup one level deeper in the closure class mapper. 167 // Closures require a lookup one level deeper in the closure class mapper.
161 if (target == null) { 168 if (target == null) {
169 FunctionElement originTargetFunction = originTarget;
162 ClosureClassMap classMap = compiler.closureToClassMapper 170 ClosureClassMap classMap = compiler.closureToClassMapper
163 .getClosureToClassMapping(originTarget.resolvedAst); 171 .getClosureToClassMapping(originTargetFunction.resolvedAst);
164 if (classMap.closureElement != null) { 172 if (classMap.closureElement != null) {
165 target = kernel.localFunctions[classMap.closureElement]; 173 target = kernel.localFunctions[classMap.closureElement];
166 } 174 }
167 } 175 }
168 } else if (originTarget is FieldElement) { 176 } else if (originTarget is FieldElement) {
169 target = kernel.fields[originTarget]; 177 target = kernel.fields[originTarget];
170 } 178 }
171 } 179 }
172 180
173 HGraph build() { 181 HGraph build() {
174 // TODO(het): no reason to do this here... 182 // TODO(het): no reason to do this here...
175 HInstruction.idCounter = 0; 183 HInstruction.idCounter = 0;
176 if (target is ir.Procedure) { 184 if (target is ir.Procedure) {
177 _targetFunction = (target as ir.Procedure).function; 185 _targetFunction = (target as ir.Procedure).function;
178 buildFunctionNode(_targetFunction); 186 buildFunctionNode(_targetFunction);
179 } else if (target is ir.Field) { 187 } else if (target is ir.Field) {
180 buildField(target); 188 buildField(target);
181 } else if (target is ir.Constructor) { 189 } else if (target is ir.Constructor) {
182 buildConstructor(target); 190 if (_targetIsConstructorBody) {
191 buildConstructorBody(target);
192 } else {
193 buildConstructor(target);
194 }
183 } else if (target is ir.FunctionExpression) { 195 } else if (target is ir.FunctionExpression) {
184 _targetFunction = (target as ir.FunctionExpression).function; 196 _targetFunction = (target as ir.FunctionExpression).function;
185 buildFunctionNode(_targetFunction); 197 buildFunctionNode(_targetFunction);
186 } else if (target is ir.FunctionDeclaration) { 198 } else if (target is ir.FunctionDeclaration) {
187 _targetFunction = (target as ir.FunctionDeclaration).function; 199 _targetFunction = (target as ir.FunctionDeclaration).function;
188 buildFunctionNode(_targetFunction); 200 buildFunctionNode(_targetFunction);
189 } else { 201 } else {
190 throw 'No case implemented to handle $target'; 202 throw 'No case implemented to handle target: $target';
191 } 203 }
192 assert(graph.isValid()); 204 assert(graph.isValid());
193 return graph; 205 return graph;
194 } 206 }
195 207
196 void buildField(ir.Field field) { 208 void buildField(ir.Field field) {
197 openFunction(); 209 openFunction();
198 if (field.initializer != null) { 210 if (field.initializer != null) {
199 field.initializer.accept(this); 211 field.initializer.accept(this);
200 HInstruction fieldValue = pop(); 212 HInstruction fieldValue = pop();
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 /// constructor bodies for all constructors in the hierarchy. 266 /// constructor bodies for all constructors in the hierarchy.
255 void buildConstructor(ir.Constructor constructor) { 267 void buildConstructor(ir.Constructor constructor) {
256 openFunction(); 268 openFunction();
257 _addClassTypeVariablesIfNeeded(constructor); 269 _addClassTypeVariablesIfNeeded(constructor);
258 270
259 // Collect field values for the current class. 271 // Collect field values for the current class.
260 // TODO(het): Does kernel always put field initializers in the constructor 272 // TODO(het): Does kernel always put field initializers in the constructor
261 // initializer list? If so then this is unnecessary... 273 // initializer list? If so then this is unnecessary...
262 Map<ir.Field, HInstruction> fieldValues = 274 Map<ir.Field, HInstruction> fieldValues =
263 _collectFieldValues(constructor.enclosingClass); 275 _collectFieldValues(constructor.enclosingClass);
276 List<ir.Constructor> constructorChain = <ir.Constructor>[];
264 277
265 _buildInitializers(constructor, fieldValues); 278 _buildInitializers(constructor, constructorChain, fieldValues);
266 279
267 final constructorArguments = <HInstruction>[]; 280 final constructorArguments = <HInstruction>[];
268 astAdapter.getClass(constructor.enclosingClass).forEachInstanceField( 281 astAdapter.getClass(constructor.enclosingClass).forEachInstanceField(
269 (ClassElement enclosingClass, FieldElement member) { 282 (ClassElement enclosingClass, FieldElement member) {
270 var value = fieldValues[astAdapter.getFieldFromElement(member)]; 283 var value = fieldValues[astAdapter.getFieldFromElement(member)];
271 constructorArguments.add(value); 284 constructorArguments.add(value);
272 }, includeSuperAndInjectedMembers: true); 285 }, includeSuperAndInjectedMembers: true);
273 286
274 // TODO(het): If the class needs runtime type information, add it as a 287 // TODO(het): If the class needs runtime type information, add it as a
275 // constructor argument. 288 // constructor argument.
276 HInstruction create = new HCreate( 289 HInstruction newObject = new HCreate(
277 astAdapter.getClass(constructor.enclosingClass), 290 astAdapter.getClass(constructor.enclosingClass),
278 constructorArguments, 291 constructorArguments,
279 new TypeMask.nonNullExact( 292 new TypeMask.nonNullExact(
280 astAdapter.getClass(constructor.enclosingClass), closedWorld), 293 astAdapter.getClass(constructor.enclosingClass), closedWorld),
281 instantiatedTypes: <ResolutionDartType>[ 294 instantiatedTypes: <ResolutionDartType>[
282 astAdapter.getClass(constructor.enclosingClass).thisType 295 astAdapter.getClass(constructor.enclosingClass).thisType
283 ], 296 ],
284 hasRtiInput: false); 297 hasRtiInput: false);
285 298
286 add(create); 299 add(newObject);
287 300
288 // Generate calls to the constructor bodies. 301 // Generate calls to the constructor bodies.
289 302
290 closeAndGotoExit(new HReturn(create, null)); 303 for (ir.Constructor body in constructorChain.reversed) {
304 if (_isEmptyStatement(body.function.body)) continue;
305
306 List<HInstruction> bodyCallInputs = <HInstruction>[];
307 bodyCallInputs.add(newObject);
308
309 // TODO(sra): Pass arguments, boxes and type parameters.
310 _invokeConstructorBody(body, bodyCallInputs);
311 }
312
313 closeAndGotoExit(new HReturn(newObject, null));
291 closeFunction(); 314 closeFunction();
292 } 315 }
293 316
317 static bool _isEmptyStatement(ir.Statement body) {
318 if (body is ir.EmptyStatement) return true;
319 if (body is ir.Block) return body.statements.every(_isEmptyStatement);
320 return false;
321 }
322
323 void _invokeConstructorBody(
324 ir.Constructor constructor, List<HInstruction> inputs) {
325 // TODO(sra): Inline the constructor body.
326 MemberEntity constructorBody =
327 astAdapter.getConstructorBodyEntity(constructor);
328 HInvokeConstructorBody invoke = new HInvokeConstructorBody(
329 constructorBody, inputs, commonMasks.nonNullType);
330 add(invoke);
331 }
332
294 /// Maps the instance fields of a class to their SSA values. 333 /// Maps the instance fields of a class to their SSA values.
295 Map<ir.Field, HInstruction> _collectFieldValues(ir.Class clazz) { 334 Map<ir.Field, HInstruction> _collectFieldValues(ir.Class clazz) {
296 final fieldValues = <ir.Field, HInstruction>{}; 335 final fieldValues = <ir.Field, HInstruction>{};
297 336
298 for (var field in clazz.fields) { 337 for (var field in clazz.fields) {
299 if (field.isInstanceMember) { 338 if (field.isInstanceMember) {
300 if (field.initializer == null) { 339 if (field.initializer == null) {
301 fieldValues[field] = graph.addConstantNull(closedWorld); 340 fieldValues[field] = graph.addConstantNull(closedWorld);
302 } else { 341 } else {
303 // Gotta update the resolvedAst when we're looking at field values 342 // Gotta update the resolvedAst when we're looking at field values
304 // outside the constructor. 343 // outside the constructor.
305 astAdapter.pushResolvedAst(field); 344 astAdapter.pushResolvedAst(field);
306 field.initializer.accept(this); 345 field.initializer.accept(this);
307 fieldValues[field] = pop(); 346 fieldValues[field] = pop();
308 astAdapter.popResolvedAstStack(); 347 astAdapter.popResolvedAstStack();
309 } 348 }
310 } 349 }
311 } 350 }
312 351
313 return fieldValues; 352 return fieldValues;
314 } 353 }
315 354
316 /// Collects field initializers all the way up the inheritance chain. 355 /// Collects field initializers all the way up the inheritance chain.
317 void _buildInitializers( 356 void _buildInitializers(
318 ir.Constructor constructor, Map<ir.Field, HInstruction> fieldValues) { 357 ir.Constructor constructor,
358 List<ir.Constructor> constructorChain,
359 Map<ir.Field, HInstruction> fieldValues) {
360 constructorChain.add(constructor);
319 var foundSuperOrRedirectCall = false; 361 var foundSuperOrRedirectCall = false;
320 for (var initializer in constructor.initializers) { 362 for (var initializer in constructor.initializers) {
321 if (initializer is ir.SuperInitializer || 363 if (initializer is ir.SuperInitializer ||
322 initializer is ir.RedirectingInitializer) { 364 initializer is ir.RedirectingInitializer) {
323 foundSuperOrRedirectCall = true; 365 foundSuperOrRedirectCall = true;
324 var superOrRedirectConstructor = initializer.target; 366 var superOrRedirectConstructor = initializer.target;
325 var arguments = _normalizeAndBuildArguments( 367 var arguments = _normalizeAndBuildArguments(
326 superOrRedirectConstructor.function, initializer.arguments); 368 superOrRedirectConstructor.function, initializer.arguments);
327 _buildInlinedInitializers( 369 _buildInlinedInitializers(superOrRedirectConstructor, arguments,
328 superOrRedirectConstructor, arguments, fieldValues); 370 constructorChain, fieldValues);
329 } else if (initializer is ir.FieldInitializer) { 371 } else if (initializer is ir.FieldInitializer) {
330 initializer.value.accept(this); 372 initializer.value.accept(this);
331 fieldValues[initializer.field] = pop(); 373 fieldValues[initializer.field] = pop();
332 } 374 }
333 } 375 }
334 376
335 // Kernel always set the super initializer at the end, so if there was no
336 // super-call initializer, then the default constructor is called in the
337 // superclass.
338 if (!foundSuperOrRedirectCall) { 377 if (!foundSuperOrRedirectCall) {
339 if (constructor.enclosingClass != astAdapter.objectClass) { 378 assert(constructor.enclosingClass == astAdapter.objectClass,
340 var superclass = constructor.enclosingClass.superclass; 379 'All constructors have super-constructor initializers, except Object() ');
341 var defaultConstructor = superclass.constructors
342 .firstWhere((c) => c.name.name == '', orElse: () => null);
343 if (defaultConstructor == null) {
344 compiler.reporter.internalError(
345 NO_LOCATION_SPANNABLE, 'Could not find default constructor.');
346 }
347 _buildInlinedInitializers(
348 defaultConstructor, <HInstruction>[], fieldValues);
349 }
350 } 380 }
351 } 381 }
352 382
353 List<HInstruction> _normalizeAndBuildArguments( 383 List<HInstruction> _normalizeAndBuildArguments(
354 ir.FunctionNode function, ir.Arguments arguments) { 384 ir.FunctionNode function, ir.Arguments arguments) {
355 var signature = astAdapter.getFunctionSignature(function); 385 var signature = astAdapter.getFunctionSignature(function);
356 var builtArguments = <HInstruction>[]; 386 var builtArguments = <HInstruction>[];
357 var positionalIndex = 0; 387 var positionalIndex = 0;
358 signature.forEachRequiredParameter((_) { 388 signature.forEachRequiredParameter((_) {
359 arguments.positional[positionalIndex++].accept(this); 389 arguments.positional[positionalIndex++].accept(this);
(...skipping 29 matching lines...) Expand all
389 } 419 }
390 }); 420 });
391 } 421 }
392 422
393 return builtArguments; 423 return builtArguments;
394 } 424 }
395 425
396 /// Inlines the given super [constructor]'s initializers by collecting its 426 /// Inlines the given super [constructor]'s initializers by collecting its
397 /// field values and building its constructor initializers. We visit super 427 /// field values and building its constructor initializers. We visit super
398 /// constructors all the way up to the [Object] constructor. 428 /// constructors all the way up to the [Object] constructor.
399 void _buildInlinedInitializers(ir.Constructor constructor, 429 void _buildInlinedInitializers(
400 List<HInstruction> arguments, Map<ir.Field, HInstruction> fieldValues) { 430 ir.Constructor constructor,
431 List<HInstruction> arguments,
432 List<ir.Constructor> constructorChain,
433 Map<ir.Field, HInstruction> fieldValues) {
401 // TODO(het): Handle RTI if class needs it 434 // TODO(het): Handle RTI if class needs it
402 fieldValues.addAll(_collectFieldValues(constructor.enclosingClass)); 435 fieldValues.addAll(_collectFieldValues(constructor.enclosingClass));
403 436
404 var signature = astAdapter.getFunctionSignature(constructor.function); 437 var signature = astAdapter.getFunctionSignature(constructor.function);
405 var index = 0; 438 var index = 0;
406 signature.orderedForEachParameter((ParameterElement parameter) { 439 signature.orderedForEachParameter((ParameterElement parameter) {
407 HInstruction argument = arguments[index++]; 440 HInstruction argument = arguments[index++];
408 // Because we are inlining the initializer, we must update 441 // Because we are inlining the initializer, we must update
409 // what was given as parameter. This will be used in case 442 // what was given as parameter. This will be used in case
410 // there is a parameter check expression in the initializer. 443 // there is a parameter check expression in the initializer.
411 parameters[parameter] = argument; 444 parameters[parameter] = argument;
412 localsHandler.updateLocal(parameter, argument); 445 localsHandler.updateLocal(parameter, argument);
413 }); 446 });
414 447
415 // TODO(het): set the locals handler state as if we were inlining the 448 // TODO(het): set the locals handler state as if we were inlining the
416 // constructor. 449 // constructor.
417 _buildInitializers(constructor, fieldValues); 450 _buildInitializers(constructor, constructorChain, fieldValues);
418 } 451 }
419 452
420 HTypeConversion buildFunctionTypeConversion( 453 HTypeConversion buildFunctionTypeConversion(
421 HInstruction original, ResolutionDartType type, int kind) { 454 HInstruction original, ResolutionDartType type, int kind) {
422 HInstruction reifiedType = buildFunctionType(type); 455 HInstruction reifiedType = buildFunctionType(type);
423 return new HTypeConversion.viaMethodOnType( 456 return new HTypeConversion.viaMethodOnType(
424 type, kind, original.instructionType, reifiedType, original); 457 type, kind, original.instructionType, reifiedType, original);
425 } 458 }
426 459
460 /// Builds generative constructor body.
461 void buildConstructorBody(ir.Constructor constructor) {
462 openFunction();
463 constructor.function.body.accept(this);
464 closeFunction();
465 }
466
427 /// Builds a SSA graph for FunctionNodes, found in FunctionExpressions and 467 /// Builds a SSA graph for FunctionNodes, found in FunctionExpressions and
428 /// Procedures. 468 /// Procedures.
429 void buildFunctionNode(ir.FunctionNode functionNode) { 469 void buildFunctionNode(ir.FunctionNode functionNode) {
430 openFunction(); 470 openFunction();
431 if (functionNode.parent is ir.Procedure && 471 if (functionNode.parent is ir.Procedure &&
432 (functionNode.parent as ir.Procedure).kind == 472 (functionNode.parent as ir.Procedure).kind ==
433 ir.ProcedureKind.Factory) { 473 ir.ProcedureKind.Factory) {
434 _addClassTypeVariablesIfNeeded(functionNode.parent); 474 _addClassTypeVariablesIfNeeded(functionNode.parent);
435 } 475 }
436 functionNode.body.accept(this); 476 functionNode.body.accept(this);
(...skipping 2590 matching lines...) Expand 10 before | Expand all | Expand 10 after
3027 enterBlock.setBlockFlow( 3067 enterBlock.setBlockFlow(
3028 new HTryBlockInformation( 3068 new HTryBlockInformation(
3029 kernelBuilder.wrapStatementGraph(bodyGraph), 3069 kernelBuilder.wrapStatementGraph(bodyGraph),
3030 exception, 3070 exception,
3031 kernelBuilder.wrapStatementGraph(catchGraph), 3071 kernelBuilder.wrapStatementGraph(catchGraph),
3032 kernelBuilder.wrapStatementGraph(finallyGraph)), 3072 kernelBuilder.wrapStatementGraph(finallyGraph)),
3033 exitBlock); 3073 exitBlock);
3034 kernelBuilder.inTryStatement = previouslyInTryStatement; 3074 kernelBuilder.inTryStatement = previouslyInTryStatement;
3035 } 3075 }
3036 } 3076 }
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