Index: pkg/compiler/lib/src/world.dart |
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart |
index 7f29d27c8a5a8a9e458b1e30651c3c9655bf4947..8c7ad70c0af5097aefd5100e75aa81d31b5a78a9 100644 |
--- a/pkg/compiler/lib/src/world.dart |
+++ b/pkg/compiler/lib/src/world.dart |
@@ -17,8 +17,7 @@ import 'elements/elements.dart' |
FunctionElement, |
MemberElement, |
MixinApplicationElement, |
- TypedefElement, |
- FieldElement; |
+ TypedefElement; |
import 'elements/resolution_types.dart'; |
import 'js_backend/backend.dart' show JavaScriptBackend; |
import 'js_backend/interceptor_data.dart' show InterceptorData; |
@@ -121,11 +120,11 @@ abstract class ClosedWorld implements World { |
/// Returns an iterable over the directly instantiated that implement [cls] |
/// possibly including [cls] itself, if it is live. |
- Iterable<ClassElement> subtypesOf(ClassEntity cls); |
+ Iterable<ClassEntity> subtypesOf(ClassEntity cls); |
/// Returns an iterable over the live classes that implement [cls] _not_ |
/// including [cls] if it is live. |
- Iterable<ClassElement> strictSubtypesOf(ClassEntity cls); |
+ Iterable<ClassEntity> strictSubtypesOf(ClassEntity cls); |
/// Returns the number of live classes that implement [cls] _not_ |
/// including [cls] itself. |
@@ -183,8 +182,8 @@ abstract class ClosedWorld implements World { |
/// commonSubclasses(A, ClassQuery.SUBTYPE, B, ClassQuery.SUBTYPE) |
/// |
/// return the set {C} because [D] is implied by [C]. |
- Iterable<ClassEntity> commonSubclasses(ClassElement cls1, ClassQuery query1, |
- ClassElement cls2, ClassQuery query2); |
+ Iterable<ClassEntity> commonSubclasses( |
+ ClassEntity cls1, ClassQuery query1, ClassEntity cls2, ClassQuery query2); |
/// Returns an iterable over the live mixin applications that mixin [cls]. |
Iterable<ClassEntity> mixinUsesOf(ClassEntity cls); |
@@ -388,7 +387,7 @@ enum ClassQuery { |
SUBTYPE, |
} |
-class ClosedWorldImpl implements ClosedWorld, ClosedWorldRefiner { |
+abstract class ClosedWorldBase implements ClosedWorld, ClosedWorldRefiner { |
final JavaScriptBackend _backend; |
BackendClasses get backendClasses => _backend.backendClasses; |
InterceptorData get interceptorData => _backend.interceptorData; |
@@ -425,7 +424,7 @@ class ClosedWorldImpl implements ClosedWorld, ClosedWorldRefiner { |
final ResolutionWorldBuilder _resolverWorld; |
- ClosedWorldImpl( |
+ ClosedWorldBase( |
{JavaScriptBackend backend, |
this.commonElements, |
ResolutionWorldBuilder resolutionWorldBuilder, |
@@ -470,47 +469,7 @@ class ClosedWorldImpl implements ClosedWorld, ClosedWorldRefiner { |
return cachedMasks.putIfAbsent(base, createMask); |
} |
- bool _checkClass(ClassElement cls) => cls.isDeclaration; |
- |
- bool checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) { |
- return invariant(cls, cls.isDeclaration, |
- message: '$cls must be the declaration.') && |
- invariant(cls, cls.isResolved, |
- message: |
- '$cls must be resolved.') /* && |
- // TODO(johnniwinther): Reinsert this or similar invariant. |
- (!mustBeInstantiated || |
- invariant(cls, isInstantiated(cls), |
- message: '$cls is not instantiated.'))*/ |
- ; |
- } |
- |
- /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an |
- /// instance of [y]. |
- bool isSubtypeOf(ClassElement x, ClassElement y) { |
- assert(checkInvariants(x)); |
- assert(checkInvariants(y, mustBeInstantiated: false)); |
- |
- if (y == commonElements.objectClass) return true; |
- if (x == commonElements.objectClass) return false; |
- if (x.asInstanceOf(y) != null) return true; |
- if (y != commonElements.functionClass) return false; |
- return x.callType != null; |
- } |
- |
- /// Return `true` if [x] is a (non-strict) subclass of [y]. |
- bool isSubclassOf(ClassElement x, ClassElement y) { |
- assert(checkInvariants(x)); |
- assert(checkInvariants(y)); |
- |
- if (y == commonElements.objectClass) return true; |
- if (x == commonElements.objectClass) return false; |
- while (x != null && x.hierarchyDepth >= y.hierarchyDepth) { |
- if (x == y) return true; |
- x = x.superclass; |
- } |
- return false; |
- } |
+ bool _checkClass(ClassEntity cls); |
@override |
bool isInstantiated(ClassEntity cls) { |
@@ -732,13 +691,275 @@ class ClosedWorldImpl implements ClosedWorld, ClosedWorldRefiner { |
return classSet != null ? classSet.getLubOfInstantiatedSubtypes() : null; |
} |
+ Set<ClassEntity> _commonContainedClasses(ClassEntity cls1, ClassQuery query1, |
+ ClassEntity cls2, ClassQuery query2) { |
+ Iterable<ClassEntity> xSubset = _containedSubset(cls1, query1); |
+ if (xSubset == null) return null; |
+ Iterable<ClassEntity> ySubset = _containedSubset(cls2, query2); |
+ if (ySubset == null) return null; |
+ return xSubset.toSet().intersection(ySubset.toSet()); |
+ } |
+ |
+ Iterable<ClassEntity> _containedSubset(ClassEntity cls, ClassQuery query) { |
+ switch (query) { |
+ case ClassQuery.EXACT: |
+ return null; |
+ case ClassQuery.SUBCLASS: |
+ return strictSubclassesOf(cls); |
+ case ClassQuery.SUBTYPE: |
+ return strictSubtypesOf(cls); |
+ } |
+ throw new ArgumentError('Unexpected query: $query.'); |
+ } |
+ |
+ /// Returns `true` if [cls] is mixed into a live class. |
+ bool isUsedAsMixin(ClassEntity cls) { |
+ return !mixinUsesOf(cls).isEmpty; |
+ } |
+ |
+ /// Returns `true` if any live class that mixes in [cls] implements [type]. |
+ bool hasAnySubclassOfMixinUseThatImplements( |
+ ClassEntity cls, ClassEntity type) { |
+ return mixinUsesOf(cls) |
+ .any((use) => hasAnySubclassThatImplements(use, type)); |
+ } |
+ |
+ /// Returns `true` if every subtype of [x] is a subclass of [y] or a subclass |
+ /// of a mixin application of [y]. |
+ bool everySubtypeIsSubclassOfOrMixinUseOf(ClassEntity x, ClassEntity y) { |
+ assert(_checkClass(x)); |
+ assert(_checkClass(y)); |
+ Map<ClassEntity, bool> secondMap = |
+ _subtypeCoveredByCache[x] ??= <ClassEntity, bool>{}; |
+ return secondMap[y] ??= subtypesOf(x).every((ClassEntity cls) => |
+ isSubclassOf(cls, y) || isSubclassOfMixinUseOf(cls, y)); |
+ } |
+ |
+ /// Returns `true` if any subclass of [superclass] implements [type]. |
+ bool hasAnySubclassThatImplements(ClassEntity superclass, ClassEntity type) { |
+ assert(_checkClass(superclass)); |
+ Set<ClassEntity> subclasses = _typesImplementedBySubclasses[superclass]; |
+ if (subclasses == null) return false; |
+ return subclasses.contains(type); |
+ } |
+ |
+ /// Returns whether a [selector] call on an instance of [cls] |
+ /// will hit a method at runtime, and not go through [noSuchMethod]. |
+ bool hasConcreteMatch(ClassEntity cls, Selector selector, |
+ {ClassEntity stopAtSuperclass}); |
+ |
+ @override |
+ bool needsNoSuchMethod( |
+ ClassEntity base, Selector selector, ClassQuery query) { |
+ /// Returns `true` if subclasses in the [rootNode] tree needs noSuchMethod |
+ /// handling. |
+ bool subclassesNeedNoSuchMethod(ClassHierarchyNode rootNode) { |
+ if (!rootNode.isInstantiated) { |
+ // No subclass needs noSuchMethod handling since they are all |
+ // uninstantiated. |
+ return false; |
+ } |
+ ClassEntity rootClass = rootNode.cls; |
+ if (hasConcreteMatch(rootClass, selector)) { |
+ // The root subclass has a concrete implementation so no subclass needs |
+ // noSuchMethod handling. |
+ return false; |
+ } else if (rootNode.isExplicitlyInstantiated) { |
+ // The root class need noSuchMethod handling. |
+ return true; |
+ } |
+ IterationStep result = rootNode.forEachSubclass((ClassEntity subclass) { |
+ if (hasConcreteMatch(subclass, selector, stopAtSuperclass: rootClass)) { |
+ // Found a match - skip all subclasses. |
+ return IterationStep.SKIP_SUBCLASSES; |
+ } else { |
+ // Stop fast - we found a need for noSuchMethod handling. |
+ return IterationStep.STOP; |
+ } |
+ }, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, strict: true); |
+ // We stopped fast so we need noSuchMethod handling. |
+ return result == IterationStep.STOP; |
+ } |
+ |
+ ClassSet classSet = getClassSet(base); |
+ ClassHierarchyNode node = classSet.node; |
+ if (query == ClassQuery.EXACT) { |
+ return node.isExplicitlyInstantiated && !hasConcreteMatch(base, selector); |
+ } else if (query == ClassQuery.SUBCLASS) { |
+ return subclassesNeedNoSuchMethod(node); |
+ } else { |
+ if (subclassesNeedNoSuchMethod(node)) return true; |
+ for (ClassHierarchyNode subtypeNode in classSet.subtypeNodes) { |
+ if (subclassesNeedNoSuchMethod(subtypeNode)) return true; |
+ } |
+ return false; |
+ } |
+ } |
+ |
+ /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies |
+ /// of known classes. |
+ /// |
+ /// This method is only provided for testing. For queries on classes, use the |
+ /// methods defined in [ClosedWorld]. |
+ ClassHierarchyNode getClassHierarchyNode(ClassEntity cls) { |
+ assert(_checkClass(cls)); |
+ return _classHierarchyNodes[cls]; |
+ } |
+ |
+ /// Returns [ClassSet] for [cls] used to model the extends and implements |
+ /// relations of known classes. |
+ /// |
+ /// This method is only provided for testing. For queries on classes, use the |
+ /// methods defined in [ClosedWorld]. |
+ ClassSet getClassSet(ClassEntity cls) { |
+ assert(_checkClass(cls)); |
+ return _classSets[cls]; |
+ } |
+ |
+ Iterable<TypedefElement> get allTypedefs => _allTypedefs; |
+ |
+ bool hasAnyUserDefinedGetter(Selector selector, TypeMask mask) { |
+ return allFunctions.filter(selector, mask).any((each) => each.isGetter); |
+ } |
+ |
+ FieldEntity locateSingleField(Selector selector, TypeMask mask) { |
+ MemberEntity result = locateSingleElement(selector, mask); |
+ return (result != null && result.isField) ? result : null; |
+ } |
+ |
+ MemberEntity locateSingleElement(Selector selector, TypeMask mask) { |
+ mask ??= commonMasks.dynamicType; |
+ return mask.locateSingleElement(selector, this); |
+ } |
+ |
+ TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask) { |
+ bool canReachAll = true; |
+ if (mask != null) { |
+ canReachAll = _backend.backendUsage.isInvokeOnUsed && |
+ mask.needsNoSuchMethodHandling(selector, this); |
+ } |
+ return canReachAll ? commonMasks.dynamicType : mask; |
+ } |
+ |
+ bool fieldNeverChanges(MemberEntity element) { |
+ if (!element.isField) return false; |
+ if (nativeData.isNativeMember(element)) { |
+ // Some native fields are views of data that may be changed by operations. |
+ // E.g. node.firstChild depends on parentNode.removeBefore(n1, n2). |
+ // TODO(sra): Refine the effect classification so that native effects are |
+ // distinct from ordinary Dart effects. |
+ return false; |
+ } |
+ |
+ if (!element.isAssignable) { |
+ return true; |
+ } |
+ if (element.isInstanceMember) { |
+ return !_resolverWorld.hasInvokedSetter(element) && |
+ !_resolverWorld.fieldSetters.contains(element); |
+ } |
+ return false; |
+ } |
+ |
+ SideEffects getSideEffectsOfSelector(Selector selector, TypeMask mask) { |
+ // We're not tracking side effects of closures. |
+ if (selector.isClosureCall) return new SideEffects(); |
+ SideEffects sideEffects = new SideEffects.empty(); |
+ for (MemberElement e in allFunctions.filter(selector, mask)) { |
+ if (e.isField) { |
+ if (selector.isGetter) { |
+ if (!fieldNeverChanges(e)) { |
+ sideEffects.setDependsOnInstancePropertyStore(); |
+ } |
+ } else if (selector.isSetter) { |
+ sideEffects.setChangesInstanceProperty(); |
+ } else { |
+ assert(selector.isCall); |
+ sideEffects.setAllSideEffects(); |
+ sideEffects.setDependsOnSomething(); |
+ } |
+ } else { |
+ sideEffects.add(getSideEffectsOfElement(e)); |
+ } |
+ } |
+ return sideEffects; |
+ } |
+} |
+ |
+class ClosedWorldImpl extends ClosedWorldBase { |
+ ClosedWorldImpl( |
+ {JavaScriptBackend backend, |
+ CommonElements commonElements, |
+ ResolutionWorldBuilder resolutionWorldBuilder, |
+ FunctionSetBuilder functionSetBuilder, |
+ Iterable<TypedefElement> allTypedefs, |
+ Map<ClassEntity, Set<ClassEntity>> mixinUses, |
+ Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses, |
+ Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes, |
+ Map<ClassEntity, ClassSet> classSets}) |
+ : super( |
+ backend: backend, |
+ commonElements: commonElements, |
+ resolutionWorldBuilder: resolutionWorldBuilder, |
+ functionSetBuilder: functionSetBuilder, |
+ allTypedefs: allTypedefs, |
+ mixinUses: mixinUses, |
+ typesImplementedBySubclasses: typesImplementedBySubclasses, |
+ classHierarchyNodes: classHierarchyNodes, |
+ classSets: classSets); |
+ |
+ bool _checkClass(ClassElement cls) => cls.isDeclaration; |
+ |
+ bool _checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) { |
+ return invariant(cls, cls.isDeclaration, |
+ message: '$cls must be the declaration.') && |
+ invariant(cls, cls.isResolved, |
+ message: |
+ '$cls must be resolved.') /* && |
+ // TODO(johnniwinther): Reinsert this or similar invariant. Currently |
+ // various call sites use uninstantiated classes for isSubtypeOf or |
+ // isSubclassOf. Some are valid, some are not. Work out better invariants |
+ // to catch the latter. |
+ (!mustBeInstantiated || |
+ invariant(cls, isInstantiated(cls), |
+ message: '$cls is not instantiated.'))*/ |
+ ; |
+ } |
+ |
+ /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an |
+ /// instance of [y]. |
+ bool isSubtypeOf(ClassElement x, ClassElement y) { |
+ assert(_checkInvariants(x)); |
+ assert(_checkInvariants(y, mustBeInstantiated: false)); |
+ |
+ if (y == commonElements.objectClass) return true; |
+ if (x == commonElements.objectClass) return false; |
+ if (x.asInstanceOf(y) != null) return true; |
+ if (y != commonElements.functionClass) return false; |
+ return x.callType != null; |
+ } |
+ |
+ /// Return `true` if [x] is a (non-strict) subclass of [y]. |
+ bool isSubclassOf(ClassElement x, ClassElement y) { |
+ assert(_checkInvariants(x)); |
+ assert(_checkInvariants(y)); |
+ |
+ if (y == commonElements.objectClass) return true; |
+ if (x == commonElements.objectClass) return false; |
+ while (x != null && x.hierarchyDepth >= y.hierarchyDepth) { |
+ if (x == y) return true; |
+ x = x.superclass; |
+ } |
+ return false; |
+ } |
+ |
/// Returns an iterable over the common supertypes of the [classes]. |
Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes) { |
Iterator<ClassElement> iterator = classes.iterator; |
if (!iterator.moveNext()) return const <ClassElement>[]; |
ClassElement cls = iterator.current; |
- assert(checkInvariants(cls)); |
+ assert(_checkInvariants(cls)); |
OrderedTypeSet typeSet = cls.allSupertypesAndSelf; |
if (!iterator.moveNext()) return typeSet.types.map((type) => type.element); |
@@ -746,7 +967,7 @@ class ClosedWorldImpl implements ClosedWorld, ClosedWorldRefiner { |
Link<OrderedTypeSet> otherTypeSets = const Link<OrderedTypeSet>(); |
do { |
ClassElement otherClass = iterator.current; |
- assert(checkInvariants(otherClass)); |
+ assert(_checkInvariants(otherClass)); |
OrderedTypeSet otherTypeSet = otherClass.allSupertypesAndSelf; |
otherTypeSets = otherTypeSets.prepend(otherTypeSet); |
if (otherTypeSet.maxDepth < depth) { |
@@ -804,27 +1025,6 @@ class ClosedWorldImpl implements ClosedWorld, ClosedWorldRefiner { |
}); |
} |
- Set<ClassEntity> _commonContainedClasses(ClassEntity cls1, ClassQuery query1, |
- ClassEntity cls2, ClassQuery query2) { |
- Iterable<ClassEntity> xSubset = _containedSubset(cls1, query1); |
- if (xSubset == null) return null; |
- Iterable<ClassEntity> ySubset = _containedSubset(cls2, query2); |
- if (ySubset == null) return null; |
- return xSubset.toSet().intersection(ySubset.toSet()); |
- } |
- |
- Iterable<ClassEntity> _containedSubset(ClassEntity cls, ClassQuery query) { |
- switch (query) { |
- case ClassQuery.EXACT: |
- return null; |
- case ClassQuery.SUBCLASS: |
- return strictSubclassesOf(cls); |
- case ClassQuery.SUBTYPE: |
- return strictSubtypesOf(cls); |
- } |
- throw new ArgumentError('Unexpected query: $query.'); |
- } |
- |
/// Returns an iterable over the live mixin applications that mixin [cls]. |
Iterable<ClassEntity> mixinUsesOf(ClassEntity cls) { |
if (_liveMixinUses == null) { |
@@ -853,18 +1053,6 @@ class ClosedWorldImpl implements ClosedWorld, ClosedWorldRefiner { |
return uses != null ? uses : const <ClassEntity>[]; |
} |
- /// Returns `true` if [cls] is mixed into a live class. |
- bool isUsedAsMixin(ClassEntity cls) { |
- return !mixinUsesOf(cls).isEmpty; |
- } |
- |
- /// Returns `true` if any live class that mixes in [cls] implements [type]. |
- bool hasAnySubclassOfMixinUseThatImplements( |
- ClassEntity cls, ClassEntity type) { |
- return mixinUsesOf(cls) |
- .any((use) => hasAnySubclassThatImplements(use, type)); |
- } |
- |
/// Returns `true` if any live class that mixes in [mixin] is also a subclass |
/// of [superclass]. |
bool hasAnySubclassThatMixes(ClassEntity superclass, ClassEntity mixin) { |
@@ -890,25 +1078,6 @@ class ClosedWorldImpl implements ClosedWorld, ClosedWorldRefiner { |
return false; |
} |
- /// Returns `true` if every subtype of [x] is a subclass of [y] or a subclass |
- /// of a mixin application of [y]. |
- bool everySubtypeIsSubclassOfOrMixinUseOf(ClassEntity x, ClassEntity y) { |
- assert(_checkClass(x)); |
- assert(_checkClass(y)); |
- Map<ClassEntity, bool> secondMap = |
- _subtypeCoveredByCache[x] ??= <ClassEntity, bool>{}; |
- return secondMap[y] ??= subtypesOf(x).every((ClassEntity cls) => |
- isSubclassOf(cls, y) || isSubclassOfMixinUseOf(cls, y)); |
- } |
- |
- /// Returns `true` if any subclass of [superclass] implements [type]. |
- bool hasAnySubclassThatImplements(ClassEntity superclass, ClassEntity type) { |
- assert(_checkClass(superclass)); |
- Set<ClassEntity> subclasses = _typesImplementedBySubclasses[superclass]; |
- if (subclasses == null) return false; |
- return subclasses.contains(type); |
- } |
- |
@override |
bool hasElementIn(ClassEntity cls, Selector selector, Element element) { |
// Use [:implementation:] of [element] |
@@ -943,74 +1112,6 @@ class ClosedWorldImpl implements ClosedWorld, ClosedWorldRefiner { |
return selector.appliesUntyped(element); |
} |
- @override |
- bool needsNoSuchMethod( |
- ClassElement base, Selector selector, ClassQuery query) { |
- /// Returns `true` if subclasses in the [rootNode] tree needs noSuchMethod |
- /// handling. |
- bool subclassesNeedNoSuchMethod(ClassHierarchyNode rootNode) { |
- if (!rootNode.isInstantiated) { |
- // No subclass needs noSuchMethod handling since they are all |
- // uninstantiated. |
- return false; |
- } |
- ClassElement rootClass = rootNode.cls; |
- if (hasConcreteMatch(rootClass, selector)) { |
- // The root subclass has a concrete implementation so no subclass needs |
- // noSuchMethod handling. |
- return false; |
- } else if (rootNode.isExplicitlyInstantiated) { |
- // The root class need noSuchMethod handling. |
- return true; |
- } |
- IterationStep result = rootNode.forEachSubclass((ClassElement subclass) { |
- if (hasConcreteMatch(subclass, selector, stopAtSuperclass: rootClass)) { |
- // Found a match - skip all subclasses. |
- return IterationStep.SKIP_SUBCLASSES; |
- } else { |
- // Stop fast - we found a need for noSuchMethod handling. |
- return IterationStep.STOP; |
- } |
- }, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, strict: true); |
- // We stopped fast so we need noSuchMethod handling. |
- return result == IterationStep.STOP; |
- } |
- |
- ClassSet classSet = getClassSet(base); |
- ClassHierarchyNode node = classSet.node; |
- if (query == ClassQuery.EXACT) { |
- return node.isExplicitlyInstantiated && !hasConcreteMatch(base, selector); |
- } else if (query == ClassQuery.SUBCLASS) { |
- return subclassesNeedNoSuchMethod(node); |
- } else { |
- if (subclassesNeedNoSuchMethod(node)) return true; |
- for (ClassHierarchyNode subtypeNode in classSet.subtypeNodes) { |
- if (subclassesNeedNoSuchMethod(subtypeNode)) return true; |
- } |
- return false; |
- } |
- } |
- |
- /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies |
- /// of known classes. |
- /// |
- /// This method is only provided for testing. For queries on classes, use the |
- /// methods defined in [ClosedWorld]. |
- ClassHierarchyNode getClassHierarchyNode(ClassEntity cls) { |
- assert(_checkClass(cls)); |
- return _classHierarchyNodes[cls]; |
- } |
- |
- /// Returns [ClassSet] for [cls] used to model the extends and implements |
- /// relations of known classes. |
- /// |
- /// This method is only provided for testing. For queries on classes, use the |
- /// methods defined in [ClosedWorld]. |
- ClassSet getClassSet(ClassEntity cls) { |
- assert(_checkClass(cls)); |
- return _classSets[cls]; |
- } |
- |
void registerClosureClass(ClosureClassElement cls) { |
ClassHierarchyNode parentNode = getClassHierarchyNode(cls.superclass); |
ClassHierarchyNode node = _classHierarchyNodes[cls] = |
@@ -1038,8 +1139,6 @@ class ClosedWorldImpl implements ClosedWorld, ClosedWorldRefiner { |
} |
} |
- Iterable<TypedefElement> get allTypedefs => _allTypedefs; |
- |
@override |
String dump([ClassElement cls]) { |
StringBuffer sb = new StringBuffer(); |
@@ -1053,57 +1152,6 @@ class ClosedWorldImpl implements ClosedWorld, ClosedWorldRefiner { |
return sb.toString(); |
} |
- bool hasAnyUserDefinedGetter(Selector selector, TypeMask mask) { |
- return allFunctions.filter(selector, mask).any((each) => each.isGetter); |
- } |
- |
- FieldElement locateSingleField(Selector selector, TypeMask mask) { |
- Element result = locateSingleElement(selector, mask); |
- return (result != null && result.isField) ? result : null; |
- } |
- |
- MemberElement locateSingleElement(Selector selector, TypeMask mask) { |
- mask ??= commonMasks.dynamicType; |
- return mask.locateSingleElement(selector, this); |
- } |
- |
- TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask) { |
- bool canReachAll = true; |
- if (mask != null) { |
- canReachAll = _backend.backendUsage.isInvokeOnUsed && |
- mask.needsNoSuchMethodHandling(selector, this); |
- } |
- return canReachAll ? commonMasks.dynamicType : mask; |
- } |
- |
- void addFunctionCalledInLoop(Element element) { |
- functionsCalledInLoop.add(element.declaration); |
- } |
- |
- bool isCalledInLoop(Element element) { |
- return functionsCalledInLoop.contains(element.declaration); |
- } |
- |
- bool fieldNeverChanges(MemberElement element) { |
- if (!element.isField) return false; |
- if (nativeData.isNativeMember(element)) { |
- // Some native fields are views of data that may be changed by operations. |
- // E.g. node.firstChild depends on parentNode.removeBefore(n1, n2). |
- // TODO(sra): Refine the effect classification so that native effects are |
- // distinct from ordinary Dart effects. |
- return false; |
- } |
- |
- if (element.isFinal || element.isConst) { |
- return true; |
- } |
- if (element.isInstanceMember) { |
- return !_resolverWorld.hasInvokedSetter(element) && |
- !_resolverWorld.fieldSetters.contains(element); |
- } |
- return false; |
- } |
- |
SideEffects getSideEffectsOfElement(Element element) { |
// The type inferrer (where the side effects are being computed), |
// does not see generative constructor bodies because they are |
@@ -1133,28 +1181,12 @@ class ClosedWorldImpl implements ClosedWorld, ClosedWorldRefiner { |
sideEffectsFreeElements.add(element); |
} |
- SideEffects getSideEffectsOfSelector(Selector selector, TypeMask mask) { |
- // We're not tracking side effects of closures. |
- if (selector.isClosureCall) return new SideEffects(); |
- SideEffects sideEffects = new SideEffects.empty(); |
- for (MemberElement e in allFunctions.filter(selector, mask)) { |
- if (e.isField) { |
- if (selector.isGetter) { |
- if (!fieldNeverChanges(e)) { |
- sideEffects.setDependsOnInstancePropertyStore(); |
- } |
- } else if (selector.isSetter) { |
- sideEffects.setChangesInstanceProperty(); |
- } else { |
- assert(selector.isCall); |
- sideEffects.setAllSideEffects(); |
- sideEffects.setDependsOnSomething(); |
- } |
- } else { |
- sideEffects.add(getSideEffectsOfElement(e)); |
- } |
- } |
- return sideEffects; |
+ void addFunctionCalledInLoop(Element element) { |
+ functionsCalledInLoop.add(element.declaration); |
+ } |
+ |
+ bool isCalledInLoop(Element element) { |
+ return functionsCalledInLoop.contains(element.declaration); |
} |
void registerCannotThrow(Element element) { |