Index: pkg/compiler/lib/src/universe/world_builder.dart |
diff --git a/pkg/compiler/lib/src/universe/world_builder.dart b/pkg/compiler/lib/src/universe/world_builder.dart |
index f7683986429ce451043d9a0e9b04ce2738e6bbe8..495988f49dfbb515b0019fe7791e4cd279f8ed8f 100644 |
--- a/pkg/compiler/lib/src/universe/world_builder.dart |
+++ b/pkg/compiler/lib/src/universe/world_builder.dart |
@@ -375,7 +375,11 @@ class ResolutionWorldBuilderImpl implements ResolutionWorldBuilder { |
final Map<ClassElement, _ClassUsage> _processedClasses = |
<ClassElement, _ClassUsage>{}; |
- /// Map of registers usage of instance members of live classes. |
+ /// Map of registered usage of static members of live classes. |
+ final Map<Entity, _StaticMemberUsage> _staticMemberUsage = |
+ <Entity, _StaticMemberUsage>{}; |
+ |
+ /// Map of registered usage of instance members of live classes. |
final Map<MemberEntity, _MemberUsage> _instanceMemberUsage = |
<MemberEntity, _MemberUsage>{}; |
@@ -619,7 +623,8 @@ class ResolutionWorldBuilderImpl implements ResolutionWorldBuilder { |
return _hasMatchingSelector(_invokedSetters[member.name], member); |
} |
- void registerDynamicUse(DynamicUse dynamicUse, MemberUsed memberUsed) { |
+ void registerDynamicUse( |
+ DynamicUse dynamicUse, MemberUsedCallback memberUsed) { |
Selector selector = dynamicUse.selector; |
String methodName = selector.name; |
switch (dynamicUse.kind) { |
@@ -690,35 +695,65 @@ class ResolutionWorldBuilderImpl implements ResolutionWorldBuilder { |
return type; |
} |
- void registerStaticUse(StaticUse staticUse) { |
+ void registerStaticUse(StaticUse staticUse, MemberUsedCallback memberUsed) { |
Element element = staticUse.element; |
+ assert(invariant(element, element.isDeclaration, |
+ message: "Element ${element} is not the declaration.")); |
+ _StaticMemberUsage usage = _staticMemberUsage.putIfAbsent(element, () { |
+ if ((element.isStatic || element.isTopLevel) && element.isFunction) { |
+ return new _StaticFunctionUsage(element); |
+ } else { |
+ return new _GeneralStaticMemberUsage(element); |
+ } |
+ }); |
+ EnumSet<MemberUse> useSet = new EnumSet<MemberUse>(); |
+ |
if (Elements.isStaticOrTopLevel(element) && element.isField) { |
allReferencedStaticFields.add(element); |
} |
+ // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and |
+ // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue. |
+ // Also [CLOSURE] contains [LocalFunctionElement] which we cannot |
+ // enqueue. |
switch (staticUse.kind) { |
- case StaticUseKind.SUPER_FIELD_SET: |
+ case StaticUseKind.FIELD_GET: |
+ break; |
case StaticUseKind.FIELD_SET: |
fieldSetters.add(element); |
break; |
+ case StaticUseKind.CLOSURE: |
+ LocalFunctionElement closure = staticUse.element; |
+ if (closure.type.containsTypeVariables) { |
+ closuresWithFreeTypeVariables.add(closure); |
+ } |
+ allClosures.add(element); |
+ break; |
case StaticUseKind.SUPER_TEAR_OFF: |
+ useSet.addAll(usage.tearOff()); |
methodsNeedingSuperGetter.add(element); |
break; |
+ case StaticUseKind.SUPER_FIELD_SET: |
+ fieldSetters.add(element); |
+ useSet.addAll(usage.normalUse()); |
+ break; |
+ case StaticUseKind.STATIC_TEAR_OFF: |
+ useSet.addAll(usage.tearOff()); |
+ break; |
case StaticUseKind.GENERAL: |
case StaticUseKind.DIRECT_USE: |
- case StaticUseKind.STATIC_TEAR_OFF: |
- case StaticUseKind.FIELD_GET: |
case StaticUseKind.CONSTRUCTOR_INVOKE: |
case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: |
case StaticUseKind.REDIRECTION: |
- break; |
- case StaticUseKind.CLOSURE: |
- allClosures.add(element); |
+ useSet.addAll(usage.normalUse()); |
break; |
case StaticUseKind.DIRECT_INVOKE: |
invariant( |
element, 'Direct static use is not supported for resolution.'); |
break; |
} |
+ if (useSet.isNotEmpty) { |
+ memberUsed(usage.entity, useSet); |
+ } |
} |
void forgetEntity(Entity entity, Compiler compiler) { |
@@ -780,7 +815,7 @@ class ResolutionWorldBuilderImpl implements ResolutionWorldBuilder { |
/// Computes usage for all members declared by [cls]. Calls [membersUsed] with |
/// the usage changes for each member. |
- void processClassMembers(ClassElement cls, MemberUsed memberUsed) { |
+ void processClassMembers(ClassElement cls, MemberUsedCallback memberUsed) { |
cls.implementation.forEachMember((ClassElement cls, MemberElement member) { |
_processInstantiatedClassMember(cls, member, memberUsed); |
}); |
@@ -814,7 +849,7 @@ class ResolutionWorldBuilderImpl implements ResolutionWorldBuilder { |
} |
void _processInstantiatedClassMember( |
- ClassElement cls, MemberElement member, MemberUsed memberUsed) { |
+ ClassElement cls, MemberElement member, MemberUsedCallback memberUsed) { |
assert(invariant(member, member.isDeclaration)); |
if (!member.isInstanceMember) return; |
String memberName = member.name; |
@@ -1401,7 +1436,7 @@ class MemberUses { |
static const EnumSet<MemberUse> ALL = const EnumSet<MemberUse>.fixed(3); |
} |
-typedef void MemberUsed(MemberEntity member, EnumSet<MemberUse> useSet); |
+typedef void MemberUsedCallback(MemberEntity member, EnumSet<MemberUse> useSet); |
/// Registry for the observed use of a class [entity] in the open world. |
// TODO(johnniwinther): Merge this with [InstantiationInfo]. |
@@ -1449,3 +1484,51 @@ class ClassUses { |
} |
typedef void ClassUsed(ClassEntity cls, EnumSet<ClassUse> useSet); |
+ |
+// TODO(johnniwinther): Merge this with [_MemberUsage]. |
+abstract class _StaticMemberUsage extends _AbstractUsage<MemberUse> { |
+ final Entity entity; |
+ |
+ bool hasNormalUse = false; |
+ bool get hasClosurization => false; |
+ |
+ _StaticMemberUsage.internal(this.entity); |
+ |
+ EnumSet<MemberUse> normalUse() { |
+ if (hasNormalUse) { |
+ return MemberUses.NONE; |
+ } |
+ hasNormalUse = true; |
+ return _pendingUse.removeAll(MemberUses.NORMAL_ONLY); |
+ } |
+ |
+ EnumSet<MemberUse> tearOff(); |
+ |
+ @override |
+ EnumSet<MemberUse> get _originalUse => MemberUses.NORMAL_ONLY; |
+ |
+ String toString() => entity.toString(); |
+} |
+ |
+class _GeneralStaticMemberUsage extends _StaticMemberUsage { |
+ _GeneralStaticMemberUsage(Entity entity) : super.internal(entity); |
+ |
+ EnumSet<MemberUse> tearOff() => normalUse(); |
+} |
+ |
+class _StaticFunctionUsage extends _StaticMemberUsage { |
+ bool hasClosurization = false; |
+ |
+ _StaticFunctionUsage(Entity entity) : super.internal(entity); |
+ |
+ EnumSet<MemberUse> tearOff() { |
+ if (hasClosurization) { |
+ return MemberUses.NONE; |
+ } |
+ hasNormalUse = hasClosurization = true; |
+ return _pendingUse.removeAll(MemberUses.ALL); |
+ } |
+ |
+ @override |
+ EnumSet<MemberUse> get _originalUse => MemberUses.ALL; |
+} |