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

Side by Side Diff: pkg/compiler/lib/src/universe/world_builder.dart

Issue 2543753004: Move processing of instance members from ResolutionEnqueuer to ResolutionWorldBuilderImpl (Closed)
Patch Set: Created 4 years 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 library universe; 5 library universe;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 8
9 import '../cache_strategy.dart'; 9 import '../cache_strategy.dart';
10 import '../common.dart'; 10 import '../common.dart';
11 import '../common/backend_api.dart' show Backend; 11 import '../common/backend_api.dart' show Backend;
12 import '../common/resolution.dart' show Resolution; 12 import '../common/resolution.dart' show Resolution;
13 import '../compiler.dart' show Compiler; 13 import '../compiler.dart' show Compiler;
14 import '../core_types.dart' show CoreClasses; 14 import '../core_types.dart' show CoreClasses;
15 import '../dart_types.dart'; 15 import '../dart_types.dart';
16 import '../elements/elements.dart'; 16 import '../elements/elements.dart';
17 import '../elements/entities.dart';
17 import '../universe/class_set.dart' show Instantiation; 18 import '../universe/class_set.dart' show Instantiation;
19 import '../util/enumset.dart';
18 import '../util/util.dart'; 20 import '../util/util.dart';
19 import '../world.dart' show World, ClosedWorld, OpenWorld, WorldImpl; 21 import '../world.dart' show World, ClosedWorld, OpenWorld, WorldImpl;
20 import 'selector.dart' show Selector; 22 import 'selector.dart' show Selector;
21 import 'use.dart' show DynamicUse, DynamicUseKind, StaticUse, StaticUseKind; 23 import 'use.dart' show DynamicUse, DynamicUseKind, StaticUse, StaticUseKind;
22 24
23 /// The known constraint on receiver for a dynamic call site. 25 /// The known constraint on receiver for a dynamic call site.
24 /// 26 ///
25 /// This can for instance be used to constrain this dynamic call to `foo` to 27 /// This can for instance be used to constrain this dynamic call to `foo` to
26 /// 'receivers of the exact instance `Bar`': 28 /// 'receivers of the exact instance `Bar`':
27 /// 29 ///
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 Iterable<DartType> get isChecks; 124 Iterable<DartType> get isChecks;
123 125
124 /// Registers that [type] is checked in this universe. The unaliased type is 126 /// Registers that [type] is checked in this universe. The unaliased type is
125 /// returned. 127 /// returned.
126 DartType registerIsCheck(DartType type, Resolution resolution); 128 DartType registerIsCheck(DartType type, Resolution resolution);
127 129
128 /// All directly instantiated types, that is, the types of the directly 130 /// All directly instantiated types, that is, the types of the directly
129 /// instantiated classes. 131 /// instantiated classes.
130 // TODO(johnniwinther): Improve semantic precision. 132 // TODO(johnniwinther): Improve semantic precision.
131 Iterable<DartType> get instantiatedTypes; 133 Iterable<DartType> get instantiatedTypes;
132
133 /// Returns `true` if [member] is invoked as a setter.
134 bool hasInvokedSetter(Element member, World world);
135 } 134 }
136 135
137 abstract class ResolutionWorldBuilder implements WorldBuilder { 136 abstract class ResolutionWorldBuilder implements WorldBuilder {
138 /// Set of (live) local functions (closures) whose signatures reference type 137 /// Set of (live) local functions (closures) whose signatures reference type
139 /// variables. 138 /// variables.
140 /// 139 ///
141 /// A live function is one whose enclosing member function has been enqueued. 140 /// A live function is one whose enclosing member function has been enqueued.
142 Iterable<Element> get closuresWithFreeTypeVariables; 141 Iterable<Element> get closuresWithFreeTypeVariables;
143 142
144 /// Set of (live) `call` methods whose signatures reference type variables. 143 /// Set of (live) `call` methods whose signatures reference type variables.
(...skipping 15 matching lines...) Expand all
160 bool isImplemented(ClassElement cls); 159 bool isImplemented(ClassElement cls);
161 160
162 /// Set of all fields that are statically known to be written to. 161 /// Set of all fields that are statically known to be written to.
163 Iterable<Element> get fieldSetters; 162 Iterable<Element> get fieldSetters;
164 163
165 /// Call [f] for all classes with instantiated types. This includes the 164 /// Call [f] for all classes with instantiated types. This includes the
166 /// directly and abstractly instantiated classes but also classes whose type 165 /// directly and abstractly instantiated classes but also classes whose type
167 /// arguments are used in live factory constructors. 166 /// arguments are used in live factory constructors.
168 void forEachInstantiatedClass(f(ClassElement cls, InstantiationInfo info)); 167 void forEachInstantiatedClass(f(ClassElement cls, InstantiationInfo info));
169 168
169 /// Returns `true` if [member] is invoked as a setter.
170 bool hasInvokedSetter(Element member);
171
170 /// `true` of `Object.runtimeType` is supported. 172 /// `true` of `Object.runtimeType` is supported.
171 bool get hasRuntimeTypeSupport; 173 bool get hasRuntimeTypeSupport;
172 174
173 /// `true` of use of the `dart:isolate` library is supported. 175 /// `true` of use of the `dart:isolate` library is supported.
174 bool get hasIsolateSupport; 176 bool get hasIsolateSupport;
175 177
176 /// `true` of `Function.apply` is supported. 178 /// `true` of `Function.apply` is supported.
177 bool get hasFunctionApplySupport; 179 bool get hasFunctionApplySupport;
178 180
179 /// The [OpenWorld] being created by this world builder. 181 /// The [OpenWorld] being created by this world builder.
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 */ 365 */
364 final Set<FunctionElement> methodsNeedingSuperGetter = 366 final Set<FunctionElement> methodsNeedingSuperGetter =
365 new Set<FunctionElement>(); 367 new Set<FunctionElement>();
366 final Map<String, Map<Selector, SelectorConstraints>> _invokedNames = 368 final Map<String, Map<Selector, SelectorConstraints>> _invokedNames =
367 <String, Map<Selector, SelectorConstraints>>{}; 369 <String, Map<Selector, SelectorConstraints>>{};
368 final Map<String, Map<Selector, SelectorConstraints>> _invokedGetters = 370 final Map<String, Map<Selector, SelectorConstraints>> _invokedGetters =
369 <String, Map<Selector, SelectorConstraints>>{}; 371 <String, Map<Selector, SelectorConstraints>>{};
370 final Map<String, Map<Selector, SelectorConstraints>> _invokedSetters = 372 final Map<String, Map<Selector, SelectorConstraints>> _invokedSetters =
371 <String, Map<Selector, SelectorConstraints>>{}; 373 <String, Map<Selector, SelectorConstraints>>{};
372 374
375 /// Map of registers usage of instance members of live classes.
376 final Map<MemberEntity, MemberUsage> _instanceMemberUsage =
377 <MemberEntity, MemberUsage>{};
378
379 /// Map containing instance members of live classes that are not yet live
380 /// themselves.
381 final Map<String, Set<MemberUsage>> _instanceMembersByName =
382 <String, Set<MemberUsage>>{};
383
384 /// Map containing instance methods of live classes that are not yet
385 /// closurized.
386 final Map<String, Set<MemberUsage>> _instanceFunctionsByName =
387 <String, Set<MemberUsage>>{};
388
373 /// Fields set. 389 /// Fields set.
374 final Set<Element> fieldSetters = new Set<Element>(); 390 final Set<Element> fieldSetters = new Set<Element>();
375 final Set<DartType> isChecks = new Set<DartType>(); 391 final Set<DartType> isChecks = new Set<DartType>();
376 392
377 /** 393 /**
378 * Set of (live) [:call:] methods whose signatures reference type variables. 394 * Set of (live) [:call:] methods whose signatures reference type variables.
379 * 395 *
380 * A live [:call:] method is one whose enclosing class has been instantiated. 396 * A live [:call:] method is one whose enclosing class has been instantiated.
381 */ 397 */
382 final Set<Element> callMethodsWithFreeTypeVariables = new Set<Element>(); 398 final Set<Element> callMethodsWithFreeTypeVariables = new Set<Element>();
(...skipping 23 matching lines...) Expand all
406 bool hasRuntimeTypeSupport = false; 422 bool hasRuntimeTypeSupport = false;
407 bool hasIsolateSupport = false; 423 bool hasIsolateSupport = false;
408 bool hasFunctionApplySupport = false; 424 bool hasFunctionApplySupport = false;
409 425
410 /// Used for testing the new more precise computation of instantiated types 426 /// Used for testing the new more precise computation of instantiated types
411 /// and classes. 427 /// and classes.
412 bool useInstantiationMap = false; 428 bool useInstantiationMap = false;
413 429
414 OpenWorld _openWorld; 430 OpenWorld _openWorld;
415 431
416 ResolutionWorldBuilderImpl(Backend backend, CoreClasses coreClasses, 432 final Backend _backend;
417 CacheStrategy cacheStrategy, this.selectorConstraintsStrategy) { 433 final Resolution _resolution;
418 _openWorld = new WorldImpl(this, backend, coreClasses, cacheStrategy); 434
435 ResolutionWorldBuilderImpl(Backend backend, Resolution resolution,
436 CacheStrategy cacheStrategy, this.selectorConstraintsStrategy)
437 : this._backend = backend,
438 this._resolution = resolution {
439 _openWorld =
440 new WorldImpl(this, backend, resolution.coreClasses, cacheStrategy);
419 } 441 }
420 442
421 OpenWorld get openWorld => _openWorld; 443 OpenWorld get openWorld => _openWorld;
422 444
423 /// All directly instantiated classes, that is, classes with a generative 445 /// All directly instantiated classes, that is, classes with a generative
424 /// constructor that has been called directly and not only through a 446 /// constructor that has been called directly and not only through a
425 /// super-call. 447 /// super-call.
426 // TODO(johnniwinther): Improve semantic precision. 448 // TODO(johnniwinther): Improve semantic precision.
427 Iterable<ClassElement> get directlyInstantiatedClasses { 449 Iterable<ClassElement> get directlyInstantiatedClasses {
428 Set<ClassElement> classes = new Set<ClassElement>(); 450 Set<ClassElement> classes = new Set<ClassElement>();
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
509 } 531 }
510 }); 532 });
511 } 533 }
512 } 534 }
513 535
514 @override 536 @override
515 void forEachInstantiatedClass(f(ClassElement cls, InstantiationInfo info)) { 537 void forEachInstantiatedClass(f(ClassElement cls, InstantiationInfo info)) {
516 getInstantiationMap().forEach(f); 538 getInstantiationMap().forEach(f);
517 } 539 }
518 540
519 bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors, 541 bool _hasMatchingSelector(
520 Element member, OpenWorld world) { 542 Map<Selector, SelectorConstraints> selectors, Element member) {
521 if (selectors == null) return false; 543 if (selectors == null) return false;
522 for (Selector selector in selectors.keys) { 544 for (Selector selector in selectors.keys) {
523 if (selector.appliesUnnamed(member)) { 545 if (selector.appliesUnnamed(member)) {
524 SelectorConstraints masks = selectors[selector]; 546 SelectorConstraints masks = selectors[selector];
525 if (masks.applies(member, selector, world)) { 547 if (masks.applies(member, selector, _openWorld)) {
526 return true; 548 return true;
527 } 549 }
528 } 550 }
529 } 551 }
530 return false; 552 return false;
531 } 553 }
532 554
533 /// Returns the instantiation map used for computing the closed world. 555 /// Returns the instantiation map used for computing the closed world.
534 /// 556 ///
535 /// If [useInstantiationMap] is `true`, redirections are removed and 557 /// If [useInstantiationMap] is `true`, redirections are removed and
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 infoFor(targetType.element) 589 infoFor(targetType.element)
568 .addInstantiation(target, targetType, kind); 590 .addInstantiation(target, targetType, kind);
569 } 591 }
570 } 592 }
571 }); 593 });
572 } 594 }
573 }); 595 });
574 return instantiationMap; 596 return instantiationMap;
575 } 597 }
576 598
577 bool hasInvocation(Element member, OpenWorld world) { 599 bool _hasInvocation(Element member) {
578 return _hasMatchingSelector(_invokedNames[member.name], member, world); 600 return _hasMatchingSelector(_invokedNames[member.name], member);
579 } 601 }
580 602
581 bool hasInvokedGetter(Element member, OpenWorld world) { 603 bool _hasInvokedGetter(Element member) {
582 return _hasMatchingSelector(_invokedGetters[member.name], member, world) || 604 return _hasMatchingSelector(_invokedGetters[member.name], member) ||
583 member.isFunction && methodsNeedingSuperGetter.contains(member); 605 member.isFunction && methodsNeedingSuperGetter.contains(member);
584 } 606 }
585 607
586 bool hasInvokedSetter(Element member, OpenWorld world) { 608 bool hasInvokedSetter(Element member) {
587 return _hasMatchingSelector(_invokedSetters[member.name], member, world); 609 return _hasMatchingSelector(_invokedSetters[member.name], member);
588 } 610 }
589 611
590 bool registerDynamicUse(DynamicUse dynamicUse) { 612 void registerDynamicUse(DynamicUse dynamicUse, MemberUsed memberUsed) {
613 Selector selector = dynamicUse.selector;
614 String methodName = selector.name;
591 switch (dynamicUse.kind) { 615 switch (dynamicUse.kind) {
592 case DynamicUseKind.INVOKE: 616 case DynamicUseKind.INVOKE:
593 return _registerNewSelector(dynamicUse, _invokedNames); 617 if (_registerNewSelector(dynamicUse, _invokedNames)) {
618 _processInstanceMembers(methodName, (MemberUsage usage) {
619 if (dynamicUse.appliesUnnamed(usage.member, _openWorld)) {
620 memberUsed(usage.member, usage.invoke());
621 return true;
622 }
623 return false;
624 });
625 }
626 break;
594 case DynamicUseKind.GET: 627 case DynamicUseKind.GET:
595 return _registerNewSelector(dynamicUse, _invokedGetters); 628 if (_registerNewSelector(dynamicUse, _invokedGetters)) {
629 _processInstanceMembers(methodName, (MemberUsage usage) {
630 if (dynamicUse.appliesUnnamed(usage.member, _openWorld)) {
631 memberUsed(usage.member, usage.read());
632 return true;
633 }
634 return false;
635 });
636 _processInstanceFunctions(methodName, (MemberUsage usage) {
637 if (dynamicUse.appliesUnnamed(usage.member, _openWorld)) {
638 memberUsed(usage.member, usage.read());
639 return true;
640 }
641 return false;
642 });
643 }
644 break;
596 case DynamicUseKind.SET: 645 case DynamicUseKind.SET:
597 return _registerNewSelector(dynamicUse, _invokedSetters); 646 if (_registerNewSelector(dynamicUse, _invokedSetters)) {
647 _processInstanceMembers(methodName, (MemberUsage usage) {
648 if (dynamicUse.appliesUnnamed(usage.member, _openWorld)) {
649 memberUsed(usage.member, usage.write());
650 return true;
651 }
652 return false;
653 });
654 }
655 break;
598 } 656 }
599 } 657 }
600 658
601 bool _registerNewSelector(DynamicUse dynamicUse, 659 bool _registerNewSelector(DynamicUse dynamicUse,
602 Map<String, Map<Selector, SelectorConstraints>> selectorMap) { 660 Map<String, Map<Selector, SelectorConstraints>> selectorMap) {
603 Selector selector = dynamicUse.selector; 661 Selector selector = dynamicUse.selector;
604 String name = selector.name; 662 String name = selector.name;
605 ReceiverConstraint mask = dynamicUse.mask; 663 ReceiverConstraint mask = dynamicUse.mask;
606 Map<Selector, SelectorConstraints> selectors = selectorMap.putIfAbsent( 664 Map<Selector, SelectorConstraints> selectors = selectorMap.putIfAbsent(
607 name, () => new Maplet<Selector, SelectorConstraints>()); 665 name, () => new Maplet<Selector, SelectorConstraints>());
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 break; 710 break;
653 } 711 }
654 } 712 }
655 713
656 void forgetElement(Element element, Compiler compiler) { 714 void forgetElement(Element element, Compiler compiler) {
657 allClosures.remove(element); 715 allClosures.remove(element);
658 slowDirectlyNestedClosures(element).forEach(compiler.forgetElement); 716 slowDirectlyNestedClosures(element).forEach(compiler.forgetElement);
659 closurizedMembers.remove(element); 717 closurizedMembers.remove(element);
660 fieldSetters.remove(element); 718 fieldSetters.remove(element);
661 _instantiationInfo.remove(element); 719 _instantiationInfo.remove(element);
720
721 void removeUsage(Set<MemberUsage> set, Element element) {
722 if (set == null) return;
723 set.removeAll(
724 set.where((MemberUsage usage) => usage.member == element).toList());
Harry Terkelsen 2016/12/05 22:48:53 is toList() necessary to prevent the 'where' from
Johnni Winther 2016/12/06 09:28:05 Yes.
725 }
726
727 removeUsage(_instanceMembersByName[element.name], element);
728 removeUsage(_instanceFunctionsByName[element.name], element);
662 } 729 }
663 730
664 // TODO(ahe): Replace this method with something that is O(1), for example, 731 // TODO(ahe): Replace this method with something that is O(1), for example,
665 // by using a map. 732 // by using a map.
666 List<LocalFunctionElement> slowDirectlyNestedClosures(Element element) { 733 List<LocalFunctionElement> slowDirectlyNestedClosures(Element element) {
667 // Return new list to guard against concurrent modifications. 734 // Return new list to guard against concurrent modifications.
668 return new List<LocalFunctionElement>.from( 735 return new List<LocalFunctionElement>.from(
669 allClosures.where((LocalFunctionElement closure) { 736 allClosures.where((LocalFunctionElement closure) {
670 return closure.executableContext == element; 737 return closure.executableContext == element;
671 })); 738 }));
672 } 739 }
740
741 void _processSet(Map<String, Set<MemberUsage>> map, String memberName,
742 bool f(MemberUsage e)) {
743 Set<MemberUsage> members = map[memberName];
744 if (members == null) return;
745 // [f] might add elements to [: map[memberName] :] during the loop below
746 // so we create a new list for [: map[memberName] :] and prepend the
747 // [remaining] members after the loop.
748 map[memberName] = new Set<MemberUsage>();
749 Set<MemberUsage> remaining = new Set<MemberUsage>();
750 for (MemberUsage usage in members) {
751 if (!f(usage)) remaining.add(usage);
752 }
753 map[memberName].addAll(remaining);
754 }
755
756 void _processInstanceMembers(String n, bool f(MemberUsage e)) {
Harry Terkelsen 2016/12/05 22:48:53 give these params full names
Johnni Winther 2016/12/06 09:28:06 Done.
757 _processSet(_instanceMembersByName, n, f);
758 }
759
760 void _processInstanceFunctions(String n, bool f(MemberUsage e)) {
761 _processSet(_instanceFunctionsByName, n, f);
762 }
763
764 // TODO(johnniwinther): Make this private when
765 // [ResolutionEnqueuer._processClass] is move to [ResolutionWorldBuilderImpl].
766 void processInstantiatedClassMember(
767 ClassElement cls, MemberElement member, MemberUsed memberUsed) {
768 assert(invariant(member, member.isDeclaration));
769 if (!member.isInstanceMember) return;
770 String memberName = member.name;
771 member.computeType(_resolution);
772 EnumSet<MemberUse> useSet = new EnumSet<MemberUse>();
773 // The obvious thing to test here would be "member.isNative",
774 // however, that only works after metadata has been parsed/analyzed,
775 // and that may not have happened yet.
776 // So instead we use the enclosing class, which we know have had
777 // its metadata parsed and analyzed.
778 // Note: this assumes that there are no non-native fields on native
779 // classes, which may not be the case when a native class is subclassed.
780 bool isNative = _backend.isNative(cls);
781 MemberUsage usage = _instanceMemberUsage.putIfAbsent(member, () {
782 MemberUsage usage = new MemberUsage(member, isNative: isNative);
783 useSet.addAll(usage.appliedUse);
784 if (member.isField && isNative) {
785 _openWorld.registerUsedElement(member);
786 }
787
788 if (_hasInvokedGetter(member)) {
789 useSet.addAll(usage.read());
790 }
791 if (_hasInvocation(member)) {
792 useSet.addAll(usage.invoke());
793 }
794 if (hasInvokedSetter(member)) {
795 useSet.addAll(usage.write());
796 }
797
798 if (usage.pendingUse.contains(MemberUse.NORMAL)) {
799 // The element is not yet used. Add it to the list of instance
800 // members to still be processed.
801 _instanceMembersByName
802 .putIfAbsent(memberName, () => new Set<MemberUsage>())
803 .add(usage);
804 }
805 if (usage.pendingUse.contains(MemberUse.CLOSURIZE)) {
806 // Store the member in [instanceFunctionsByName] to catch
807 // getters on the function.
808 _instanceFunctionsByName
809 .putIfAbsent(memberName, () => new Set<MemberUsage>())
810 .add(usage);
811 }
812
813 memberUsed(usage.member, useSet);
814 return usage;
815 });
816 }
673 } 817 }
674 818
675 /// World builder specific to codegen. 819 /// World builder specific to codegen.
676 /// 820 ///
677 /// This adds additional access to liveness of selectors and elements. 821 /// This adds additional access to liveness of selectors and elements.
678 abstract class CodegenWorldBuilder implements WorldBuilder { 822 abstract class CodegenWorldBuilder implements WorldBuilder {
679 void forEachInvokedName( 823 void forEachInvokedName(
680 f(String name, Map<Selector, SelectorConstraints> selectors)); 824 f(String name, Map<Selector, SelectorConstraints> selectors));
681 825
682 void forEachInvokedGetter( 826 void forEachInvokedGetter(
683 f(String name, Map<Selector, SelectorConstraints> selectors)); 827 f(String name, Map<Selector, SelectorConstraints> selectors));
684 828
685 void forEachInvokedSetter( 829 void forEachInvokedSetter(
686 f(String name, Map<Selector, SelectorConstraints> selectors)); 830 f(String name, Map<Selector, SelectorConstraints> selectors));
687 831
832 /// Returns `true` if [member] is invoked as a setter.
833 bool hasInvokedSetter(Element member, ClosedWorld world);
834
688 bool hasInvokedGetter(Element member, ClosedWorld world); 835 bool hasInvokedGetter(Element member, ClosedWorld world);
689 836
690 Map<Selector, SelectorConstraints> invocationsByName(String name); 837 Map<Selector, SelectorConstraints> invocationsByName(String name);
691 838
692 Map<Selector, SelectorConstraints> getterInvocationsByName(String name); 839 Map<Selector, SelectorConstraints> getterInvocationsByName(String name);
693 840
694 Map<Selector, SelectorConstraints> setterInvocationsByName(String name); 841 Map<Selector, SelectorConstraints> setterInvocationsByName(String name);
695 842
696 Iterable<FunctionElement> get staticFunctionsNeedingGetter; 843 Iterable<FunctionElement> get staticFunctionsNeedingGetter;
697 Iterable<FunctionElement> get methodsNeedingSuperGetter; 844 Iterable<FunctionElement> get methodsNeedingSuperGetter;
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
925 1072
926 void forgetElement(Element element, Compiler compiler) { 1073 void forgetElement(Element element, Compiler compiler) {
927 _directlyInstantiatedClasses.remove(element); 1074 _directlyInstantiatedClasses.remove(element);
928 if (element is ClassElement) { 1075 if (element is ClassElement) {
929 assert(invariant(element, element.thisType.isRaw, 1076 assert(invariant(element, element.thisType.isRaw,
930 message: 'Generic classes not supported (${element.thisType}).')); 1077 message: 'Generic classes not supported (${element.thisType}).'));
931 _instantiatedTypes..remove(element.rawType)..remove(element.thisType); 1078 _instantiatedTypes..remove(element.rawType)..remove(element.thisType);
932 } 1079 }
933 } 1080 }
934 } 1081 }
1082
1083 /// Registry for the observed use of [member] in the open world.
1084 abstract class MemberUsage {
1085 // TODO(johnniwinther): Change [Entity] to [MemberEntity].
1086 final Entity member;
1087 final EnumSet<MemberUse> _pendingUse = new EnumSet<MemberUse>();
1088
1089 MemberUsage.internal(this.member) {
1090 _pendingUse.addAll(_originalUse);
1091 }
1092
1093 factory MemberUsage(MemberEntity member, {bool isNative: false}) {
1094 if (member.isField) {
1095 if (member.isAssignable) {
1096 return new _FieldUsage(member, isNative: isNative);
1097 } else {
1098 return new _FinalFieldUsage(member, isNative: isNative);
1099 }
1100 } else if (member.isGetter) {
1101 return new _GetterUsage(member);
1102 } else if (member.isSetter) {
1103 return new _SetterUsage(member);
1104 } else {
1105 assert(member.isFunction);
1106 return new _FunctionUsage(member);
1107 }
1108 }
1109
1110 /// `true` if [member] has be read as a value. For a field this is a normal
Harry Terkelsen 2016/12/05 22:48:53 be -> been
Johnni Winther 2016/12/06 09:28:06 Done.
1111 /// read access, for a function this is a closurization.
1112 bool get hasRead => false;
1113
1114 /// `true` if a value as been written to [member].
Harry Terkelsen 2016/12/05 22:48:53 as -> has
Johnni Winther 2016/12/06 09:28:05 Done.
1115 bool get hasWrite => false;
1116
1117 /// `true` if an invocation has been performed on the value [member]. For a
1118 /// function this is a normal invocation, for a field this is a read access
1119 /// followed by an invocation of the function-like value.
1120 bool get hasInvoke => false;
1121
1122 /// `true` if [member] has been used in all the ways possible.
1123 bool get fullyUsed;
1124
1125 /// Registers a read of the value of [member] and returns the new [MemberUse]s
1126 /// that it caused.
1127 ///
1128 /// For a field this is a normal read access, for a function this is a
1129 /// closurization.
1130 EnumSet<MemberUse> read() => MemberUse.NONE;
1131
1132 /// Registers a write of a value to [member] and returns the new [MemberUse]s
1133 /// that it caused.
1134 EnumSet<MemberUse> write() => MemberUse.NONE;
1135
1136 /// Registers an invocation on the value of [member] and returns the new
1137 /// [MemberUse]s that it caused.
1138 ///
1139 /// For a function this is a normal invocation, for a field this is a read
1140 /// access followed by an invocation of the function-like value.
1141 EnumSet<MemberUse> invoke() => MemberUse.NONE;
1142
1143 /// Registers all possible uses of [member] and returns the new [MemberUse]s
1144 /// that it caused.
1145 EnumSet<MemberUse> fullyUse() => MemberUse.NONE;
1146
1147 /// Returns the possible [MemberUse]s of [member] that have not yet been
1148 /// registered.
1149 EnumSet<MemberUse> get pendingUse => _pendingUse;
1150
1151 /// Returns the [MemberUse]s of [member] that have been registered.
1152 EnumSet<MemberUse> get appliedUse => _originalUse.minus(_pendingUse);
1153
1154 EnumSet<MemberUse> get _originalUse;
1155
1156 int get hashCode => member.hashCode;
1157
1158 bool operator ==(other) {
1159 if (identical(this, other)) return true;
1160 if (other is! MemberUsage) return false;
1161 return member == other.member;
1162 }
1163
1164 String toString() => member.toString();
1165 }
1166
1167 class _FieldUsage extends MemberUsage {
1168 bool hasRead = false;
1169 bool hasWrite = false;
1170
1171 _FieldUsage(FieldEntity field, {bool isNative: false})
1172 : super.internal(field) {
1173 if (!isNative) {
1174 // All field initializers must be resolved as they could
1175 // have an observable side-effect (and cannot be tree-shaken
1176 // away).
1177 fullyUse();
1178 }
1179 }
1180
1181 EnumSet<MemberUse> get _originalUse => MemberUse.NORMAL_ONLY;
1182
1183 @override
1184 bool get fullyUsed => hasRead && hasWrite;
1185
1186 @override
1187 EnumSet<MemberUse> read() {
1188 if (fullyUsed) {
1189 return MemberUse.NONE;
1190 }
1191 hasRead = true;
1192 return _pendingUse.removeAll(MemberUse.NORMAL_ONLY);
1193 }
1194
1195 @override
1196 EnumSet<MemberUse> write() {
1197 if (fullyUsed) {
1198 return MemberUse.NONE;
1199 }
1200 hasWrite = true;
1201 return _pendingUse.removeAll(MemberUse.NORMAL_ONLY);
1202 }
1203
1204 @override
1205 EnumSet<MemberUse> invoke() => read();
1206
1207 @override
1208 EnumSet<MemberUse> fullyUse() {
1209 if (fullyUsed) {
1210 return MemberUse.NONE;
1211 }
1212 hasRead = hasWrite = true;
1213 return _pendingUse.removeAll(MemberUse.NORMAL_ONLY);
1214 }
1215 }
1216
1217 class _FinalFieldUsage extends MemberUsage {
1218 bool hasRead = false;
1219
1220 _FinalFieldUsage(FieldEntity field, {bool isNative: false})
1221 : super.internal(field) {
1222 if (!isNative) {
1223 // All field initializers must be resolved as they could
1224 // have an observable side-effect (and cannot be tree-shaken
1225 // away).
1226 read();
1227 }
1228 }
1229
1230 EnumSet<MemberUse> get _originalUse => MemberUse.NORMAL_ONLY;
1231
1232 @override
1233 bool get fullyUsed => hasRead;
1234
1235 @override
1236 EnumSet<MemberUse> read() {
1237 if (hasRead) {
1238 return MemberUse.NONE;
1239 }
1240 hasRead = true;
1241 return _pendingUse.removeAll(MemberUse.NORMAL_ONLY);
1242 }
1243
1244 @override
1245 EnumSet<MemberUse> invoke() => read();
1246
1247 @override
1248 EnumSet<MemberUse> fullyUse() => read();
1249 }
1250
1251 class _FunctionUsage extends MemberUsage {
1252 bool hasInvoke = false;
1253 bool hasRead = false;
1254
1255 _FunctionUsage(FunctionEntity function) : super.internal(function);
1256
1257 EnumSet<MemberUse> get _originalUse => MemberUse.ALL;
1258
1259 @override
1260 EnumSet<MemberUse> read() => fullyUse();
1261
1262 @override
1263 EnumSet<MemberUse> invoke() {
1264 if (hasInvoke) {
1265 return MemberUse.NONE;
1266 }
1267 hasInvoke = true;
1268 return _pendingUse
1269 .removeAll(hasRead ? MemberUse.NONE : MemberUse.NORMAL_ONLY);
1270 }
1271
1272 @override
1273 EnumSet<MemberUse> fullyUse() {
1274 if (hasInvoke) {
1275 if (hasRead) {
1276 return MemberUse.NONE;
1277 }
1278 hasRead = true;
1279 return _pendingUse.removeAll(MemberUse.CLOSURIZE_ONLY);
1280 } else if (hasRead) {
1281 hasInvoke = true;
1282 return _pendingUse.removeAll(MemberUse.NORMAL_ONLY);
1283 } else {
1284 hasRead = hasInvoke = true;
1285 return _pendingUse.removeAll(MemberUse.ALL);
1286 }
1287 }
1288
1289 @override
1290 bool get fullyUsed => hasInvoke && hasRead;
1291 }
1292
1293 class _GetterUsage extends MemberUsage {
1294 bool hasRead = false;
1295
1296 _GetterUsage(FunctionEntity getter) : super.internal(getter);
1297
1298 EnumSet<MemberUse> get _originalUse => MemberUse.NORMAL_ONLY;
1299
1300 @override
1301 bool get fullyUsed => hasRead;
1302
1303 @override
1304 EnumSet<MemberUse> read() {
1305 if (hasRead) {
1306 return MemberUse.NONE;
1307 }
1308 hasRead = true;
1309 return _pendingUse.removeAll(MemberUse.NORMAL_ONLY);
1310 }
1311
1312 @override
1313 EnumSet<MemberUse> invoke() => read();
1314
1315 @override
1316 EnumSet<MemberUse> fullyUse() => read();
1317 }
1318
1319 class _SetterUsage extends MemberUsage {
1320 bool hasWrite = false;
1321
1322 _SetterUsage(FunctionEntity setter) : super.internal(setter);
1323
1324 EnumSet<MemberUse> get _originalUse => MemberUse.NORMAL_ONLY;
Harry Terkelsen 2016/12/05 22:48:53 maybe make _originalUse have a default NORMAL_ONLY
Johnni Winther 2016/12/06 09:28:06 Done.
1325
1326 @override
1327 bool get fullyUsed => hasWrite;
1328
1329 @override
1330 EnumSet<MemberUse> write() {
1331 if (hasWrite) {
1332 return MemberUse.NONE;
1333 }
1334 hasWrite = true;
1335 return MemberUse.NORMAL_ONLY;
1336 }
1337
1338 @override
1339 EnumSet<MemberUse> fullyUse() => write();
1340 }
1341
1342 /// Enum-like class for the possible kind of use of [MemberEntity] objects.
1343 class MemberUse {
Harry Terkelsen 2016/12/05 22:48:53 why not just use an actual enum? and move the stat
Johnni Winther 2016/12/06 09:28:06 Done.
1344 final int index;
1345
1346 const MemberUse._(this.index);
1347
1348 static const List<MemberUse> values = const <MemberUse>[NORMAL, CLOSURIZE];
1349
1350 static const MemberUse NORMAL = const MemberUse._(0);
1351 static const MemberUse CLOSURIZE = const MemberUse._(1);
1352
1353 static const EnumSet<MemberUse> NONE = const EnumSet<MemberUse>.fixed(0);
1354 static const EnumSet<MemberUse> NORMAL_ONLY =
1355 const EnumSet<MemberUse>.fixed(1);
1356 static const EnumSet<MemberUse> CLOSURIZE_ONLY =
1357 const EnumSet<MemberUse>.fixed(2);
1358 static const EnumSet<MemberUse> ALL = const EnumSet<MemberUse>.fixed(3);
1359 }
1360
1361 typedef void MemberUsed(MemberEntity member, EnumSet<MemberUse> useSet);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698