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

Unified Diff: pkg/compiler/lib/src/world.dart

Issue 2813503005: Extract ClosedWorldBase from ClosedWorldImpl (Closed)
Patch Set: Updated invariant comment. Created 3 years, 8 months 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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) {
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698