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

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: fix analyzer warning Created 3 years, 7 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.
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.
268 ///
269 /// 5. Create reified type information for instance.
270 ///
271 /// 6. Allocate instance and assign initializers and reified type information
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
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 AstElement astElement = astAdapter.getElement(constructor);
624 ResolvedAst resolvedAst = astElement.resolvedAst;
625 ClosureClassMap oldClosureData = localsHandler.closureData;
626 ClosureClassMap newClosureData =
627 compiler.closureToClassMapper.getClosureToClassMapping(resolvedAst);
628 localsHandler.closureData = newClosureData;
629 if (resolvedAst.kind == ResolvedAstKind.PARSED) {
630 localsHandler.enterScope(
631 resolvedAst.node, astAdapter.getElement(constructor));
632 }
633 inlinedFrom(constructor, () {
634 _buildInitializers(constructor, constructorChain, fieldValues);
635 });
636 localsHandler.closureData = oldClosureData;
637 astAdapter.popResolvedAstStack();
460 } 638 }
461 639
462 /// Builds generative constructor body. 640 /// Builds generative constructor body.
463 void buildConstructorBody(ir.Constructor constructor) { 641 void buildConstructorBody(ir.Constructor constructor) {
464 openFunction(); 642 openFunction();
643 _addClassTypeVariablesIfNeeded(constructor);
465 constructor.function.body.accept(this); 644 constructor.function.body.accept(this);
466 closeFunction(); 645 closeFunction();
467 } 646 }
468 647
469 /// Builds a SSA graph for FunctionNodes, found in FunctionExpressions and 648 /// Builds a SSA graph for FunctionNodes, found in FunctionExpressions and
470 /// Procedures. 649 /// Procedures.
471 void buildFunctionNode(ir.FunctionNode functionNode) { 650 void buildFunctionNode(ir.FunctionNode functionNode) {
472 openFunction(); 651 openFunction();
473 if (functionNode.parent is ir.Procedure && 652 if (functionNode.parent is ir.Procedure &&
474 (functionNode.parent as ir.Procedure).kind == 653 (functionNode.parent as ir.Procedure).kind ==
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 push(trap); 719 push(trap);
541 } 720 }
542 721
543 /// Returns the current source element. This is used by the type builder. 722 /// Returns the current source element. This is used by the type builder.
544 /// 723 ///
545 /// The returned element is a declaration element. 724 /// The returned element is a declaration element.
546 // TODO(efortuna): Update this when we implement inlining. 725 // TODO(efortuna): Update this when we implement inlining.
547 // TODO(sra): Re-implement type builder using Kernel types and the 726 // TODO(sra): Re-implement type builder using Kernel types and the
548 // `target` for context. 727 // `target` for context.
549 @override 728 @override
550 Element get sourceElement => _sourceElementForTarget(target); 729 Element get sourceElement => _sourceElementForTarget(_targetStack.last);
730
731 List<ir.Node> _targetStack = <ir.Node>[];
551 732
552 Element _sourceElementForTarget(ir.Node target) { 733 Element _sourceElementForTarget(ir.Node target) {
553 // For closure-converted (i.e. local functions) the source element is the 734 // For closure-converted (i.e. local functions) the source element is the
554 // 'call' method of the class that represents the closure. 735 // 'call' method of the class that represents the closure.
555 if (target is ir.FunctionExpression) { 736 Element callMethodOfClosureClass() {
556 LocalFunctionElement element = astAdapter.getElement(target); 737 LocalFunctionElement element = astAdapter.getElement(target);
557 ClosureClassMap classMap = 738 ClosureClassMap classMap =
558 closureToClassMapper.getClosureToClassMapping(element.resolvedAst); 739 closureToClassMapper.getClosureToClassMapping(element.resolvedAst);
559 return classMap.callElement; 740 return classMap.callElement;
560 } 741 }
742
743 if (target is ir.FunctionExpression) {
744 return callMethodOfClosureClass();
745 }
561 if (target is ir.FunctionDeclaration) { 746 if (target is ir.FunctionDeclaration) {
562 LocalFunctionElement element = astAdapter.getElement(target); 747 return callMethodOfClosureClass();
563 ClosureClassMap classMap =
564 closureToClassMapper.getClosureToClassMapping(element.resolvedAst);
565 return classMap.callElement;
566 } 748 }
567 Element element = astAdapter.getElement(target); 749 Element element = astAdapter.getElement(target);
568 return element; 750 return element;
569 } 751 }
570 752
571 @override 753 @override
572 void visitCheckLibraryIsLoaded(ir.CheckLibraryIsLoaded checkLoad) { 754 void visitCheckLibraryIsLoaded(ir.CheckLibraryIsLoaded checkLoad) {
573 HInstruction prefixConstant = graph.addConstantString( 755 HInstruction prefixConstant = graph.addConstantString(
574 new DartString.literal(checkLoad.import.name), closedWorld); 756 new DartString.literal(checkLoad.import.name), closedWorld);
575 var prefixElement = astAdapter.getElement(checkLoad.import); 757 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) { 2195 ir.FunctionNode target, ir.Arguments arguments) {
2014 // Visit arguments in source order, then re-order and fill in defaults. 2196 // Visit arguments in source order, then re-order and fill in defaults.
2015 var values = _visitPositionalArguments(arguments); 2197 var values = _visitPositionalArguments(arguments);
2016 2198
2017 while (values.length < target.positionalParameters.length) { 2199 while (values.length < target.positionalParameters.length) {
2018 ir.VariableDeclaration parameter = 2200 ir.VariableDeclaration parameter =
2019 target.positionalParameters[values.length]; 2201 target.positionalParameters[values.length];
2020 values.add(_defaultValueForParameter(parameter)); 2202 values.add(_defaultValueForParameter(parameter));
2021 } 2203 }
2022 2204
2023 if (arguments.named.isEmpty) return values; 2205 if (arguments.named.isNotEmpty) {
2206 var namedValues = <String, HInstruction>{};
2207 for (ir.NamedExpression argument in arguments.named) {
2208 argument.value.accept(this);
2209 namedValues[argument.name] = pop();
2210 }
2024 2211
2025 var namedValues = <String, HInstruction>{}; 2212 // Visit named arguments in parameter-position order, selecting provided
2026 for (ir.NamedExpression argument in arguments.named) { 2213 // or default value.
2027 argument.value.accept(this); 2214 // TODO(sra): Ensure the stored order is canonical so we don't have to
2028 namedValues[argument.name] = pop(); 2215 // sort. The old builder uses CallStructure.makeArgumentList which depends
2216 // on the old element model.
2217 var namedParameters = target.namedParameters.toList()
2218 ..sort((ir.VariableDeclaration a, ir.VariableDeclaration b) =>
2219 a.name.compareTo(b.name));
2220 for (ir.VariableDeclaration parameter in namedParameters) {
2221 HInstruction value = namedValues[parameter.name];
2222 if (value == null) {
2223 values.add(_defaultValueForParameter(parameter));
2224 } else {
2225 values.add(value);
2226 namedValues.remove(parameter.name);
2227 }
2228 }
2229 assert(namedValues.isEmpty);
2029 } 2230 }
2030 2231
2031 // Visit named arguments in parameter-position order, selecting provided or 2232 return values;
2032 // default value. 2233 }
2033 // TODO(sra): Ensure the stored order is canonical so we don't have to 2234
2034 // sort. The old builder uses CallStructure.makeArgumentList which depends 2235 void _addTypeArguments(List<HInstruction> values, ir.Arguments arguments) {
2035 // on the old element model. 2236 // need to translate type to
2036 var namedParameters = target.namedParameters.toList() 2237 for (ir.DartType type in arguments.types) {
2037 ..sort((ir.VariableDeclaration a, ir.VariableDeclaration b) => 2238 values.add(typeBuilder.analyzeTypeArgument(
2038 a.name.compareTo(b.name)); 2239 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 } 2240 }
2048 assert(namedValues.isEmpty);
2049
2050 return values;
2051 } 2241 }
2052 2242
2053 HInstruction _defaultValueForParameter(ir.VariableDeclaration parameter) { 2243 HInstruction _defaultValueForParameter(ir.VariableDeclaration parameter) {
2054 ir.Expression initializer = parameter.initializer; 2244 ir.Expression initializer = parameter.initializer;
2055 if (initializer == null) return graph.addConstantNull(closedWorld); 2245 if (initializer == null) return graph.addConstantNull(closedWorld);
2056 // TODO(sra): Evaluate constant in ir.Node domain. 2246 // TODO(sra): Evaluate constant in ir.Node domain.
2057 ConstantValue constant = 2247 ConstantValue constant =
2058 astAdapter.getConstantForParameterDefaultValue(initializer); 2248 astAdapter.getConstantForParameterDefaultValue(initializer);
2059 if (constant == null) return graph.addConstantNull(closedWorld); 2249 if (constant == null) return graph.addConstantNull(closedWorld);
2060 return graph.addConstant(constant, closedWorld); 2250 return graph.addConstant(constant, closedWorld);
2061 } 2251 }
2062 2252
2063 @override 2253 @override
2064 void visitStaticInvocation(ir.StaticInvocation invocation) { 2254 void visitStaticInvocation(ir.StaticInvocation invocation) {
2065 ir.Procedure target = invocation.target; 2255 ir.Procedure target = invocation.target;
2066 if (astAdapter.isInForeignLibrary(target)) { 2256 if (astAdapter.isInForeignLibrary(target)) {
2067 handleInvokeStaticForeign(invocation, target); 2257 handleInvokeStaticForeign(invocation, target);
2068 return; 2258 return;
2069 } 2259 }
2070 TypeMask typeMask = astAdapter.returnTypeOf(target); 2260 TypeMask typeMask = astAdapter.returnTypeOf(target);
2071 2261
2072 // TODO(sra): For JS interop external functions, use a different function to 2262 // TODO(sra): For JS interop external functions, use a different function to
2073 // build arguments. 2263 // build arguments.
2074 List<HInstruction> arguments = 2264 List<HInstruction> arguments =
2075 _visitArgumentsForStaticTarget(target.function, invocation.arguments); 2265 _visitArgumentsForStaticTarget(target.function, invocation.arguments);
2076 2266
2267 // Factory constructors take type parameters; other static methods ignore
2268 // them.
2269 if (target.kind == ir.ProcedureKind.Factory) {
2270 if (backend.rtiNeed
2271 .classNeedsRti(astAdapter.getClass(target.enclosingClass))) {
2272 _addTypeArguments(arguments, invocation.arguments);
2273 }
2274 }
2275
2077 _pushStaticInvocation(target, arguments, typeMask); 2276 _pushStaticInvocation(target, arguments, typeMask);
2078 } 2277 }
2079 2278
2080 void handleInvokeStaticForeign( 2279 void handleInvokeStaticForeign(
2081 ir.StaticInvocation invocation, ir.Procedure target) { 2280 ir.StaticInvocation invocation, ir.Procedure target) {
2082 String name = target.name.name; 2281 String name = target.name.name;
2083 if (name == 'JS') { 2282 if (name == 'JS') {
2084 handleForeignJs(invocation); 2283 handleForeignJs(invocation);
2085 } else if (name == 'JS_CURRENT_ISOLATE_CONTEXT') { 2284 } else if (name == 'JS_CURRENT_ISOLATE_CONTEXT') {
2086 handleForeignJsCurrentIsolateContext(invocation); 2285 handleForeignJsCurrentIsolateContext(invocation);
(...skipping 692 matching lines...) Expand 10 before | Expand all | Expand 10 after
2779 _buildInvokeSuper(astAdapter.getSelector(invocation), 2978 _buildInvokeSuper(astAdapter.getSelector(invocation),
2780 _containingClass(invocation), invocation.interfaceTarget, arguments); 2979 _containingClass(invocation), invocation.interfaceTarget, arguments);
2781 } 2980 }
2782 2981
2783 @override 2982 @override
2784 void visitConstructorInvocation(ir.ConstructorInvocation invocation) { 2983 void visitConstructorInvocation(ir.ConstructorInvocation invocation) {
2785 ir.Constructor target = invocation.target; 2984 ir.Constructor target = invocation.target;
2786 // TODO(sra): For JS-interop targets, process arguments differently. 2985 // TODO(sra): For JS-interop targets, process arguments differently.
2787 List<HInstruction> arguments = 2986 List<HInstruction> arguments =
2788 _visitArgumentsForStaticTarget(target.function, invocation.arguments); 2987 _visitArgumentsForStaticTarget(target.function, invocation.arguments);
2988 if (backend.rtiNeed
2989 .classNeedsRti(astAdapter.getClass(target.enclosingClass))) {
2990 _addTypeArguments(arguments, invocation.arguments);
2991 }
2789 TypeMask typeMask = new TypeMask.nonNullExact( 2992 TypeMask typeMask = new TypeMask.nonNullExact(
2790 astAdapter.getClass(target.enclosingClass), closedWorld); 2993 astAdapter.getClass(target.enclosingClass), closedWorld);
2791 _pushStaticInvocation(target, arguments, typeMask); 2994 _pushStaticInvocation(target, arguments, typeMask);
2792 } 2995 }
2793 2996
2794 @override 2997 @override
2795 void visitIsExpression(ir.IsExpression isExpression) { 2998 void visitIsExpression(ir.IsExpression isExpression) {
2796 isExpression.operand.accept(this); 2999 isExpression.operand.accept(this);
2797 HInstruction expression = pop(); 3000 HInstruction expression = pop();
2798 pushIsTest(isExpression, isExpression.type, expression); 3001 pushIsTest(isExpression, isExpression.type, expression);
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
3218 enterBlock.setBlockFlow( 3421 enterBlock.setBlockFlow(
3219 new HTryBlockInformation( 3422 new HTryBlockInformation(
3220 kernelBuilder.wrapStatementGraph(bodyGraph), 3423 kernelBuilder.wrapStatementGraph(bodyGraph),
3221 exception, 3424 exception,
3222 kernelBuilder.wrapStatementGraph(catchGraph), 3425 kernelBuilder.wrapStatementGraph(catchGraph),
3223 kernelBuilder.wrapStatementGraph(finallyGraph)), 3426 kernelBuilder.wrapStatementGraph(finallyGraph)),
3224 exitBlock); 3427 exitBlock);
3225 kernelBuilder.inTryStatement = previouslyInTryStatement; 3428 kernelBuilder.inTryStatement = previouslyInTryStatement;
3226 } 3429 }
3227 } 3430 }
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