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

Side by Side Diff: pkg/compiler/lib/src/inferrer/inferrer_engine.dart

Issue 2955353002: Split inference type-info accessors into members, parameters and local functions (Closed)
Patch Set: Updated cf. comments Created 3 years, 5 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
OLDNEW
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import 'package:kernel/ast.dart' as ir; 5 import 'package:kernel/ast.dart' as ir;
6 6
7 import '../common.dart'; 7 import '../common.dart';
8 import '../common/names.dart'; 8 import '../common/names.dart';
9 import '../compiler.dart'; 9 import '../compiler.dart';
10 import '../constants/expressions.dart'; 10 import '../constants/expressions.dart';
(...skipping 25 matching lines...) Expand all
36 import 'type_graph_inferrer.dart'; 36 import 'type_graph_inferrer.dart';
37 import 'type_graph_nodes.dart'; 37 import 'type_graph_nodes.dart';
38 import 'type_system.dart'; 38 import 'type_system.dart';
39 39
40 /** 40 /**
41 * An inferencing engine that computes a call graph of 41 * An inferencing engine that computes a call graph of
42 * [TypeInformation] nodes by visiting the AST of the application, and 42 * [TypeInformation] nodes by visiting the AST of the application, and
43 * then does the inferencing on the graph. 43 * then does the inferencing on the graph.
44 */ 44 */
45 class InferrerEngine { 45 class InferrerEngine {
46 final Map<Element, TypeInformation> defaultTypeOfParameter = 46 final Map<ParameterElement, TypeInformation> defaultTypeOfParameter =
47 new Map<Element, TypeInformation>(); 47 new Map<ParameterElement, TypeInformation>();
48 final WorkQueue workQueue = new WorkQueue(); 48 final WorkQueue workQueue = new WorkQueue();
49 final FunctionEntity mainElement; 49 final FunctionEntity mainElement;
50 final Set<Element> analyzedElements = new Set<Element>(); 50 final Set<MemberElement> analyzedElements = new Set<MemberElement>();
51 51
52 /// The maximum number of times we allow a node in the graph to 52 /// The maximum number of times we allow a node in the graph to
53 /// change types. If a node reaches that limit, we give up 53 /// change types. If a node reaches that limit, we give up
54 /// inferencing on it and give it the dynamic type. 54 /// inferencing on it and give it the dynamic type.
55 final int MAX_CHANGE_COUNT = 6; 55 final int MAX_CHANGE_COUNT = 6;
56 56
57 int overallRefineCount = 0; 57 int overallRefineCount = 0;
58 int addedInGraph = 0; 58 int addedInGraph = 0;
59 59
60 final Compiler compiler; 60 final Compiler compiler;
61 61
62 /// The [ClosedWorld] on which inference reasoning is based. 62 /// The [ClosedWorld] on which inference reasoning is based.
63 final ClosedWorld closedWorld; 63 final ClosedWorld closedWorld;
64 64
65 final ClosedWorldRefiner closedWorldRefiner; 65 final ClosedWorldRefiner closedWorldRefiner;
66 final TypeSystem types; 66 final TypeSystem types;
67 final Map<ast.Node, TypeInformation> concreteTypes = 67 final Map<ast.Node, TypeInformation> concreteTypes =
68 new Map<ast.Node, TypeInformation>(); 68 new Map<ast.Node, TypeInformation>();
69 69
70 /// Parallel structure for concreteTypes. 70 /// Parallel structure for concreteTypes.
71 // TODO(efortuna): Remove concreteTypes and/or parameterize InferrerEngine by 71 // TODO(efortuna): Remove concreteTypes and/or parameterize InferrerEngine by
72 // ir.Node or ast.Node type. Then remove this in favor of `concreteTypes`. 72 // ir.Node or ast.Node type. Then remove this in favor of `concreteTypes`.
73 final Map<ir.Node, TypeInformation> concreteKernelTypes = 73 final Map<ir.Node, TypeInformation> concreteKernelTypes =
74 new Map<ir.Node, TypeInformation>(); 74 new Map<ir.Node, TypeInformation>();
75 final Set<Element> generativeConstructorsExposingThis = new Set<Element>(); 75 final Set<ConstructorElement> generativeConstructorsExposingThis =
76 new Set<ConstructorElement>();
76 77
77 /// Data computed internally within elements, like the type-mask of a send a 78 /// Data computed internally within elements, like the type-mask of a send a
78 /// list allocation, or a for-in loop. 79 /// list allocation, or a for-in loop.
79 final Map<Element, GlobalTypeInferenceElementData> inTreeData = 80 final Map<Element, GlobalTypeInferenceElementData> inTreeData =
80 new Map<Element, GlobalTypeInferenceElementData>(); 81 new Map<Element, GlobalTypeInferenceElementData>();
81 82
82 InferrerEngine(this.compiler, ClosedWorld closedWorld, 83 InferrerEngine(this.compiler, ClosedWorld closedWorld,
83 this.closedWorldRefiner, this.mainElement) 84 this.closedWorldRefiner, this.mainElement)
84 : this.types = new TypeSystem(closedWorld), 85 : this.types = new TypeSystem(closedWorld),
85 this.closedWorld = closedWorld; 86 this.closedWorld = closedWorld;
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 data.setMoveNextTypeMask(node, mask); 218 data.setMoveNextTypeMask(node, mask);
218 } 219 }
219 } 220 }
220 } 221 }
221 222
222 bool isNativeMember(Element element) { 223 bool isNativeMember(Element element) {
223 return element is MemberElement && 224 return element is MemberElement &&
224 closedWorld.nativeData.isNativeMember(element); 225 closedWorld.nativeData.isNativeMember(element);
225 } 226 }
226 227
227 bool checkIfExposesThis(Element element) { 228 bool checkIfExposesThis(ConstructorElement element) {
228 element = element.implementation; 229 element = element.implementation;
229 return generativeConstructorsExposingThis.contains(element); 230 return generativeConstructorsExposingThis.contains(element);
230 } 231 }
231 232
232 void recordExposesThis(Element element, bool exposesThis) { 233 void recordExposesThis(ConstructorElement element, bool exposesThis) {
233 element = element.implementation; 234 element = element.implementation;
234 if (exposesThis) { 235 if (exposesThis) {
235 generativeConstructorsExposingThis.add(element); 236 generativeConstructorsExposingThis.add(element);
236 } 237 }
237 } 238 }
238 239
239 JavaScriptBackend get backend => compiler.backend; 240 JavaScriptBackend get backend => compiler.backend;
240 OptimizerHintsForTests get optimizerHints => backend.optimizerHints; 241 OptimizerHintsForTests get optimizerHints => backend.optimizerHints;
241 DiagnosticReporter get reporter => compiler.reporter; 242 DiagnosticReporter get reporter => compiler.reporter;
242 CommonMasks get commonMasks => closedWorld.commonMasks; 243 CommonMasks get commonMasks => closedWorld.commonMasks;
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 types.allocatedClosures.forEach((dynamic info) { 353 types.allocatedClosures.forEach((dynamic info) {
353 void trace( 354 void trace(
354 Iterable<FunctionElement> elements, ClosureTracerVisitor tracer) { 355 Iterable<FunctionElement> elements, ClosureTracerVisitor tracer) {
355 tracer.run(); 356 tracer.run();
356 if (!tracer.continueAnalyzing) { 357 if (!tracer.continueAnalyzing) {
357 elements.forEach((FunctionElement e) { 358 elements.forEach((FunctionElement e) {
358 closedWorldRefiner.registerMightBePassedToApply(e); 359 closedWorldRefiner.registerMightBePassedToApply(e);
359 if (debug.VERBOSE) print("traced closure $e as ${true} (bail)"); 360 if (debug.VERBOSE) print("traced closure $e as ${true} (bail)");
360 e.functionSignature.forEachParameter((parameter) { 361 e.functionSignature.forEachParameter((parameter) {
361 types 362 types
362 .getInferredTypeOf(parameter) 363 .getInferredTypeOfParameter(parameter)
363 .giveUp(this, clearAssignments: false); 364 .giveUp(this, clearAssignments: false);
364 }); 365 });
365 }); 366 });
366 bailedOutOn.addAll(elements); 367 bailedOutOn.addAll(elements);
367 return; 368 return;
368 } 369 }
369 elements 370 elements
370 .where((e) => !bailedOutOn.contains(e)) 371 .where((e) => !bailedOutOn.contains(e))
371 .forEach((FunctionElement e) { 372 .forEach((FunctionElement e) {
372 e.functionSignature.forEachParameter((parameter) { 373 e.functionSignature.forEachParameter((parameter) {
373 var info = types.getInferredTypeOf(parameter); 374 var info = types.getInferredTypeOfParameter(parameter);
374 info.maybeResume(); 375 info.maybeResume();
375 workQueue.add(info); 376 workQueue.add(info);
376 }); 377 });
377 if (tracer.tracedType.mightBePassedToFunctionApply) { 378 if (tracer.tracedType.mightBePassedToFunctionApply) {
378 closedWorldRefiner.registerMightBePassedToApply(e); 379 closedWorldRefiner.registerMightBePassedToApply(e);
379 } 380 }
380 if (debug.VERBOSE) { 381 if (debug.VERBOSE) {
381 print("traced closure $e as " 382 print("traced closure $e as "
382 "${closedWorldRefiner 383 "${closedWorldRefiner
383 .getCurrentlyKnownMightBePassedToApply(e)}"); 384 .getCurrentlyKnownMightBePassedToApply(e)}");
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 print('${types.getInferredSignatureOf(info.element)} for ' 454 print('${types.getInferredSignatureOf(info.element)} for '
454 '${info.element}'); 455 '${info.element}');
455 } else if (info is ClosureTypeInformation) { 456 } else if (info is ClosureTypeInformation) {
456 print('${types.getInferredSignatureOf(info.element)} for ' 457 print('${types.getInferredSignatureOf(info.element)} for '
457 '${info.element}'); 458 '${info.element}');
458 } else if (info is DynamicCallSiteTypeInformation) { 459 } else if (info is DynamicCallSiteTypeInformation) {
459 for (MemberElement target in info.targets) { 460 for (MemberElement target in info.targets) {
460 if (target is MethodElement) { 461 if (target is MethodElement) {
461 print('${types.getInferredSignatureOf(target)} for ${target}'); 462 print('${types.getInferredSignatureOf(target)} for ${target}');
462 } else { 463 } else {
463 print('${types.getInferredTypeOf(target).type} for ${target}'); 464 print(
465 '${types.getInferredTypeOfMember(target).type} for ${target}') ;
464 } 466 }
465 } 467 }
466 } else if (info is StaticCallSiteTypeInformation) { 468 } else if (info is StaticCallSiteTypeInformation) {
467 ClassElement cls = info.calledElement.enclosingClass; 469 ClassElement cls = info.calledElement.enclosingClass;
468 FunctionElement callMethod = cls.lookupMember(Identifiers.call); 470 FunctionElement callMethod = cls.lookupMember(Identifiers.call);
469 print('${types.getInferredSignatureOf(callMethod)} for ${cls}'); 471 print('${types.getInferredSignatureOf(callMethod)} for ${cls}');
470 } else { 472 } else {
471 print('${info.type} for some unknown kind of closure'); 473 print('${info.type} for some unknown kind of closure');
472 } 474 }
473 }); 475 });
474 analyzedElements.forEach((Element elem) { 476 analyzedElements.forEach((MemberElement elem) {
475 TypeInformation type = types.getInferredTypeOf(elem); 477 TypeInformation type = types.getInferredTypeOfMember(elem);
476 print('${elem} :: ${type} from ${type.assignments} '); 478 print('${elem} :: ${type} from ${type.assignments} ');
477 }); 479 });
478 } 480 }
479 dump?.afterAnalysis(); 481 dump?.afterAnalysis();
480 482
481 reporter.log('Inferred $overallRefineCount types.'); 483 reporter.log('Inferred $overallRefineCount types.');
482 484
483 processLoopInformation(); 485 processLoopInformation();
484 } 486 }
485 487
486 void analyze(ResolvedAst resolvedAst, ArgumentsTypes arguments) { 488 void analyze(ResolvedAst resolvedAst, ArgumentsTypes arguments) {
487 AstElement element = resolvedAst.element.implementation; 489 MemberElement element = resolvedAst.element.implementation;
488 if (analyzedElements.contains(element)) return; 490 if (analyzedElements.contains(element)) return;
489 analyzedElements.add(element); 491 analyzedElements.add(element);
490 492
491 dynamic visitor = compiler.options.kernelGlobalInference 493 dynamic visitor = compiler.options.kernelGlobalInference
492 ? new KernelTypeGraphBuilder(element, resolvedAst, compiler, this) 494 ? new KernelTypeGraphBuilder(element, resolvedAst, compiler, this)
493 : new ElementGraphBuilder(element, resolvedAst, compiler, this); 495 : new ElementGraphBuilder(element, resolvedAst, compiler, this);
494 TypeInformation type; 496 TypeInformation type;
495 reporter.withCurrentElement(element, () { 497 reporter.withCurrentElement(element, () {
496 // ignore: UNDEFINED_METHOD 498 // ignore: UNDEFINED_METHOD
497 type = visitor.run(); 499 type = visitor.run();
498 }); 500 });
499 addedInGraph++; 501 addedInGraph++;
500 502
501 if (element.isField) { 503 if (element.isField) {
502 VariableElement fieldElement = element; 504 FieldElement fieldElement = element;
503 ast.Node node = resolvedAst.node; 505 ast.Node node = resolvedAst.node;
504 ast.Node initializer = resolvedAst.body; 506 ast.Node initializer = resolvedAst.body;
505 if (element.isFinal || element.isConst) { 507 if (element.isFinal || element.isConst) {
506 // If [element] is final and has an initializer, we record 508 // If [element] is final and has an initializer, we record
507 // the inferred type. 509 // the inferred type.
508 if (resolvedAst.body != null) { 510 if (resolvedAst.body != null) {
509 if (type is! ListTypeInformation && type is! MapTypeInformation) { 511 if (type is! ListTypeInformation && type is! MapTypeInformation) {
510 // For non-container types, the constant handler does 512 // For non-container types, the constant handler does
511 // constant folding that could give more precise results. 513 // constant folding that could give more precise results.
512 ConstantExpression constant = fieldElement.constant; 514 ConstantExpression constant = fieldElement.constant;
(...skipping 19 matching lines...) Expand all
532 fieldElement.isInstanceMember || 534 fieldElement.isInstanceMember ||
533 constant.isImplicit || 535 constant.isImplicit ||
534 constant.isPotential, 536 constant.isPotential,
535 failedAt( 537 failedAt(
536 fieldElement, 538 fieldElement,
537 "Constant expression without value: " 539 "Constant expression without value: "
538 "${constant.toStructuredText()}.")); 540 "${constant.toStructuredText()}."));
539 } 541 }
540 } 542 }
541 } 543 }
542 recordType(element, type); 544 recordTypeOfField(element, type);
543 } else if (!element.isInstanceMember) { 545 } else if (!element.isInstanceMember) {
544 recordType(element, types.nullType); 546 recordTypeOfField(element, types.nullType);
545 } 547 }
546 } else if (initializer == null) { 548 } else if (initializer == null) {
547 // Only update types of static fields if there is no 549 // Only update types of static fields if there is no
548 // assignment. Instance fields are dealt with in the constructor. 550 // assignment. Instance fields are dealt with in the constructor.
549 if (Elements.isStaticOrTopLevelField(element)) { 551 if (Elements.isStaticOrTopLevelField(element)) {
550 recordTypeOfNonFinalField(node, element, type); 552 recordTypeOfNonFinalField(element, type);
551 } 553 }
552 } else { 554 } else {
553 recordTypeOfNonFinalField(node, element, type); 555 recordTypeOfNonFinalField(element, type);
554 } 556 }
555 if (Elements.isStaticOrTopLevelField(element) && 557 if (Elements.isStaticOrTopLevelField(element) &&
556 resolvedAst.body != null && 558 resolvedAst.body != null &&
557 !element.isConst) { 559 !element.isConst) {
558 dynamic argument = resolvedAst.body; 560 dynamic argument = resolvedAst.body;
559 // TODO(13429): We could do better here by using the 561 // TODO(13429): We could do better here by using the
560 // constant handler to figure out if it's a lazy field or not. 562 // constant handler to figure out if it's a lazy field or not.
561 if (argument.asSend() != null || 563 if (argument.asSend() != null ||
562 (argument.asNewExpression() != null && !argument.isConst)) { 564 (argument.asNewExpression() != null && !argument.isConst)) {
563 recordType(element, types.nullType); 565 recordTypeOfField(element, types.nullType);
564 } 566 }
565 } 567 }
566 } else { 568 } else {
567 recordReturnType(element, type); 569 recordReturnType(element, type);
568 } 570 }
569 } 571 }
570 572
571 void processLoopInformation() { 573 void processLoopInformation() {
572 types.allocatedCalls.forEach((dynamic info) { 574 types.allocatedCalls.forEach((dynamic info) {
573 if (!info.inLoop) return; 575 if (!info.inLoop) return;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 * Update the assignments to parameters in the graph. [remove] tells 630 * Update the assignments to parameters in the graph. [remove] tells
629 * wheter assignments must be added or removed. If [init] is false, 631 * wheter assignments must be added or removed. If [init] is false,
630 * parameters are added to the work queue. 632 * parameters are added to the work queue.
631 */ 633 */
632 void updateParameterAssignments(TypeInformation caller, Element callee, 634 void updateParameterAssignments(TypeInformation caller, Element callee,
633 ArgumentsTypes arguments, Selector selector, TypeMask mask, 635 ArgumentsTypes arguments, Selector selector, TypeMask mask,
634 {bool remove, bool addToQueue: true}) { 636 {bool remove, bool addToQueue: true}) {
635 if (callee.name == Identifiers.noSuchMethod_) return; 637 if (callee.name == Identifiers.noSuchMethod_) return;
636 if (callee.isField) { 638 if (callee.isField) {
637 if (selector.isSetter) { 639 if (selector.isSetter) {
638 ElementTypeInformation info = types.getInferredTypeOf(callee); 640 ElementTypeInformation info = types.getInferredTypeOfMember(callee);
639 if (remove) { 641 if (remove) {
640 info.removeAssignment(arguments.positional[0]); 642 info.removeAssignment(arguments.positional[0]);
641 } else { 643 } else {
642 info.addAssignment(arguments.positional[0]); 644 info.addAssignment(arguments.positional[0]);
643 } 645 }
644 if (addToQueue) workQueue.add(info); 646 if (addToQueue) workQueue.add(info);
645 } 647 }
646 } else if (callee.isGetter) { 648 } else if (callee.isGetter) {
647 return; 649 return;
648 } else if (selector != null && selector.isGetter) { 650 } else if (selector != null && selector.isGetter) {
649 // We are tearing a function off and thus create a closure. 651 // We are tearing a function off and thus create a closure.
650 assert(callee.isFunction); 652 assert(callee.isFunction);
651 MemberTypeInformation info = types.getInferredTypeOf(callee); 653 MemberTypeInformation info = types.getInferredTypeOfMember(callee);
652 if (remove) { 654 if (remove) {
653 info.closurizedCount--; 655 info.closurizedCount--;
654 } else { 656 } else {
655 info.closurizedCount++; 657 info.closurizedCount++;
656 if (Elements.isStaticOrTopLevel(callee)) { 658 if (Elements.isStaticOrTopLevel(callee)) {
657 types.allocatedClosures.add(info); 659 types.allocatedClosures.add(info);
658 } else { 660 } else {
659 // We add the call-site type information here so that we 661 // We add the call-site type information here so that we
660 // can benefit from further refinement of the selector. 662 // can benefit from further refinement of the selector.
661 types.allocatedClosures.add(caller); 663 types.allocatedClosures.add(caller);
662 } 664 }
663 FunctionElement function = callee.implementation; 665 FunctionElement function = callee.implementation;
664 FunctionSignature signature = function.functionSignature; 666 FunctionSignature signature = function.functionSignature;
665 signature.forEachParameter((Element parameter) { 667 signature.forEachParameter((Element parameter) {
666 ParameterTypeInformation info = types.getInferredTypeOf(parameter); 668 ParameterTypeInformation info =
669 types.getInferredTypeOfParameter(parameter);
667 info.tagAsTearOffClosureParameter(this); 670 info.tagAsTearOffClosureParameter(this);
668 if (addToQueue) workQueue.add(info); 671 if (addToQueue) workQueue.add(info);
669 }); 672 });
670 } 673 }
671 } else { 674 } else {
672 FunctionElement function = callee.implementation; 675 FunctionElement function = callee.implementation;
673 FunctionSignature signature = function.functionSignature; 676 FunctionSignature signature = function.functionSignature;
674 int parameterIndex = 0; 677 int parameterIndex = 0;
675 bool visitingRequiredParameter = true; 678 bool visitingRequiredParameter = true;
676 signature.forEachParameter((Element parameter) { 679 signature.forEachParameter((Element parameter) {
677 if (signature.hasOptionalParameters && 680 if (signature.hasOptionalParameters &&
678 parameter == signature.optionalParameters.first) { 681 parameter == signature.optionalParameters.first) {
679 visitingRequiredParameter = false; 682 visitingRequiredParameter = false;
680 } 683 }
681 TypeInformation type = visitingRequiredParameter 684 TypeInformation type = visitingRequiredParameter
682 ? arguments.positional[parameterIndex] 685 ? arguments.positional[parameterIndex]
683 : signature.optionalParametersAreNamed 686 : signature.optionalParametersAreNamed
684 ? arguments.named[parameter.name] 687 ? arguments.named[parameter.name]
685 : parameterIndex < arguments.positional.length 688 : parameterIndex < arguments.positional.length
686 ? arguments.positional[parameterIndex] 689 ? arguments.positional[parameterIndex]
687 : null; 690 : null;
688 if (type == null) type = getDefaultTypeOfParameter(parameter); 691 if (type == null) type = getDefaultTypeOfParameter(parameter);
689 TypeInformation info = types.getInferredTypeOf(parameter); 692 TypeInformation info = types.getInferredTypeOfParameter(parameter);
690 if (remove) { 693 if (remove) {
691 info.removeAssignment(type); 694 info.removeAssignment(type);
692 } else { 695 } else {
693 info.addAssignment(type); 696 info.addAssignment(type);
694 } 697 }
695 parameterIndex++; 698 parameterIndex++;
696 if (addToQueue) workQueue.add(info); 699 if (addToQueue) workQueue.add(info);
697 }); 700 });
698 } 701 }
699 } 702 }
700 703
701 /** 704 /**
702 * Sets the type of a parameter's default value to [type]. If the global 705 * Sets the type of a parameter's default value to [type]. If the global
703 * mapping in [defaultTypeOfParameter] already contains a type, it must be 706 * mapping in [defaultTypeOfParameter] already contains a type, it must be
704 * a [PlaceholderTypeInformation], which will be replaced. All its uses are 707 * a [PlaceholderTypeInformation], which will be replaced. All its uses are
705 * updated. 708 * updated.
706 */ 709 */
707 void setDefaultTypeOfParameter( 710 void setDefaultTypeOfParameter(
708 ParameterElement parameter, TypeInformation type) { 711 ParameterElement parameter, TypeInformation type) {
709 assert(parameter.functionDeclaration.isImplementation); 712 assert(parameter.functionDeclaration.isImplementation);
710 TypeInformation existing = defaultTypeOfParameter[parameter]; 713 TypeInformation existing = defaultTypeOfParameter[parameter];
711 defaultTypeOfParameter[parameter] = type; 714 defaultTypeOfParameter[parameter] = type;
712 TypeInformation info = types.getInferredTypeOf(parameter); 715 TypeInformation info = types.getInferredTypeOfParameter(parameter);
713 if (existing != null && existing is PlaceholderTypeInformation) { 716 if (existing != null && existing is PlaceholderTypeInformation) {
714 // Replace references to [existing] to use [type] instead. 717 // Replace references to [existing] to use [type] instead.
715 if (parameter.functionDeclaration.isInstanceMember) { 718 if (parameter.functionDeclaration.isInstanceMember) {
716 ParameterAssignments assignments = info.assignments; 719 ParameterAssignments assignments = info.assignments;
717 assignments.replace(existing, type); 720 assignments.replace(existing, type);
718 } else { 721 } else {
719 List<TypeInformation> assignments = info.assignments; 722 List<TypeInformation> assignments = info.assignments;
720 for (int i = 0; i < assignments.length; i++) { 723 for (int i = 0; i < assignments.length; i++) {
721 if (assignments[i] == existing) { 724 if (assignments[i] == existing) {
722 assignments[i] = type; 725 assignments[i] = type;
(...skipping 10 matching lines...) Expand all
733 /** 736 /**
734 * Returns the [TypeInformation] node for the default value of a parameter. 737 * Returns the [TypeInformation] node for the default value of a parameter.
735 * If this is queried before it is set by [setDefaultTypeOfParameter], a 738 * If this is queried before it is set by [setDefaultTypeOfParameter], a
736 * [PlaceholderTypeInformation] is returned, which will later be replaced 739 * [PlaceholderTypeInformation] is returned, which will later be replaced
737 * by the actual node when [setDefaultTypeOfParameter] is called. 740 * by the actual node when [setDefaultTypeOfParameter] is called.
738 * 741 *
739 * Invariant: After graph construction, no [PlaceholderTypeInformation] nodes 742 * Invariant: After graph construction, no [PlaceholderTypeInformation] nodes
740 * should be present and a default type for each parameter should 743 * should be present and a default type for each parameter should
741 * exist. 744 * exist.
742 */ 745 */
743 TypeInformation getDefaultTypeOfParameter(Element parameter) { 746 TypeInformation getDefaultTypeOfParameter(ParameterElement parameter) {
744 return defaultTypeOfParameter.putIfAbsent(parameter, () { 747 return defaultTypeOfParameter.putIfAbsent(parameter, () {
745 return new PlaceholderTypeInformation(types.currentMember); 748 return new PlaceholderTypeInformation(types.currentMember);
746 }); 749 });
747 } 750 }
748 751
749 /** 752 /**
750 * This helper breaks abstractions but is currently required to work around 753 * This helper breaks abstractions but is currently required to work around
751 * the wrong modeling of default values of optional parameters of 754 * the wrong modeling of default values of optional parameters of
752 * synthetic constructors. 755 * synthetic constructors.
753 * 756 *
754 * TODO(johnniwinther): Remove once default values of synthetic parameters 757 * TODO(johnniwinther): Remove once default values of synthetic parameters
755 * are fixed. 758 * are fixed.
756 */ 759 */
757 bool hasAlreadyComputedTypeOfParameterDefault(Element parameter) { 760 bool hasAlreadyComputedTypeOfParameterDefault(ParameterElement parameter) {
758 TypeInformation seen = defaultTypeOfParameter[parameter]; 761 TypeInformation seen = defaultTypeOfParameter[parameter];
759 return (seen != null && seen is! PlaceholderTypeInformation); 762 return (seen != null && seen is! PlaceholderTypeInformation);
760 } 763 }
761 764
762 /** 765 /**
763 * Returns the type of [element]. 766 * Returns the type of [element].
764 */ 767 */
765 TypeInformation typeOfElement(Entity element) { 768 TypeInformation typeOfParameter(ParameterElement element) {
766 if (element is FunctionElement) return types.functionType; 769 return types.getInferredTypeOfParameter(element);
767 return types.getInferredTypeOf(element); 770 }
771
772 /**
773 * Returns the type of [element].
774 */
775 TypeInformation typeOfMember(MemberElement element) {
776 if (element is MethodElement) return types.functionType;
777 return types.getInferredTypeOfMember(element);
768 } 778 }
769 779
770 /** 780 /**
771 * Returns the return type of [element]. 781 * Returns the return type of [element].
772 */ 782 */
773 TypeInformation returnTypeOfElement(Entity element) { 783 @deprecated
774 if (element is! FunctionElement) return types.dynamicType; 784 TypeInformation returnTypeOfLocalFunction(LocalFunctionElement element) {
775 return types.getInferredTypeOf(element); 785 return types.getInferredTypeOfLocalFunction(element);
776 } 786 }
777 787
778 /** 788 /**
789 * Returns the return type of [element].
790 */
791 TypeInformation returnTypeOfMember(MemberElement element) {
792 if (element is! MethodElement) return types.dynamicType;
793 return types.getInferredTypeOfMember(element);
794 }
795
796 /**
779 * Records that [node] sets final field [element] to be of type [type]. 797 * Records that [node] sets final field [element] to be of type [type].
780 * 798 *
781 * [nodeHolder] is the element holder of [node]. 799 * [nodeHolder] is the element holder of [node].
782 */ 800 */
783 void recordTypeOfFinalField( 801 void recordTypeOfFinalField(FieldElement element, TypeInformation type) {
784 Spannable node, Entity analyzed, Entity element, TypeInformation type) { 802 types.getInferredTypeOfMember(element).addAssignment(type);
785 types.getInferredTypeOf(element).addAssignment(type);
786 } 803 }
787 804
788 /** 805 /**
789 * Records that [node] sets non-final field [element] to be of type 806 * Records that [node] sets non-final field [element] to be of type
790 * [type]. 807 * [type].
791 */ 808 */
792 void recordTypeOfNonFinalField( 809 void recordTypeOfNonFinalField(FieldElement element, TypeInformation type) {
793 Spannable node, Entity element, TypeInformation type) { 810 types.getInferredTypeOfMember(element).addAssignment(type);
794 types.getInferredTypeOf(element).addAssignment(type);
795 } 811 }
796 812
797 /** 813 /**
798 * Records that [element] is of type [type]. 814 * Records that [element] is of type [type].
799 */ 815 */
800 void recordType(Entity element, TypeInformation type) { 816 // TODO(johnniwinther): Merge [recordTypeOfFinalField] and
801 types.getInferredTypeOf(element).addAssignment(type); 817 // [recordTypeOfNonFinalField] with this?
818 void recordTypeOfField(FieldElement element, TypeInformation type) {
819 types.getInferredTypeOfMember(element).addAssignment(type);
802 } 820 }
803 821
804 /** 822 /**
805 * Records that the return type [element] is of type [type]. 823 * Records that the return type [element] is of type [type].
806 */ 824 */
807 void recordReturnType(Element element, TypeInformation type) { 825 @deprecated
808 TypeInformation info = types.getInferredTypeOf(element); 826 void recordReturnTypeOfLocalFunction(
827 LocalFunctionElement element, TypeInformation type) {
828 TypeInformation info = types.getInferredTypeOfLocalFunction(element);
809 if (element.name == '==') { 829 if (element.name == '==') {
810 // Even if x.== doesn't return a bool, 'x == null' evaluates to 'false'. 830 // Even if x.== doesn't return a bool, 'x == null' evaluates to 'false'.
811 info.addAssignment(types.boolType); 831 info.addAssignment(types.boolType);
832 }
833 // TODO(ngeoffray): Clean up. We do these checks because
834 // [SimpleTypesInferrer] deals with two different inferrers.
835 if (type == null) return;
836 if (info.assignments.isEmpty) info.addAssignment(type);
837 }
838
839 /**
840 * Records that the return type [element] is of type [type].
841 */
842 void recordReturnType(MethodElement element, TypeInformation type) {
843 TypeInformation info = types.getInferredTypeOfMember(element);
844 if (element.name == '==') {
845 // Even if x.== doesn't return a bool, 'x == null' evaluates to 'false'.
846 info.addAssignment(types.boolType);
812 } 847 }
813 // TODO(ngeoffray): Clean up. We do these checks because 848 // TODO(ngeoffray): Clean up. We do these checks because
814 // [SimpleTypesInferrer] deals with two different inferrers. 849 // [SimpleTypesInferrer] deals with two different inferrers.
815 if (type == null) return; 850 if (type == null) return;
816 if (info.assignments.isEmpty) info.addAssignment(type); 851 if (info.assignments.isEmpty) info.addAssignment(type);
817 } 852 }
818 853
819 /** 854 /**
820 * Notifies to the inferrer that [analyzedElement] can have return 855 * Notifies to the inferrer that [analyzedElement] can have return
821 * type [newType]. [currentType] is the type the [ElementGraphBuilder] 856 * type [newType]. [currentType] is the type the [ElementGraphBuilder]
822 * currently found. 857 * currently found.
823 * 858 *
824 * Returns the new type for [analyzedElement]. 859 * Returns the new type for [analyzedElement].
825 */ 860 */
826 TypeInformation addReturnTypeFor( 861 @deprecated
827 Element element, TypeInformation unused, TypeInformation newType) { 862 TypeInformation addReturnTypeForLocalFunction(LocalFunctionElement element,
828 TypeInformation type = types.getInferredTypeOf(element); 863 TypeInformation unused, TypeInformation newType) {
864 TypeInformation type = types.getInferredTypeOfLocalFunction(element);
829 // TODO(ngeoffray): Clean up. We do this check because 865 // TODO(ngeoffray): Clean up. We do this check because
830 // [SimpleTypesInferrer] deals with two different inferrers. 866 // [SimpleTypesInferrer] deals with two different inferrers.
831 if (element.isGenerativeConstructor) return type; 867 if (element.isGenerativeConstructor) return type;
868 type.addAssignment(newType);
869 return type;
870 }
871
872 /**
873 * Notifies to the inferrer that [analyzedElement] can have return
874 * type [newType]. [currentType] is the type the [ElementGraphBuilder]
875 * currently found.
876 *
877 * Returns the new type for [analyzedElement].
878 */
879 TypeInformation addReturnTypeForMethod(
880 MethodElement element, TypeInformation unused, TypeInformation newType) {
881 TypeInformation type = types.getInferredTypeOfMember(element);
882 // TODO(ngeoffray): Clean up. We do this check because
883 // [SimpleTypesInferrer] deals with two different inferrers.
884 if (element.isGenerativeConstructor) return type;
832 type.addAssignment(newType); 885 type.addAssignment(newType);
833 return type; 886 return type;
834 } 887 }
835 888
836 /** 889 /**
837 * Registers that [caller] calls [callee] at location [node], with 890 * Registers that [caller] calls [callee] at location [node], with
838 * [selector], and [arguments]. Note that [selector] is null for 891 * [selector], and [arguments]. Note that [selector] is null for
839 * forwarding constructors. 892 * forwarding constructors.
840 * 893 *
841 * [sideEffects] will be updated to incorporate [callee]'s side 894 * [sideEffects] will be updated to incorporate [callee]'s side
842 * effects. 895 * effects.
843 * 896 *
844 * [inLoop] tells whether the call happens in a loop. 897 * [inLoop] tells whether the call happens in a loop.
845 */ 898 */
846 TypeInformation registerCalledElement( 899 @deprecated
900 TypeInformation registerCalledLocalFunction(
847 Spannable node, 901 Spannable node,
848 Selector selector, 902 Selector selector,
849 TypeMask mask, 903 TypeMask mask,
904 Element caller,
905 LocalFunctionElement callee,
906 ArgumentsTypes arguments,
907 SideEffects sideEffects,
908 bool inLoop) {
909 return _registerCalledElement(
910 node, selector, mask, caller, callee, arguments, sideEffects, inLoop);
911 }
912
913 /**
914 * Registers that [caller] calls [callee] at location [node], with
915 * [selector], and [arguments]. Note that [selector] is null for
916 * forwarding constructors.
917 *
918 * [sideEffects] will be updated to incorporate [callee]'s side
919 * effects.
920 *
921 * [inLoop] tells whether the call happens in a loop.
922 */
923 TypeInformation registerCalledMember(
924 Spannable node,
925 Selector selector,
926 TypeMask mask,
927 Element caller,
928 MemberElement callee,
929 ArgumentsTypes arguments,
930 SideEffects sideEffects,
931 bool inLoop) {
932 return _registerCalledElement(
933 node, selector, mask, caller, callee, arguments, sideEffects, inLoop);
934 }
935
936 /**
937 * Registers that [caller] calls [callee] at location [node], with
938 * [selector], and [arguments]. Note that [selector] is null for
939 * forwarding constructors.
940 *
941 * [sideEffects] will be updated to incorporate [callee]'s side
942 * effects.
943 *
944 * [inLoop] tells whether the call happens in a loop.
945 */
946 TypeInformation _registerCalledElement(
947 Spannable node,
948 Selector selector,
949 TypeMask mask,
850 Element caller, 950 Element caller,
851 Element callee, 951 Element callee,
852 ArgumentsTypes arguments, 952 ArgumentsTypes arguments,
853 SideEffects sideEffects, 953 SideEffects sideEffects,
854 bool inLoop) { 954 bool inLoop) {
855 CallSiteTypeInformation info = new StaticCallSiteTypeInformation( 955 CallSiteTypeInformation info = new StaticCallSiteTypeInformation(
856 types.currentMember, 956 types.currentMember,
857 node, 957 node,
858 caller, 958 caller,
859 callee, 959 callee,
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
1036 types.allocatedClosures.forEach(cleanup); 1136 types.allocatedClosures.forEach(cleanup);
1037 types.allocatedClosures.clear(); 1137 types.allocatedClosures.clear();
1038 1138
1039 analyzedElements.clear(); 1139 analyzedElements.clear();
1040 generativeConstructorsExposingThis.clear(); 1140 generativeConstructorsExposingThis.clear();
1041 1141
1042 types.allocatedMaps.values.forEach(cleanup); 1142 types.allocatedMaps.values.forEach(cleanup);
1043 types.allocatedLists.values.forEach(cleanup); 1143 types.allocatedLists.values.forEach(cleanup);
1044 } 1144 }
1045 1145
1046 Iterable<Element> getCallersOf(Element element) { 1146 Iterable<Element> getCallersOf(MemberElement element) {
1047 if (compiler.disableTypeInference) { 1147 if (compiler.disableTypeInference) {
1048 throw new UnsupportedError( 1148 throw new UnsupportedError(
1049 "Cannot query the type inferrer when type inference is disabled."); 1149 "Cannot query the type inferrer when type inference is disabled.");
1050 } 1150 }
1051 MemberTypeInformation info = types.getInferredTypeOf(element); 1151 MemberTypeInformation info = types.getInferredTypeOfMember(element);
1052 return info.callers; 1152 return info.callers;
1053 } 1153 }
1054 1154
1055 /** 1155 /**
1056 * Returns the type of [element] when being called with [selector]. 1156 * Returns the type of [element] when being called with [selector].
1057 */ 1157 */
1058 TypeInformation typeOfElementWithSelector( 1158 TypeInformation typeOfLocalFunctionWithSelector(
1159 LocalFunctionElement element, Selector selector) {
1160 return _typeOfElementWithSelector(element, selector);
1161 }
1162
1163 /**
1164 * Returns the type of [element] when being called with [selector].
1165 */
1166 TypeInformation typeOfMemberWithSelector(
1167 MemberElement element, Selector selector) {
1168 return _typeOfElementWithSelector(element, selector);
1169 }
1170
1171 /**
1172 * Returns the type of [element] when being called with [selector].
1173 */
1174 TypeInformation _typeOfElementWithSelector(
1059 Element element, Selector selector) { 1175 Element element, Selector selector) {
1060 if (element.name == Identifiers.noSuchMethod_ && 1176 if (element.name == Identifiers.noSuchMethod_ &&
1061 selector.name != element.name) { 1177 selector.name != element.name) {
1062 // An invocation can resolve to a [noSuchMethod], in which case 1178 // An invocation can resolve to a [noSuchMethod], in which case
1063 // we get the return type of [noSuchMethod]. 1179 // we get the return type of [noSuchMethod].
1064 return returnTypeOfElement(element); 1180 if (element.isLocal) {
1181 return returnTypeOfLocalFunction(element);
1182 } else {
1183 return returnTypeOfMember(element);
1184 }
1065 } else if (selector.isGetter) { 1185 } else if (selector.isGetter) {
1066 if (element.isFunction) { 1186 if (element.isFunction) {
1067 // [functionType] is null if the inferrer did not run. 1187 // [functionType] is null if the inferrer did not run.
1068 return types.functionType == null 1188 return types.functionType == null
1069 ? types.dynamicType 1189 ? types.dynamicType
1070 : types.functionType; 1190 : types.functionType;
1071 } else if (element.isField) { 1191 } else if (element.isField) {
1072 return typeOfElement(element); 1192 return typeOfMember(element);
1073 } else if (Elements.isUnresolved(element)) { 1193 } else if (Elements.isUnresolved(element)) {
1074 return types.dynamicType; 1194 return types.dynamicType;
1075 } else { 1195 } else {
1076 assert(element.isGetter); 1196 assert(element.isGetter);
1077 return returnTypeOfElement(element); 1197 if (element.isLocal) {
1198 return returnTypeOfLocalFunction(element);
1199 } else {
1200 return returnTypeOfMember(element);
1201 }
1078 } 1202 }
1079 } else if (element.isGetter || element.isField) { 1203 } else if (element.isGetter || element.isField) {
1080 assert(selector.isCall || selector.isSetter); 1204 assert(selector.isCall || selector.isSetter);
1081 return types.dynamicType; 1205 return types.dynamicType;
1082 } else { 1206 } else {
1083 return returnTypeOfElement(element); 1207 if (element.isLocal) {
1208 return returnTypeOfLocalFunction(element);
1209 } else {
1210 return returnTypeOfMember(element);
1211 }
1084 } 1212 }
1085 } 1213 }
1086 1214
1087 /** 1215 /**
1088 * Records that the captured variable [local] is read. 1216 * Records that the captured variable [local] is read.
1089 */ 1217 */
1090 void recordCapturedLocalRead(Local local) {} 1218 void recordCapturedLocalRead(Local local) {}
1091 1219
1092 /** 1220 /**
1093 * Records that the variable [local] is being updated. 1221 * Records that the variable [local] is being updated.
1094 */ 1222 */
1095 void recordLocalUpdate(Local local, TypeInformation type) {} 1223 void recordLocalUpdate(Local local, TypeInformation type) {}
1096 } 1224 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/inferrer/closure_tracer.dart ('k') | pkg/compiler/lib/src/inferrer/locals_handler.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698