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

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

Issue 2841213002: dart2js-kernel: Bind type variables in generative constructor. (Closed)
Patch Set: Created 3 years, 8 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 | « no previous file | 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';
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 graph.sourceInformation = 151 graph.sourceInformation =
152 sourceInformationBuilder.buildVariableDeclaration(); 152 sourceInformationBuilder.buildVariableDeclaration();
153 this.localsHandler = new LocalsHandler( 153 this.localsHandler = new LocalsHandler(
154 this, targetElement, null, nativeData, interceptorData); 154 this, targetElement, null, nativeData, interceptorData);
155 this.astAdapter = new KernelAstAdapter(kernel, compiler.backend, 155 this.astAdapter = new KernelAstAdapter(kernel, compiler.backend,
156 resolvedAst, kernel.nodeToAst, kernel.nodeToElement); 156 resolvedAst, kernel.nodeToAst, kernel.nodeToElement);
157 target = astAdapter.getInitialKernelNode(targetElement); 157 target = astAdapter.getInitialKernelNode(targetElement);
158 if (targetElement is ConstructorBodyElement) { 158 if (targetElement is ConstructorBodyElement) {
159 _targetIsConstructorBody = true; 159 _targetIsConstructorBody = true;
160 } 160 }
161 _targetStack.add(target);
161 } 162 }
162 163
163 HGraph build() { 164 HGraph build() {
164 // TODO(het): no reason to do this here... 165 // TODO(het): no reason to do this here...
165 HInstruction.idCounter = 0; 166 HInstruction.idCounter = 0;
166 if (target is ir.Procedure) { 167 if (target is ir.Procedure) {
167 _targetFunction = (target as ir.Procedure).function; 168 _targetFunction = (target as ir.Procedure).function;
168 buildFunctionNode(_targetFunction); 169 buildFunctionNode(_targetFunction);
169 } else if (target is ir.Field) { 170 } else if (target is ir.Field) {
170 buildField(target); 171 buildField(target);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 if (typeBuilder.checkOrTrustTypes) { 213 if (typeBuilder.checkOrTrustTypes) {
213 ResolutionInterfaceType type = commonElements.boolType; 214 ResolutionInterfaceType type = commonElements.boolType;
214 return typeBuilder.potentiallyCheckOrTrustType(value, type, 215 return typeBuilder.potentiallyCheckOrTrustType(value, type,
215 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); 216 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK);
216 } 217 }
217 HInstruction result = new HBoolify(value, commonMasks.boolType); 218 HInstruction result = new HBoolify(value, commonMasks.boolType);
218 add(result); 219 add(result);
219 return result; 220 return result;
220 } 221 }
221 222
223 /// Extend current method parameters with parameters for the class type
224 /// parameters. If the class has type parameters but does not need them, bind
225 /// to `dynamic` (represented as `null`) so the bindings are available for
226 /// building types up the inheritance chain of generative constructors.
222 void _addClassTypeVariablesIfNeeded(ir.Member constructor) { 227 void _addClassTypeVariablesIfNeeded(ir.Member constructor) {
223 var enclosing = constructor.enclosingClass; 228 var enclosing = constructor.enclosingClass;
224 if (rtiNeed.classNeedsRti(astAdapter.getElement(enclosing))) { 229 bool needParameters;
225 enclosing.typeParameters.forEach((ir.TypeParameter typeParameter) { 230 enclosing.typeParameters.forEach((ir.TypeParameter typeParameter) {
226 var typeParamElement = astAdapter.getElement(typeParameter); 231 var typeParamElement = astAdapter.getElement(typeParameter);
227 HParameterValue param = 232 HInstruction param;
228 addParameter(typeParamElement, commonMasks.nonNullType); 233 needParameters ??=
229 // This is a little bit wacky (and n^2) until we make the localsHandler 234 rtiNeed.classNeedsRti(astAdapter.getElement(enclosing));
230 // take Kernel DartTypes instead of just the AST DartTypes. 235 if (needParameters) {
231 var typeVariableType = astAdapter 236 param = addParameter(typeParamElement, commonMasks.nonNullType);
232 .getClass(enclosing) 237 } else {
233 .typeVariables 238 // Unused, so bind to `dynamic`.
234 .firstWhere( 239 param = graph.addConstantNull(closedWorld);
235 (ResolutionTypeVariableType i) => i.name == typeParameter.name); 240 }
236 localsHandler.directLocals[ 241 // This is a little bit wacky (and n^2) until we make the localsHandler
237 localsHandler.getTypeVariableAsLocal(typeVariableType)] = param; 242 // take Kernel DartTypes instead of just the AST DartTypes.
238 }); 243 var typeVariableType = astAdapter
239 } 244 .getClass(enclosing)
245 .typeVariables
246 .firstWhere(
247 (ResolutionTypeVariableType i) => i.name == typeParameter.name);
248 localsHandler.directLocals[
249 localsHandler.getTypeVariableAsLocal(typeVariableType)] = param;
250 });
240 } 251 }
241 252
242 /// Builds generative constructors. 253 /// Builds a generative constructor.
243 /// 254 ///
244 /// Generative constructors are built in two stages. 255 /// Generative constructors are built in stages, in effect inlining the
256 /// initializers and constructor bodies up the inheritance chain.
245 /// 257 ///
246 /// First, the field values for every instance field for every class in the 258 /// 1. Extend method parameters with parameters the class's type parameters.
Siggi Cherem (dart-lang) 2017/04/27 00:32:27 with parameters the => with the
247 /// class hierarchy are collected. Then, create a function body that sets 259 ///
248 /// all of the instance fields to the collected values and call the 260 /// 2. Add type checks for value parameters (might need result of (1)).
249 /// constructor bodies for all constructors in the hierarchy. 261 ///
262 /// 3. Walk inheritance chain to build bindings for type parameters of
263 /// superclasses and mixed-in classes.
264 ///
265 /// 4. Collect initializer values. Walk up inheritance chain to collect field
266 /// initializers from field declarations, initializing parameters and
267 /// initializer.
Siggi Cherem (dart-lang) 2017/04/27 00:32:27 "intializer" => "initializer assignments"? or "ini
268 ///
269 /// 5. Create reified type information for instance.
Siggi Cherem (dart-lang) 2017/04/27 00:32:27 nit: for instance => for the object instance? (I r
270 ///
271 /// 6. Allocate instance and assign initializers and reified type information
Siggi Cherem (dart-lang) 2017/04/27 00:32:27 instance => object instance
272 /// to fields by calling JavaScript constructor.
273 ///
274 /// 7. Walk inheritance chain to call or inline constructor bodies.
275 ///
276 /// All the bindings are put in the constructor's locals handler. The
277 /// implication is that a class cannot be extended or mixed-in twice. If we in
278 /// future support repeated uses of a mixin class, we should do so by cloning
Siggi Cherem (dart-lang) 2017/04/27 00:32:27 in future => in the future
279 /// the mixin class in the Kernel input.
250 void buildConstructor(ir.Constructor constructor) { 280 void buildConstructor(ir.Constructor constructor) {
281 ir.Class constructedClass = constructor.enclosingClass;
282
251 openFunction(); 283 openFunction();
252 _addClassTypeVariablesIfNeeded(constructor); 284 _addClassTypeVariablesIfNeeded(constructor);
253 285
286 // TODO(sra): Type parameter constraint checks.
287
288 // TODO(sra): Checked mode parameter checks.
289
254 // Collect field values for the current class. 290 // Collect field values for the current class.
255 // TODO(het): Does kernel always put field initializers in the constructor
256 // initializer list? If so then this is unnecessary...
257 Map<ir.Field, HInstruction> fieldValues = 291 Map<ir.Field, HInstruction> fieldValues =
258 _collectFieldValues(constructor.enclosingClass); 292 _collectFieldValues(constructedClass);
259 List<ir.Constructor> constructorChain = <ir.Constructor>[]; 293 List<ir.Constructor> constructorChain = <ir.Constructor>[];
260
261 _buildInitializers(constructor, constructorChain, fieldValues); 294 _buildInitializers(constructor, constructorChain, fieldValues);
262 295
263 final constructorArguments = <HInstruction>[]; 296 final constructorArguments = <HInstruction>[];
264 // Doing this instead of fieldValues.forEach because we haven't defined the 297 // Doing this instead of fieldValues.forEach because we haven't defined the
265 // order of the arguments here. We can define that with JElements. 298 // order of the arguments here. We can define that with JElements.
266 astAdapter.getClass(constructor.enclosingClass).forEachInstanceField( 299 astAdapter.getClass(constructedClass).forEachInstanceField(
267 (ClassElement enclosingClass, FieldElement member) { 300 (ClassElement enclosingClass, FieldElement member) {
268 var value = fieldValues[astAdapter.getFieldFromElement(member)]; 301 var value = fieldValues[astAdapter.getFieldFromElement(member)];
302 assert(value != null,
303 'No value for field ${member} aka ${astAdapter.getFieldFromElement(mem ber)}');
269 constructorArguments.add(value); 304 constructorArguments.add(value);
270 }, includeSuperAndInjectedMembers: true); 305 }, includeSuperAndInjectedMembers: true);
271 306
272 // TODO(het): If the class needs runtime type information, add it as a 307 // Create the runtime type information, if needed.
273 // constructor argument. 308 bool hasRtiInput = backend.rtiNeed
309 .classNeedsRtiField(astAdapter.getClass(constructedClass));
310 if (hasRtiInput) {
311 // Read the values of the type arguments and create a HTypeInfoExpression
312 // to set on the newly create object.
313 List<HInstruction> typeArguments = <HInstruction>[];
314 for (ir.DartType typeParameter
315 in constructedClass.thisType.typeArguments) {
316 HInstruction argument = localsHandler.readLocal(localsHandler
317 .getTypeVariableAsLocal(astAdapter.getDartType(typeParameter)
318 as ResolutionTypeVariableType));
319 typeArguments.add(argument);
320 }
321
322 HInstruction typeInfo = new HTypeInfoExpression(
323 TypeInfoExpressionKind.INSTANCE,
324 astAdapter.getClass(constructedClass).thisType,
325 typeArguments,
326 commonMasks.dynamicType);
327 add(typeInfo);
328 constructorArguments.add(typeInfo);
329 }
330
274 HInstruction newObject = new HCreate( 331 HInstruction newObject = new HCreate(
275 astAdapter.getClass(constructor.enclosingClass), 332 astAdapter.getClass(constructedClass),
276 constructorArguments, 333 constructorArguments,
277 new TypeMask.nonNullExact( 334 new TypeMask.nonNullExact(
278 astAdapter.getClass(constructor.enclosingClass), closedWorld), 335 astAdapter.getClass(constructedClass), closedWorld),
279 instantiatedTypes: <ResolutionInterfaceType>[ 336 instantiatedTypes: <ResolutionInterfaceType>[
280 astAdapter.getClass(constructor.enclosingClass).thisType 337 astAdapter.getClass(constructedClass).thisType
281 ], 338 ],
282 hasRtiInput: false); 339 hasRtiInput: hasRtiInput);
283 340
284 add(newObject); 341 add(newObject);
285 342
286 // Generate calls to the constructor bodies. 343 // Generate calls to the constructor bodies.
287 344
288 for (ir.Constructor body in constructorChain.reversed) { 345 for (ir.Constructor body in constructorChain.reversed) {
289 if (_isEmptyStatement(body.function.body)) continue; 346 if (_isEmptyStatement(body.function.body)) continue;
290 347
291 List<HInstruction> bodyCallInputs = <HInstruction>[]; 348 List<HInstruction> bodyCallInputs = <HInstruction>[];
292 bodyCallInputs.add(newObject); 349 bodyCallInputs.add(newObject);
(...skipping 16 matching lines...) Expand all
309 }); 366 });
310 367
311 // If there are locals that escape (i.e. mutated in closures), we pass the 368 // If there are locals that escape (i.e. mutated in closures), we pass the
312 // box to the constructor. 369 // box to the constructor.
313 ClosureScope scopeData = parameterClosureData 370 ClosureScope scopeData = parameterClosureData
314 .capturingScopes[constructorElement.resolvedAst.node]; 371 .capturingScopes[constructorElement.resolvedAst.node];
315 if (scopeData != null) { 372 if (scopeData != null) {
316 bodyCallInputs.add(localsHandler.readLocal(scopeData.boxElement)); 373 bodyCallInputs.add(localsHandler.readLocal(scopeData.boxElement));
317 } 374 }
318 375
319 // TODO(sra): Pass type arguments. 376 // Pass type arguments.
377 ir.Class currentClass = body.enclosingClass;
378 if (backend.rtiNeed.classNeedsRti(astAdapter.getClass(currentClass))) {
379 for (ir.DartType typeParameter in currentClass.thisType.typeArguments) {
380 HInstruction argument = localsHandler.readLocal(localsHandler
381 .getTypeVariableAsLocal(astAdapter.getDartType(typeParameter)
382 as ResolutionTypeVariableType));
383 bodyCallInputs.add(argument);
384 }
385 }
320 386
321 _invokeConstructorBody(body, bodyCallInputs); 387 _invokeConstructorBody(body, bodyCallInputs);
322 } 388 }
323 389
324 closeAndGotoExit(new HReturn(newObject, null)); 390 closeAndGotoExit(new HReturn(newObject, null));
325 closeFunction(); 391 closeFunction();
326 } 392 }
327 393
328 static bool _isEmptyStatement(ir.Statement body) { 394 static bool _isEmptyStatement(ir.Statement body) {
329 if (body is ir.EmptyStatement) return true; 395 if (body is ir.EmptyStatement) return true;
330 if (body is ir.Block) return body.statements.every(_isEmptyStatement); 396 if (body is ir.Block) return body.statements.every(_isEmptyStatement);
331 return false; 397 return false;
332 } 398 }
333 399
334 void _invokeConstructorBody( 400 void _invokeConstructorBody(
335 ir.Constructor constructor, List<HInstruction> inputs) { 401 ir.Constructor constructor, List<HInstruction> inputs) {
336 // TODO(sra): Inline the constructor body. 402 // TODO(sra): Inline the constructor body.
337 MemberEntity constructorBody = 403 MemberEntity constructorBody =
338 astAdapter.getConstructorBodyEntity(constructor); 404 astAdapter.getConstructorBodyEntity(constructor);
339 HInvokeConstructorBody invoke = new HInvokeConstructorBody( 405 HInvokeConstructorBody invoke = new HInvokeConstructorBody(
340 constructorBody, inputs, commonMasks.nonNullType); 406 constructorBody, inputs, commonMasks.nonNullType);
341 add(invoke); 407 add(invoke);
342 } 408 }
343 409
410 withCurrentIrNode(ir.Node node, f()) {
411 compiler.reporter.withCurrentElement(astAdapter.getElement(node), f);
412 }
413
414 /// Sets context for generating code that is the result of inlining
415 /// [inlinedTarget].
416 inlinedFrom(ir.TreeNode inlinedTarget, f()) {
417 withCurrentIrNode(inlinedTarget, () {
418 SourceInformationBuilder oldSourceInformationBuilder =
419 sourceInformationBuilder;
420 // TODO(sra): Update sourceInformationBuilder to Kernel.
421 // sourceInformationBuilder =
422 // sourceInformationBuilder.forContext(resolvedAst);
423 _targetStack.add(inlinedTarget);
424 var result = f();
425 sourceInformationBuilder = oldSourceInformationBuilder;
426 _targetStack.removeLast();
427 return result;
428 });
429 }
430
344 /// Maps the instance fields of a class to their SSA values. 431 /// Maps the instance fields of a class to their SSA values.
345 Map<ir.Field, HInstruction> _collectFieldValues(ir.Class clazz) { 432 Map<ir.Field, HInstruction> _collectFieldValues(ir.Class clazz) {
346 final fieldValues = <ir.Field, HInstruction>{}; 433 final fieldValues = <ir.Field, HInstruction>{};
347 434
348 for (var field in clazz.fields) { 435 for (var field in clazz.fields) {
349 if (field.isInstanceMember) { 436 if (field.isInstanceMember) {
350 if (field.initializer == null) { 437 if (field.initializer == null) {
351 fieldValues[field] = graph.addConstantNull(closedWorld); 438 fieldValues[field] = graph.addConstantNull(closedWorld);
352 } else { 439 } else {
353 // Gotta update the resolvedAst when we're looking at field values 440 // Gotta update the resolvedAst when we're looking at field values
354 // outside the constructor. 441 // outside the constructor.
355 astAdapter.pushResolvedAst(field); 442 astAdapter.pushResolvedAst(field);
356 field.initializer.accept(this); 443 inlinedFrom(field, () {
357 fieldValues[field] = pop(); 444 field.initializer.accept(this);
445 fieldValues[field] = pop();
446 });
358 astAdapter.popResolvedAstStack(); 447 astAdapter.popResolvedAstStack();
359 } 448 }
360 } 449 }
361 } 450 }
362 451
363 return fieldValues; 452 return fieldValues;
364 } 453 }
365 454
366 /// Collects field initializers all the way up the inheritance chain. 455 /// Collects field initializers all the way up the inheritance chain.
367 void _buildInitializers( 456 void _buildInitializers(
368 ir.Constructor constructor, 457 ir.Constructor constructor,
369 List<ir.Constructor> constructorChain, 458 List<ir.Constructor> constructorChain,
370 Map<ir.Field, HInstruction> fieldValues) { 459 Map<ir.Field, HInstruction> fieldValues) {
460 astAdapter.assertAtResolvedAstFor(constructor);
371 constructorChain.add(constructor); 461 constructorChain.add(constructor);
462
372 var foundSuperOrRedirectCall = false; 463 var foundSuperOrRedirectCall = false;
373 for (var initializer in constructor.initializers) { 464 for (var initializer in constructor.initializers) {
374 if (initializer is ir.SuperInitializer || 465 if (initializer is ir.FieldInitializer) {
375 initializer is ir.RedirectingInitializer) {
376 foundSuperOrRedirectCall = true;
377 var superOrRedirectConstructor = initializer.target;
378 var arguments = _normalizeAndBuildArguments(
379 superOrRedirectConstructor.function, initializer.arguments);
380 _buildInlinedInitializers(superOrRedirectConstructor, arguments,
381 constructorChain, fieldValues);
382 } else if (initializer is ir.FieldInitializer) {
383 initializer.value.accept(this); 466 initializer.value.accept(this);
384 fieldValues[initializer.field] = pop(); 467 fieldValues[initializer.field] = pop();
468 } else if (initializer is ir.SuperInitializer) {
469 assert(!foundSuperOrRedirectCall);
470 foundSuperOrRedirectCall = true;
471 _inlineSuperInitializer(
472 initializer, constructorChain, fieldValues, constructor);
473 } else if (initializer is ir.RedirectingInitializer) {
474 assert(!foundSuperOrRedirectCall);
475 foundSuperOrRedirectCall = true;
476 _inlineRedirectingInitializer(
477 initializer, constructorChain, fieldValues, constructor);
478 } else if (initializer is ir.LocalInitializer) {
479 assert(false, 'ir.LocalInitializer not handled');
480 } else if (initializer is ir.InvalidInitializer) {
481 assert(false, 'ir.InvalidInitializer not handled');
385 } 482 }
386 } 483 }
387 484
388 if (!foundSuperOrRedirectCall) { 485 if (!foundSuperOrRedirectCall) {
389 assert(constructor.enclosingClass == astAdapter.objectClass, 486 assert(
390 'All constructors have super-constructor initializers, except Object() '); 487 constructor.enclosingClass == astAdapter.objectClass,
488 'All constructors should have super- or redirecting- initializers,'
489 ' except Object()');
391 } 490 }
392 } 491 }
393 492
394 List<HInstruction> _normalizeAndBuildArguments( 493 List<HInstruction> _normalizeAndBuildArguments(
395 ir.FunctionNode function, ir.Arguments arguments) { 494 ir.FunctionNode function, ir.Arguments arguments) {
396 var signature = astAdapter.getFunctionSignature(function); 495 var signature = astAdapter.getFunctionSignature(function);
397 var builtArguments = <HInstruction>[]; 496 var builtArguments = <HInstruction>[];
398 var positionalIndex = 0; 497 var positionalIndex = 0;
399 signature.forEachRequiredParameter((_) { 498 signature.forEachRequiredParameter((_) {
400 arguments.positional[positionalIndex++].accept(this); 499 arguments.positional[positionalIndex++].accept(this);
(...skipping 24 matching lines...) Expand all
425 assert(invariant(element, constantValue != null, 524 assert(invariant(element, constantValue != null,
426 message: 'No constant computed for $element')); 525 message: 'No constant computed for $element'));
427 builtArguments.add(graph.addConstant(constantValue, closedWorld)); 526 builtArguments.add(graph.addConstant(constantValue, closedWorld));
428 } 527 }
429 }); 528 });
430 } 529 }
431 530
432 return builtArguments; 531 return builtArguments;
433 } 532 }
434 533
534 /// Creates localsHandler bindings for type parameters of a Supertype.
535 void _bindSupertypeTypeParameters(ir.Supertype supertype) {
536 ir.Class cls = supertype.classNode;
537 var parameters = cls.typeParameters;
538 var arguments = supertype.typeArguments;
539 assert(arguments.length == parameters.length);
540
541 for (int i = 0; i < parameters.length; i++) {
542 ir.DartType argument = arguments[i];
543 ir.TypeParameter parameter = parameters[i];
544
545 localsHandler.updateLocal(
546 localsHandler.getTypeVariableAsLocal(
547 astAdapter.getDartType(new ir.TypeParameterType(parameter))),
548 typeBuilder.analyzeTypeArgument(
549 astAdapter.getDartType(argument), sourceElement));
550 }
551 }
552
553 /// Inlines the given redirecting [constructor]'s initializers by collecting
554 /// its field values and building its constructor initializers. We visit super
555 /// constructors all the way up to the [Object] constructor.
556 void _inlineRedirectingInitializer(
557 ir.RedirectingInitializer initializer,
558 List<ir.Constructor> constructorChain,
559 Map<ir.Field, HInstruction> fieldValues,
560 ir.Constructor caller) {
561 var superOrRedirectConstructor = initializer.target;
562 var arguments = _normalizeAndBuildArguments(
563 superOrRedirectConstructor.function, initializer.arguments);
564
565 // Redirecting initializer already has [localsHandler] bindings for type
566 // parameters from the redirecting constructor.
567
568 // For redirecting constructors, the fields will be initialized later by the
569 // effective target, so we don't do it here.
570
571 _inlineSuperOrRedirectCommon(initializer, superOrRedirectConstructor,
572 arguments, constructorChain, fieldValues, caller);
573 }
574
435 /// Inlines the given super [constructor]'s initializers by collecting its 575 /// Inlines the given super [constructor]'s initializers by collecting its
436 /// field values and building its constructor initializers. We visit super 576 /// field values and building its constructor initializers. We visit super
437 /// constructors all the way up to the [Object] constructor. 577 /// constructors all the way up to the [Object] constructor.
438 void _buildInlinedInitializers( 578 void _inlineSuperInitializer(
579 ir.SuperInitializer initializer,
580 List<ir.Constructor> constructorChain,
581 Map<ir.Field, HInstruction> fieldValues,
582 ir.Constructor caller) {
583 var target = initializer.target;
584 var arguments =
585 _normalizeAndBuildArguments(target.function, initializer.arguments);
586
587 ir.Class callerClass = caller.enclosingClass;
588 _bindSupertypeTypeParameters(callerClass.supertype);
589 if (callerClass.mixedInType != null) {
590 _bindSupertypeTypeParameters(callerClass.mixedInType);
591 }
592
593 ir.Class cls = target.enclosingClass;
594
595 inlinedFrom(target, () {
596 fieldValues.addAll(_collectFieldValues(cls));
597 });
598
599 _inlineSuperOrRedirectCommon(
600 initializer, target, arguments, constructorChain, fieldValues, caller);
601 }
602
603 void _inlineSuperOrRedirectCommon(
604 ir.Initializer initializer,
439 ir.Constructor constructor, 605 ir.Constructor constructor,
440 List<HInstruction> arguments, 606 List<HInstruction> arguments,
441 List<ir.Constructor> constructorChain, 607 List<ir.Constructor> constructorChain,
442 Map<ir.Field, HInstruction> fieldValues) { 608 Map<ir.Field, HInstruction> fieldValues,
443 // TODO(het): Handle RTI if class needs it 609 ir.Constructor caller) {
444 fieldValues.addAll(_collectFieldValues(constructor.enclosingClass));
445
446 var signature = astAdapter.getFunctionSignature(constructor.function); 610 var signature = astAdapter.getFunctionSignature(constructor.function);
447 var index = 0; 611 var index = 0;
448 signature.orderedForEachParameter((ParameterElement parameter) { 612 signature.orderedForEachParameter((ParameterElement parameter) {
449 HInstruction argument = arguments[index++]; 613 HInstruction argument = arguments[index++];
450 // Because we are inlining the initializer, we must update 614 // Because we are inlining the initializer, we must update
451 // what was given as parameter. This will be used in case 615 // what was given as parameter. This will be used in case
452 // there is a parameter check expression in the initializer. 616 // there is a parameter check expression in the initializer.
453 parameters[parameter] = argument; 617 parameters[parameter] = argument;
454 localsHandler.updateLocal(parameter, argument); 618 localsHandler.updateLocal(parameter, argument);
455 }); 619 });
456 620
457 // TODO(het): set the locals handler state as if we were inlining the 621 // Set the locals handler state as if we were inlining the constructor.
458 // constructor. 622 astAdapter.pushResolvedAst(constructor);
459 _buildInitializers(constructor, constructorChain, fieldValues); 623 ResolvedAst resolvedAst = astAdapter.getElement(constructor).resolvedAst;
624 ClosureClassMap oldClosureData = localsHandler.closureData;
625 ClosureClassMap newClosureData =
626 compiler.closureToClassMapper.getClosureToClassMapping(resolvedAst);
627 localsHandler.closureData = newClosureData;
628 if (resolvedAst.kind == ResolvedAstKind.PARSED) {
629 localsHandler.enterScope(
630 resolvedAst.node, astAdapter.getElement(constructor));
631 }
632 inlinedFrom(constructor, () {
633 _buildInitializers(constructor, constructorChain, fieldValues);
634 });
635 localsHandler.closureData = oldClosureData;
636 astAdapter.popResolvedAstStack();
460 } 637 }
461 638
462 /// Builds generative constructor body. 639 /// Builds generative constructor body.
463 void buildConstructorBody(ir.Constructor constructor) { 640 void buildConstructorBody(ir.Constructor constructor) {
464 openFunction(); 641 openFunction();
642 _addClassTypeVariablesIfNeeded(constructor);
465 constructor.function.body.accept(this); 643 constructor.function.body.accept(this);
466 closeFunction(); 644 closeFunction();
467 } 645 }
468 646
469 /// Builds a SSA graph for FunctionNodes, found in FunctionExpressions and 647 /// Builds a SSA graph for FunctionNodes, found in FunctionExpressions and
470 /// Procedures. 648 /// Procedures.
471 void buildFunctionNode(ir.FunctionNode functionNode) { 649 void buildFunctionNode(ir.FunctionNode functionNode) {
472 openFunction(); 650 openFunction();
473 if (functionNode.parent is ir.Procedure && 651 if (functionNode.parent is ir.Procedure &&
474 (functionNode.parent as ir.Procedure).kind == 652 (functionNode.parent as ir.Procedure).kind ==
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 push(trap); 718 push(trap);
541 } 719 }
542 720
543 /// Returns the current source element. This is used by the type builder. 721 /// Returns the current source element. This is used by the type builder.
544 /// 722 ///
545 /// The returned element is a declaration element. 723 /// The returned element is a declaration element.
546 // TODO(efortuna): Update this when we implement inlining. 724 // TODO(efortuna): Update this when we implement inlining.
547 // TODO(sra): Re-implement type builder using Kernel types and the 725 // TODO(sra): Re-implement type builder using Kernel types and the
548 // `target` for context. 726 // `target` for context.
549 @override 727 @override
550 Element get sourceElement => _sourceElementForTarget(target); 728 Element get sourceElement => _sourceElementForTarget(_targetStack.last);
729
730 List<ir.Node> _targetStack = <ir.Node>[];
551 731
552 Element _sourceElementForTarget(ir.Node target) { 732 Element _sourceElementForTarget(ir.Node target) {
553 // For closure-converted (i.e. local functions) the source element is the 733 // For closure-converted (i.e. local functions) the source element is the
554 // 'call' method of the class that represents the closure. 734 // 'call' method of the class that represents the closure.
555 if (target is ir.FunctionExpression) { 735 Element callMethodOfClosureClass() {
556 LocalFunctionElement element = astAdapter.getElement(target); 736 LocalFunctionElement element = astAdapter.getElement(target);
557 ClosureClassMap classMap = 737 ClosureClassMap classMap =
558 closureToClassMapper.getClosureToClassMapping(element.resolvedAst); 738 closureToClassMapper.getClosureToClassMapping(element.resolvedAst);
559 return classMap.callElement; 739 return classMap.callElement;
560 } 740 }
741
742 if (target is ir.FunctionExpression) {
743 return callMethodOfClosureClass();
744 }
561 if (target is ir.FunctionDeclaration) { 745 if (target is ir.FunctionDeclaration) {
562 LocalFunctionElement element = astAdapter.getElement(target); 746 return callMethodOfClosureClass();
563 ClosureClassMap classMap =
564 closureToClassMapper.getClosureToClassMapping(element.resolvedAst);
565 return classMap.callElement;
566 } 747 }
567 Element element = astAdapter.getElement(target); 748 Element element = astAdapter.getElement(target);
568 return element; 749 return element;
569 } 750 }
570 751
571 @override 752 @override
572 void visitCheckLibraryIsLoaded(ir.CheckLibraryIsLoaded checkLoad) { 753 void visitCheckLibraryIsLoaded(ir.CheckLibraryIsLoaded checkLoad) {
573 HInstruction prefixConstant = graph.addConstantString( 754 HInstruction prefixConstant = graph.addConstantString(
574 new DartString.literal(checkLoad.import.name), closedWorld); 755 new DartString.literal(checkLoad.import.name), closedWorld);
575 var prefixElement = astAdapter.getElement(checkLoad.import); 756 var prefixElement = astAdapter.getElement(checkLoad.import);
(...skipping 1437 matching lines...) Expand 10 before | Expand all | Expand 10 after
2013 ir.FunctionNode target, ir.Arguments arguments) { 2194 ir.FunctionNode target, ir.Arguments arguments) {
2014 // Visit arguments in source order, then re-order and fill in defaults. 2195 // Visit arguments in source order, then re-order and fill in defaults.
2015 var values = _visitPositionalArguments(arguments); 2196 var values = _visitPositionalArguments(arguments);
2016 2197
2017 while (values.length < target.positionalParameters.length) { 2198 while (values.length < target.positionalParameters.length) {
2018 ir.VariableDeclaration parameter = 2199 ir.VariableDeclaration parameter =
2019 target.positionalParameters[values.length]; 2200 target.positionalParameters[values.length];
2020 values.add(_defaultValueForParameter(parameter)); 2201 values.add(_defaultValueForParameter(parameter));
2021 } 2202 }
2022 2203
2023 if (arguments.named.isEmpty) return values; 2204 if (arguments.named.isNotEmpty) {
2205 var namedValues = <String, HInstruction>{};
2206 for (ir.NamedExpression argument in arguments.named) {
2207 argument.value.accept(this);
2208 namedValues[argument.name] = pop();
2209 }
2024 2210
2025 var namedValues = <String, HInstruction>{}; 2211 // Visit named arguments in parameter-position order, selecting provided
2026 for (ir.NamedExpression argument in arguments.named) { 2212 // or default value.
2027 argument.value.accept(this); 2213 // TODO(sra): Ensure the stored order is canonical so we don't have to
2028 namedValues[argument.name] = pop(); 2214 // sort. The old builder uses CallStructure.makeArgumentList which depends
2215 // on the old element model.
2216 var namedParameters = target.namedParameters.toList()
2217 ..sort((ir.VariableDeclaration a, ir.VariableDeclaration b) =>
2218 a.name.compareTo(b.name));
2219 for (ir.VariableDeclaration parameter in namedParameters) {
2220 HInstruction value = namedValues[parameter.name];
2221 if (value == null) {
2222 values.add(_defaultValueForParameter(parameter));
2223 } else {
2224 values.add(value);
2225 namedValues.remove(parameter.name);
2226 }
2227 }
2228 assert(namedValues.isEmpty);
2029 } 2229 }
2030 2230
2031 // Visit named arguments in parameter-position order, selecting provided or 2231 return values;
2032 // default value. 2232 }
2033 // TODO(sra): Ensure the stored order is canonical so we don't have to 2233
2034 // sort. The old builder uses CallStructure.makeArgumentList which depends 2234 void _addTypeArguments(List<HInstruction> values, ir.Arguments arguments) {
2035 // on the old element model. 2235 // need to translate type to
2036 var namedParameters = target.namedParameters.toList() 2236 for (ir.DartType type in arguments.types) {
2037 ..sort((ir.VariableDeclaration a, ir.VariableDeclaration b) => 2237 values.add(typeBuilder.analyzeTypeArgument(
2038 a.name.compareTo(b.name)); 2238 astAdapter.getDartType(type), sourceElement));
2039 for (ir.VariableDeclaration parameter in namedParameters) {
2040 HInstruction value = namedValues[parameter.name];
2041 if (value == null) {
2042 values.add(_defaultValueForParameter(parameter));
2043 } else {
2044 values.add(value);
2045 namedValues.remove(parameter.name);
2046 }
2047 } 2239 }
2048 assert(namedValues.isEmpty);
2049
2050 return values;
2051 } 2240 }
2052 2241
2053 HInstruction _defaultValueForParameter(ir.VariableDeclaration parameter) { 2242 HInstruction _defaultValueForParameter(ir.VariableDeclaration parameter) {
2054 ir.Expression initializer = parameter.initializer; 2243 ir.Expression initializer = parameter.initializer;
2055 if (initializer == null) return graph.addConstantNull(closedWorld); 2244 if (initializer == null) return graph.addConstantNull(closedWorld);
2056 // TODO(sra): Evaluate constant in ir.Node domain. 2245 // TODO(sra): Evaluate constant in ir.Node domain.
2057 ConstantValue constant = 2246 ConstantValue constant =
2058 astAdapter.getConstantForParameterDefaultValue(initializer); 2247 astAdapter.getConstantForParameterDefaultValue(initializer);
2059 if (constant == null) return graph.addConstantNull(closedWorld); 2248 if (constant == null) return graph.addConstantNull(closedWorld);
2060 return graph.addConstant(constant, closedWorld); 2249 return graph.addConstant(constant, closedWorld);
2061 } 2250 }
2062 2251
2063 @override 2252 @override
2064 void visitStaticInvocation(ir.StaticInvocation invocation) { 2253 void visitStaticInvocation(ir.StaticInvocation invocation) {
2065 ir.Procedure target = invocation.target; 2254 ir.Procedure target = invocation.target;
2066 if (astAdapter.isInForeignLibrary(target)) { 2255 if (astAdapter.isInForeignLibrary(target)) {
2067 handleInvokeStaticForeign(invocation, target); 2256 handleInvokeStaticForeign(invocation, target);
2068 return; 2257 return;
2069 } 2258 }
2070 TypeMask typeMask = astAdapter.returnTypeOf(target); 2259 TypeMask typeMask = astAdapter.returnTypeOf(target);
2071 2260
2072 // TODO(sra): For JS interop external functions, use a different function to 2261 // TODO(sra): For JS interop external functions, use a different function to
2073 // build arguments. 2262 // build arguments.
2074 List<HInstruction> arguments = 2263 List<HInstruction> arguments =
2075 _visitArgumentsForStaticTarget(target.function, invocation.arguments); 2264 _visitArgumentsForStaticTarget(target.function, invocation.arguments);
2076 2265
2266 // Factory constructors take type parameters; other static methods ignore
2267 // them.
2268 if (target.kind == ir.ProcedureKind.Factory) {
2269 if (backend.rtiNeed
2270 .classNeedsRti(astAdapter.getClass(target.enclosingClass))) {
2271 _addTypeArguments(arguments, invocation.arguments);
2272 }
2273 }
2274
2077 _pushStaticInvocation(target, arguments, typeMask); 2275 _pushStaticInvocation(target, arguments, typeMask);
2078 } 2276 }
2079 2277
2080 void handleInvokeStaticForeign( 2278 void handleInvokeStaticForeign(
2081 ir.StaticInvocation invocation, ir.Procedure target) { 2279 ir.StaticInvocation invocation, ir.Procedure target) {
2082 String name = target.name.name; 2280 String name = target.name.name;
2083 if (name == 'JS') { 2281 if (name == 'JS') {
2084 handleForeignJs(invocation); 2282 handleForeignJs(invocation);
2085 } else if (name == 'JS_CURRENT_ISOLATE_CONTEXT') { 2283 } else if (name == 'JS_CURRENT_ISOLATE_CONTEXT') {
2086 handleForeignJsCurrentIsolateContext(invocation); 2284 handleForeignJsCurrentIsolateContext(invocation);
(...skipping 692 matching lines...) Expand 10 before | Expand all | Expand 10 after
2779 _buildInvokeSuper(astAdapter.getSelector(invocation), 2977 _buildInvokeSuper(astAdapter.getSelector(invocation),
2780 _containingClass(invocation), invocation.interfaceTarget, arguments); 2978 _containingClass(invocation), invocation.interfaceTarget, arguments);
2781 } 2979 }
2782 2980
2783 @override 2981 @override
2784 void visitConstructorInvocation(ir.ConstructorInvocation invocation) { 2982 void visitConstructorInvocation(ir.ConstructorInvocation invocation) {
2785 ir.Constructor target = invocation.target; 2983 ir.Constructor target = invocation.target;
2786 // TODO(sra): For JS-interop targets, process arguments differently. 2984 // TODO(sra): For JS-interop targets, process arguments differently.
2787 List<HInstruction> arguments = 2985 List<HInstruction> arguments =
2788 _visitArgumentsForStaticTarget(target.function, invocation.arguments); 2986 _visitArgumentsForStaticTarget(target.function, invocation.arguments);
2987 if (backend.rtiNeed
2988 .classNeedsRti(astAdapter.getClass(target.enclosingClass))) {
2989 _addTypeArguments(arguments, invocation.arguments);
2990 }
2789 TypeMask typeMask = new TypeMask.nonNullExact( 2991 TypeMask typeMask = new TypeMask.nonNullExact(
2790 astAdapter.getClass(target.enclosingClass), closedWorld); 2992 astAdapter.getClass(target.enclosingClass), closedWorld);
2791 _pushStaticInvocation(target, arguments, typeMask); 2993 _pushStaticInvocation(target, arguments, typeMask);
2792 } 2994 }
2793 2995
2794 @override 2996 @override
2795 void visitIsExpression(ir.IsExpression isExpression) { 2997 void visitIsExpression(ir.IsExpression isExpression) {
2796 isExpression.operand.accept(this); 2998 isExpression.operand.accept(this);
2797 HInstruction expression = pop(); 2999 HInstruction expression = pop();
2798 pushIsTest(isExpression, isExpression.type, expression); 3000 pushIsTest(isExpression, isExpression.type, expression);
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
3218 enterBlock.setBlockFlow( 3420 enterBlock.setBlockFlow(
3219 new HTryBlockInformation( 3421 new HTryBlockInformation(
3220 kernelBuilder.wrapStatementGraph(bodyGraph), 3422 kernelBuilder.wrapStatementGraph(bodyGraph),
3221 exception, 3423 exception,
3222 kernelBuilder.wrapStatementGraph(catchGraph), 3424 kernelBuilder.wrapStatementGraph(catchGraph),
3223 kernelBuilder.wrapStatementGraph(finallyGraph)), 3425 kernelBuilder.wrapStatementGraph(finallyGraph)),
3224 exitBlock); 3426 exitBlock);
3225 kernelBuilder.inTryStatement = previouslyInTryStatement; 3427 kernelBuilder.inTryStatement = previouslyInTryStatement;
3226 } 3428 }
3227 } 3429 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698