Index: pkg/fletchc/lib/src/dynamic_call_enqueuer.dart |
diff --git a/pkg/fletchc/lib/src/dynamic_call_enqueuer.dart b/pkg/fletchc/lib/src/dynamic_call_enqueuer.dart |
index 8f05ae21a9cd97c115c0ef4a2b4c570624b84803..f0f81cdb7bbc11edfa004cfc33cb1c7d96f853ce 100644 |
--- a/pkg/fletchc/lib/src/dynamic_call_enqueuer.dart |
+++ b/pkg/fletchc/lib/src/dynamic_call_enqueuer.dart |
@@ -7,11 +7,9 @@ library fletchc.dynamic_call_enqueuer; |
import 'dart:collection' show |
Queue; |
-import 'package:compiler/src/dart2jslib.dart' show |
- EnqueueTask; |
- |
import 'package:compiler/src/universe/universe.dart' show |
CallStructure, |
+ Selector, |
UniverseSelector; |
import 'package:compiler/src/dart_types.dart' show |
@@ -20,6 +18,7 @@ import 'package:compiler/src/dart_types.dart' show |
import 'package:compiler/src/elements/elements.dart' show |
ClassElement, |
Element, |
+ FunctionElement, |
Name; |
import 'package:compiler/src/util/util.dart' show |
@@ -28,6 +27,8 @@ import 'package:compiler/src/util/util.dart' show |
import 'fletch_compiler_implementation.dart' show |
FletchCompilerImplementation; |
+typedef void ElementUsage(Element element, UniverseSelector selector); |
+ |
/// Implements the dynamic part of the tree-shaking algorithm. |
/// |
/// By "dynamic" part we mean the part that is about matching instantiated |
@@ -40,15 +41,12 @@ class DynamicCallEnqueuer { |
final Queue<ClassElement> pendingInstantiatedClasses = |
new Queue<ClassElement>(); |
- final Set<UntypedSelector> enqueuedSelectors = new Set<UntypedSelector>(); |
+ final Set<Selector> enqueuedSelectors = new Set<Selector>(); |
- final Queue<UntypedSelector> pendingSelectors = |
- new Queue<UntypedSelector>(); |
+ final Queue<Selector> pendingSelectors = new Queue<Selector>(); |
final Set<UniverseSelector> newlySeenSelectors; |
- EnqueueTask task; |
- |
DynamicCallEnqueuer(FletchCompilerImplementation compiler) |
: compiler = compiler, |
newlySeenSelectors = compiler.cacheStrategy.newSet(); |
@@ -62,20 +60,34 @@ class DynamicCallEnqueuer { |
void enqueueApplicableMembers( |
ClassElement cls, |
- UntypedSelector selector, |
- void enqueueElement(Element element)) { |
- Element member = cls.lookupByName(selector.name); |
- if (member != null && task.resolution.isProcessed(member)) { |
- // TODO(ahe): Check if selector applies; Don't consult resolution. |
- enqueueElement(member); |
+ Selector selector, |
+ ElementUsage enqueueElement) { |
+ Element member = cls.lookupByName(selector.memberName); |
+ if (member == null) return; |
+ if (!member.isInstanceMember) return; |
+ if (selector.isGetter) { |
+ if (member.isField || member.isGetter) { |
+ enqueueElement(member, new UniverseSelector(selector, null)); |
+ } else { |
+ // Tear-off. |
+ compiler.reportVerboseInfo( |
+ member, "enqueued as tear-off", forceVerbose: true); |
+ enqueueElement(member, new UniverseSelector(selector, null)); |
+ } |
+ } else if (selector.isSetter) { |
+ if (member.isField || member.isSetter) { |
+ enqueueElement(member, new UniverseSelector(selector, null)); |
+ } |
+ } else if (member.isFunction && selector.signatureApplies(member)) { |
+ enqueueElement(member, new UniverseSelector(selector, null)); |
} |
} |
- void enqueueInstanceMethods(void enqueueElement(Element element)) { |
+ void enqueueInstanceMethods(ElementUsage enqueueElement) { |
while (!pendingInstantiatedClasses.isEmpty) { |
ClassElement cls = pendingInstantiatedClasses.removeFirst(); |
compiler.reportVerboseInfo(cls, "was instantiated", forceVerbose: true); |
- for (UntypedSelector selector in enqueuedSelectors) { |
+ for (Selector selector in enqueuedSelectors) { |
// TODO(ahe): As we iterate over enqueuedSelectors, we may end up |
// processing calling _enqueueApplicableMembers twice for newly |
// instantiated classes. Once here, and then once more in the while |
@@ -84,7 +96,7 @@ class DynamicCallEnqueuer { |
} |
} |
while (!pendingSelectors.isEmpty) { |
- UntypedSelector selector = pendingSelectors.removeFirst(); |
+ Selector selector = pendingSelectors.removeFirst(); |
compiler.reportVerboseInfo( |
null, "$selector was called", forceVerbose: true); |
for (ClassElement cls in instantiatedClasses) { |
@@ -94,8 +106,8 @@ class DynamicCallEnqueuer { |
} |
void enqueueSelector(UniverseSelector universeSelector) { |
- UntypedSelector selector = |
- new UntypedSelector.fromUniverseSelector(universeSelector); |
+ assert(universeSelector.mask == null); |
+ Selector selector = universeSelector.selector; |
if (enqueuedSelectors.add(selector)) { |
pendingSelectors.add(selector); |
newlySeenSelectors.add(universeSelector); |
@@ -109,60 +121,3 @@ class DynamicCallEnqueuer { |
instantiatedClasses.remove(element); |
} |
} |
- |
-/// Represents information about a call site. |
-/// |
-/// This class differ from [UniverseSelector] in two key areas: |
-/// |
-/// 1. Implements `operator ==` (and is thus suitable for use in a [Set]) |
ahe
2015/09/03 15:07:10
I had overlooked that Selector is canonicalized an
Johnni Winther
2015/09/03 16:21:17
They might actually not always be canonicalized bu
ahe
2015/09/03 16:24:09
That's good enough for me :-)
|
-/// 2. Has no type mask |
-class UntypedSelector { |
- final Name name; |
- |
- final bool isGetter; |
- |
- final bool isSetter; |
- |
- final CallStructure structure; |
- |
- final int hashCode; |
- |
- UntypedSelector( |
- this.name, |
- this.isGetter, |
- this.isSetter, |
- this.structure, |
- this.hashCode); |
- |
- factory UntypedSelector.fromUniverseSelector(UniverseSelector selector) { |
- if (selector.mask != null) { |
- throw new ArgumentError("[selector] has non-null type mask"); |
- } |
- Name name = selector.selector.memberName; |
- CallStructure structure = selector.selector.callStructure; |
- bool isGetter = selector.selector.isGetter; |
- bool isSetter = selector.selector.isSetter; |
- int hash = Hashing.mixHashCodeBits(name.hashCode, structure.hashCode); |
- hash = Hashing.mixHashCodeBits(hash, isSetter.hashCode); |
- hash = Hashing.mixHashCodeBits(hash, isGetter.hashCode); |
- return new UntypedSelector(name, isGetter, isSetter, structure, hash); |
- } |
- |
- bool operator ==(other) { |
- if (other is UntypedSelector) { |
- return name == other.name && |
- isGetter == other.isGetter && isSetter == other.isSetter && |
- structure == other.structure; |
- } else { |
- return false; |
- } |
- } |
- |
- String toString() { |
- return |
- 'UntypedSelector($name, ' |
- '${isGetter ? "getter, " : ""}' |
- '${isSetter ? "setter, " : ""}' |
- '$structure)'; |
- } |
-} |