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

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: Updated cf. comments. 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
« no previous file with comments | « pkg/compiler/lib/src/js_backend/enqueuer.dart ('k') | pkg/compiler/lib/src/util/enumset.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) 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());
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 /// Call [updateUsage] on all [MemberUsage]s in the set in [map] for
742 /// [memberName]. If [updateUsage] returns `true` the usage is removed from
743 /// the set.
744 void _processSet(Map<String, Set<MemberUsage>> map, String memberName,
745 bool updateUsage(MemberUsage e)) {
746 Set<MemberUsage> members = map[memberName];
747 if (members == null) return;
748 // [f] might add elements to [: map[memberName] :] during the loop below
749 // so we create a new list for [: map[memberName] :] and prepend the
750 // [remaining] members after the loop.
751 map[memberName] = new Set<MemberUsage>();
752 Set<MemberUsage> remaining = new Set<MemberUsage>();
753 for (MemberUsage usage in members) {
754 if (!updateUsage(usage)) {
755 remaining.add(usage);
756 }
757 }
758 map[memberName].addAll(remaining);
759 }
760
761 void _processInstanceMembers(String name, bool updateUsage(MemberUsage e)) {
762 _processSet(_instanceMembersByName, name, updateUsage);
763 }
764
765 void _processInstanceFunctions(String name, bool updateUsage(MemberUsage e)) {
766 _processSet(_instanceFunctionsByName, name, updateUsage);
767 }
768
769 // TODO(johnniwinther): Make this private when
770 // [ResolutionEnqueuer._processClass] is move to [ResolutionWorldBuilderImpl].
771 void processInstantiatedClassMember(
772 ClassElement cls, MemberElement member, MemberUsed memberUsed) {
773 assert(invariant(member, member.isDeclaration));
774 if (!member.isInstanceMember) return;
775 String memberName = member.name;
776 member.computeType(_resolution);
777 EnumSet<MemberUse> useSet = new EnumSet<MemberUse>();
778 // The obvious thing to test here would be "member.isNative",
779 // however, that only works after metadata has been parsed/analyzed,
780 // and that may not have happened yet.
781 // So instead we use the enclosing class, which we know have had
782 // its metadata parsed and analyzed.
783 // Note: this assumes that there are no non-native fields on native
784 // classes, which may not be the case when a native class is subclassed.
785 bool isNative = _backend.isNative(cls);
786 MemberUsage usage = _instanceMemberUsage.putIfAbsent(member, () {
787 MemberUsage usage = new MemberUsage(member, isNative: isNative);
788 useSet.addAll(usage.appliedUse);
789 if (member.isField && isNative) {
790 _openWorld.registerUsedElement(member);
791 }
792
793 if (_hasInvokedGetter(member)) {
794 useSet.addAll(usage.read());
795 }
796 if (_hasInvocation(member)) {
797 useSet.addAll(usage.invoke());
798 }
799 if (hasInvokedSetter(member)) {
800 useSet.addAll(usage.write());
801 }
802
803 if (usage.pendingUse.contains(MemberUse.NORMAL)) {
804 // The element is not yet used. Add it to the list of instance
805 // members to still be processed.
806 _instanceMembersByName
807 .putIfAbsent(memberName, () => new Set<MemberUsage>())
808 .add(usage);
809 }
810 if (usage.pendingUse.contains(MemberUse.CLOSURIZE)) {
811 // Store the member in [instanceFunctionsByName] to catch
812 // getters on the function.
813 _instanceFunctionsByName
814 .putIfAbsent(memberName, () => new Set<MemberUsage>())
815 .add(usage);
816 }
817
818 memberUsed(usage.member, useSet);
819 return usage;
820 });
821 }
673 } 822 }
674 823
675 /// World builder specific to codegen. 824 /// World builder specific to codegen.
676 /// 825 ///
677 /// This adds additional access to liveness of selectors and elements. 826 /// This adds additional access to liveness of selectors and elements.
678 abstract class CodegenWorldBuilder implements WorldBuilder { 827 abstract class CodegenWorldBuilder implements WorldBuilder {
679 void forEachInvokedName( 828 void forEachInvokedName(
680 f(String name, Map<Selector, SelectorConstraints> selectors)); 829 f(String name, Map<Selector, SelectorConstraints> selectors));
681 830
682 void forEachInvokedGetter( 831 void forEachInvokedGetter(
683 f(String name, Map<Selector, SelectorConstraints> selectors)); 832 f(String name, Map<Selector, SelectorConstraints> selectors));
684 833
685 void forEachInvokedSetter( 834 void forEachInvokedSetter(
686 f(String name, Map<Selector, SelectorConstraints> selectors)); 835 f(String name, Map<Selector, SelectorConstraints> selectors));
687 836
837 /// Returns `true` if [member] is invoked as a setter.
838 bool hasInvokedSetter(Element member, ClosedWorld world);
839
688 bool hasInvokedGetter(Element member, ClosedWorld world); 840 bool hasInvokedGetter(Element member, ClosedWorld world);
689 841
690 Map<Selector, SelectorConstraints> invocationsByName(String name); 842 Map<Selector, SelectorConstraints> invocationsByName(String name);
691 843
692 Map<Selector, SelectorConstraints> getterInvocationsByName(String name); 844 Map<Selector, SelectorConstraints> getterInvocationsByName(String name);
693 845
694 Map<Selector, SelectorConstraints> setterInvocationsByName(String name); 846 Map<Selector, SelectorConstraints> setterInvocationsByName(String name);
695 847
696 Iterable<FunctionElement> get staticFunctionsNeedingGetter; 848 Iterable<FunctionElement> get staticFunctionsNeedingGetter;
697 Iterable<FunctionElement> get methodsNeedingSuperGetter; 849 Iterable<FunctionElement> get methodsNeedingSuperGetter;
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
925 1077
926 void forgetElement(Element element, Compiler compiler) { 1078 void forgetElement(Element element, Compiler compiler) {
927 _directlyInstantiatedClasses.remove(element); 1079 _directlyInstantiatedClasses.remove(element);
928 if (element is ClassElement) { 1080 if (element is ClassElement) {
929 assert(invariant(element, element.thisType.isRaw, 1081 assert(invariant(element, element.thisType.isRaw,
930 message: 'Generic classes not supported (${element.thisType}).')); 1082 message: 'Generic classes not supported (${element.thisType}).'));
931 _instantiatedTypes..remove(element.rawType)..remove(element.thisType); 1083 _instantiatedTypes..remove(element.rawType)..remove(element.thisType);
932 } 1084 }
933 } 1085 }
934 } 1086 }
1087
1088 /// Registry for the observed use of [member] in the open world.
1089 abstract class MemberUsage {
1090 // TODO(johnniwinther): Change [Entity] to [MemberEntity].
1091 final Entity member;
1092 final EnumSet<MemberUse> _pendingUse = new EnumSet<MemberUse>();
1093
1094 MemberUsage.internal(this.member) {
1095 _pendingUse.addAll(_originalUse);
1096 }
1097
1098 factory MemberUsage(MemberEntity member, {bool isNative: false}) {
1099 if (member.isField) {
1100 if (member.isAssignable) {
1101 return new _FieldUsage(member, isNative: isNative);
1102 } else {
1103 return new _FinalFieldUsage(member, isNative: isNative);
1104 }
1105 } else if (member.isGetter) {
1106 return new _GetterUsage(member);
1107 } else if (member.isSetter) {
1108 return new _SetterUsage(member);
1109 } else {
1110 assert(member.isFunction);
1111 return new _FunctionUsage(member);
1112 }
1113 }
1114
1115 /// `true` if [member] has been read as a value. For a field this is a normal
1116 /// read access, for a function this is a closurization.
1117 bool get hasRead => false;
1118
1119 /// `true` if a value has been written to [member].
1120 bool get hasWrite => false;
1121
1122 /// `true` if an invocation has been performed on the value [member]. For a
1123 /// function this is a normal invocation, for a field this is a read access
1124 /// followed by an invocation of the function-like value.
1125 bool get hasInvoke => false;
1126
1127 /// `true` if [member] has been used in all the ways possible.
1128 bool get fullyUsed;
1129
1130 /// Registers a read of the value of [member] and returns the new [MemberUse]s
1131 /// that it caused.
1132 ///
1133 /// For a field this is a normal read access, for a function this is a
1134 /// closurization.
1135 EnumSet<MemberUse> read() => MemberUses.NONE;
1136
1137 /// Registers a write of a value to [member] and returns the new [MemberUse]s
1138 /// that it caused.
1139 EnumSet<MemberUse> write() => MemberUses.NONE;
1140
1141 /// Registers an invocation on the value of [member] and returns the new
1142 /// [MemberUse]s that it caused.
1143 ///
1144 /// For a function this is a normal invocation, for a field this is a read
1145 /// access followed by an invocation of the function-like value.
1146 EnumSet<MemberUse> invoke() => MemberUses.NONE;
1147
1148 /// Registers all possible uses of [member] and returns the new [MemberUse]s
1149 /// that it caused.
1150 EnumSet<MemberUse> fullyUse() => MemberUses.NONE;
1151
1152 /// Returns the possible [MemberUse]s of [member] that have not yet been
1153 /// registered.
1154 EnumSet<MemberUse> get pendingUse => _pendingUse;
1155
1156 /// Returns the [MemberUse]s of [member] that have been registered.
1157 EnumSet<MemberUse> get appliedUse => _originalUse.minus(_pendingUse);
1158
1159 EnumSet<MemberUse> get _originalUse => MemberUses.NORMAL_ONLY;
1160
1161 int get hashCode => member.hashCode;
1162
1163 bool operator ==(other) {
1164 if (identical(this, other)) return true;
1165 if (other is! MemberUsage) return false;
1166 return member == other.member;
1167 }
1168
1169 String toString() => member.toString();
1170 }
1171
1172 class _FieldUsage extends MemberUsage {
1173 bool hasRead = false;
1174 bool hasWrite = false;
1175
1176 _FieldUsage(FieldEntity field, {bool isNative: false})
1177 : super.internal(field) {
1178 if (!isNative) {
1179 // All field initializers must be resolved as they could
1180 // have an observable side-effect (and cannot be tree-shaken
1181 // away).
1182 fullyUse();
1183 }
1184 }
1185
1186 @override
1187 bool get fullyUsed => hasRead && hasWrite;
1188
1189 @override
1190 EnumSet<MemberUse> read() {
1191 if (fullyUsed) {
1192 return MemberUses.NONE;
1193 }
1194 hasRead = true;
1195 return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
1196 }
1197
1198 @override
1199 EnumSet<MemberUse> write() {
1200 if (fullyUsed) {
1201 return MemberUses.NONE;
1202 }
1203 hasWrite = true;
1204 return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
1205 }
1206
1207 @override
1208 EnumSet<MemberUse> invoke() => read();
1209
1210 @override
1211 EnumSet<MemberUse> fullyUse() {
1212 if (fullyUsed) {
1213 return MemberUses.NONE;
1214 }
1215 hasRead = hasWrite = true;
1216 return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
1217 }
1218 }
1219
1220 class _FinalFieldUsage extends MemberUsage {
1221 bool hasRead = false;
1222
1223 _FinalFieldUsage(FieldEntity field, {bool isNative: false})
1224 : super.internal(field) {
1225 if (!isNative) {
1226 // All field initializers must be resolved as they could
1227 // have an observable side-effect (and cannot be tree-shaken
1228 // away).
1229 read();
1230 }
1231 }
1232
1233 @override
1234 bool get fullyUsed => hasRead;
1235
1236 @override
1237 EnumSet<MemberUse> read() {
1238 if (hasRead) {
1239 return MemberUses.NONE;
1240 }
1241 hasRead = true;
1242 return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
1243 }
1244
1245 @override
1246 EnumSet<MemberUse> invoke() => read();
1247
1248 @override
1249 EnumSet<MemberUse> fullyUse() => read();
1250 }
1251
1252 class _FunctionUsage extends MemberUsage {
1253 bool hasInvoke = false;
1254 bool hasRead = false;
1255
1256 _FunctionUsage(FunctionEntity function) : super.internal(function);
1257
1258 EnumSet<MemberUse> get _originalUse => MemberUses.ALL;
1259
1260 @override
1261 EnumSet<MemberUse> read() => fullyUse();
1262
1263 @override
1264 EnumSet<MemberUse> invoke() {
1265 if (hasInvoke) {
1266 return MemberUses.NONE;
1267 }
1268 hasInvoke = true;
1269 return _pendingUse
1270 .removeAll(hasRead ? MemberUses.NONE : MemberUses.NORMAL_ONLY);
1271 }
1272
1273 @override
1274 EnumSet<MemberUse> fullyUse() {
1275 if (hasInvoke) {
1276 if (hasRead) {
1277 return MemberUses.NONE;
1278 }
1279 hasRead = true;
1280 return _pendingUse.removeAll(MemberUses.CLOSURIZE_ONLY);
1281 } else if (hasRead) {
1282 hasInvoke = true;
1283 return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
1284 } else {
1285 hasRead = hasInvoke = true;
1286 return _pendingUse.removeAll(MemberUses.ALL);
1287 }
1288 }
1289
1290 @override
1291 bool get fullyUsed => hasInvoke && hasRead;
1292 }
1293
1294 class _GetterUsage extends MemberUsage {
1295 bool hasRead = false;
1296
1297 _GetterUsage(FunctionEntity getter) : super.internal(getter);
1298
1299 @override
1300 bool get fullyUsed => hasRead;
1301
1302 @override
1303 EnumSet<MemberUse> read() {
1304 if (hasRead) {
1305 return MemberUses.NONE;
1306 }
1307 hasRead = true;
1308 return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
1309 }
1310
1311 @override
1312 EnumSet<MemberUse> invoke() => read();
1313
1314 @override
1315 EnumSet<MemberUse> fullyUse() => read();
1316 }
1317
1318 class _SetterUsage extends MemberUsage {
1319 bool hasWrite = false;
1320
1321 _SetterUsage(FunctionEntity setter) : super.internal(setter);
1322
1323 @override
1324 bool get fullyUsed => hasWrite;
1325
1326 @override
1327 EnumSet<MemberUse> write() {
1328 if (hasWrite) {
1329 return MemberUses.NONE;
1330 }
1331 hasWrite = true;
1332 return MemberUses.NORMAL_ONLY;
1333 }
1334
1335 @override
1336 EnumSet<MemberUse> fullyUse() => write();
1337 }
1338
1339 /// Enum class for the possible kind of use of [MemberEntity] objects.
1340 enum MemberUse { NORMAL, CLOSURIZE }
1341
1342 /// Common [EnumSet]s used for [MemberUse].
1343 class MemberUses {
1344 static const EnumSet<MemberUse> NONE = const EnumSet<MemberUse>.fixed(0);
1345 static const EnumSet<MemberUse> NORMAL_ONLY =
1346 const EnumSet<MemberUse>.fixed(1);
1347 static const EnumSet<MemberUse> CLOSURIZE_ONLY =
1348 const EnumSet<MemberUse>.fixed(2);
1349 static const EnumSet<MemberUse> ALL = const EnumSet<MemberUse>.fixed(3);
1350 }
1351
1352 typedef void MemberUsed(MemberEntity member, EnumSet<MemberUse> useSet);
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/enqueuer.dart ('k') | pkg/compiler/lib/src/util/enumset.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698