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

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

Issue 2318593003: Split Universe into ResolutionUniverse and CodegenUniverse (Closed)
Patch Set: Updated cf. comments. Created 4 years, 3 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 | « pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/universe/universe.dart
diff --git a/pkg/compiler/lib/src/universe/universe.dart b/pkg/compiler/lib/src/universe/universe.dart
index cb574bb95bc1e63a40c944025f9d4ea6a90f156a..55a47641507f88b0697f8dec2dba2f0ca45b6612 100644
--- a/pkg/compiler/lib/src/universe/universe.dart
+++ b/pkg/compiler/lib/src/universe/universe.dart
@@ -106,8 +106,62 @@ abstract class SelectorConstraintsStrategy {
/// [ClassWorld]. The concepts here and in [ClassWorld] are very similar -- in
/// the same way that the "universe expands" you can think of this as a mutable
/// world that is expanding as we visit and discover parts of the program.
-/// TODO(sigmund): rename to "growing/expanding/mutable world"?
-class Universe {
+// TODO(sigmund): rename to "growing/expanding/mutable world"?
+// TODO(johnniwinther): Move common implementation to a [UniverseBase] when
+// universes and worlds have been unified.
+abstract class Universe {
+ /// All directly instantiated classes, that is, classes with a generative
+ /// constructor that has been called directly and not only through a
+ /// super-call.
+ // TODO(johnniwinther): Improve semantic precision.
+ Iterable<ClassElement> get directlyInstantiatedClasses;
+
+ /// All types that are checked either through is, as or checked mode checks.
+ Iterable<DartType> get isChecks;
+
+ /// Registers that [type] is checked in this universe. The unaliased type is
+ /// returned.
+ DartType registerIsCheck(DartType type, Compiler compiler);
+
+ /// All directly instantiated types, that is, the types of the directly
+ /// instantiated classes.
+ // TODO(johnniwinther): Improve semantic precision.
+ Iterable<DartType> get instantiatedTypes;
+
+ /// Returns `true` if [member] is invoked as a setter.
+ bool hasInvokedSetter(Element member, World world);
+}
+
+abstract class ResolutionUniverse implements Universe {
+ /// Set of (live) local functions (closures) whose signatures reference type
+ /// variables.
+ ///
+ /// A live function is one whose enclosing member function has been enqueued.
+ Set<Element> get closuresWithFreeTypeVariables;
+
+ /// Set of (live) `call` methods whose signatures reference type variables.
+ ///
+ /// A live `call` method is one whose enclosing class has been instantiated.
+ Iterable<Element> get callMethodsWithFreeTypeVariables;
+
+ /// Set of all closures in the program. Used by the mirror tracking system
+ /// to find all live closure instances.
+ Iterable<LocalFunctionElement> get allClosures;
+
+ /// Set of methods in instantiated classes that are potentially closurized.
+ Iterable<Element> get closurizedMembers;
+
+ /// Returns `true` if [cls] is considered to be implemented by an
+ /// instantiated class, either directly, through subclasses or through
+ /// subtypes. The latter case only contains spurious information from
+ /// instantiations through factory constructors and mixins.
+ bool isImplemented(ClassElement cls);
+
+ /// Set of all fields that are statically known to be written to.
+ Iterable<Element> get fieldSetters;
+}
+
+class ResolutionUniverseImpl implements ResolutionUniverse {
/// The set of all directly instantiated classes, that is, classes with a
/// generative constructor that has been called directly and not only through
/// a super-call.
@@ -137,8 +191,6 @@ class Universe {
*
* Invariant: Elements are declaration elements.
*/
- final Set<FunctionElement> staticFunctionsNeedingGetter =
- new Set<FunctionElement>();
final Set<FunctionElement> methodsNeedingSuperGetter =
new Set<FunctionElement>();
final Map<String, Map<Selector, SelectorConstraints>> _invokedNames =
@@ -148,16 +200,7 @@ class Universe {
final Map<String, Map<Selector, SelectorConstraints>> _invokedSetters =
<String, Map<Selector, SelectorConstraints>>{};
- /**
- * Fields accessed. Currently only the codegen knows this
- * information. The resolver is too conservative when seeing a
- * getter and only registers an invoked getter.
- */
- final Set<Element> fieldGetters = new Set<Element>();
-
- /**
- * Fields set. See comment in [fieldGetters].
- */
+ /// Fields set.
final Set<Element> fieldSetters = new Set<Element>();
final Set<DartType> isChecks = new Set<DartType>();
@@ -190,7 +233,7 @@ class Universe {
final SelectorConstraintsStrategy selectorConstraintsStrategy;
- Universe(this.selectorConstraintsStrategy);
+ ResolutionUniverseImpl(this.selectorConstraintsStrategy);
/// All directly instantiated classes, that is, classes with a generative
/// constructor that has been called directly and not only through a
@@ -307,6 +350,246 @@ class Universe {
return constraints.addReceiverConstraint(mask);
}
+ DartType registerIsCheck(DartType type, Compiler compiler) {
+ type.computeUnaliased(compiler.resolution);
+ type = type.unaliased;
+ // Even in checked mode, type annotations for return type and argument
+ // types do not imply type checks, so there should never be a check
+ // against the type variable of a typedef.
+ isChecks.add(type);
+ return type;
+ }
+
+ void registerStaticUse(StaticUse staticUse) {
+ Element element = staticUse.element;
+ if (Elements.isStaticOrTopLevel(element) && element.isField) {
+ allReferencedStaticFields.add(element);
+ }
+ switch (staticUse.kind) {
+ case StaticUseKind.SUPER_FIELD_SET:
+ case StaticUseKind.FIELD_SET:
+ fieldSetters.add(element);
+ break;
+ case StaticUseKind.SUPER_TEAR_OFF:
+ methodsNeedingSuperGetter.add(element);
+ break;
+ case StaticUseKind.GENERAL:
+ case StaticUseKind.STATIC_TEAR_OFF:
+ case StaticUseKind.FIELD_GET:
+ break;
+ case StaticUseKind.CLOSURE:
+ allClosures.add(element);
+ break;
+ }
+ }
+
+ void forgetElement(Element element, Compiler compiler) {
+ allClosures.remove(element);
+ slowDirectlyNestedClosures(element).forEach(compiler.forgetElement);
+ closurizedMembers.remove(element);
+ fieldSetters.remove(element);
+ _directlyInstantiatedClasses.remove(element);
+ if (element is ClassElement) {
+ assert(invariant(element, element.thisType.isRaw,
+ message: 'Generic classes not supported (${element.thisType}).'));
+ _instantiatedTypes..remove(element.rawType)..remove(element.thisType);
+ }
+ }
+
+ // TODO(ahe): Replace this method with something that is O(1), for example,
+ // by using a map.
+ List<LocalFunctionElement> slowDirectlyNestedClosures(Element element) {
+ // Return new list to guard against concurrent modifications.
+ return new List<LocalFunctionElement>.from(
+ allClosures.where((LocalFunctionElement closure) {
+ return closure.executableContext == element;
+ }));
+ }
+}
+
+/// Universe specific to codegen.
+///
+/// This adds additional access to liveness of selectors and elements.
+abstract class CodegenUniverse implements Universe {
+ void forEachInvokedName(
+ f(String name, Map<Selector, SelectorConstraints> selectors));
+
+ void forEachInvokedGetter(
+ f(String name, Map<Selector, SelectorConstraints> selectors));
+
+ void forEachInvokedSetter(
+ f(String name, Map<Selector, SelectorConstraints> selectors));
+
+ bool hasInvokedGetter(Element member, World world);
+
+ Map<Selector, SelectorConstraints> invocationsByName(String name);
+
+ Map<Selector, SelectorConstraints> getterInvocationsByName(String name);
+
+ Map<Selector, SelectorConstraints> setterInvocationsByName(String name);
+
+ Iterable<FunctionElement> get staticFunctionsNeedingGetter;
+ Iterable<FunctionElement> get methodsNeedingSuperGetter;
+
+ /// The set of all referenced static fields.
+ ///
+ /// Invariant: Elements are declaration elements.
+ Iterable<FieldElement> get allReferencedStaticFields;
+}
+
+class CodegenUniverseImpl implements CodegenUniverse {
+ /// The set of all directly instantiated classes, that is, classes with a
+ /// generative constructor that has been called directly and not only through
+ /// a super-call.
+ ///
+ /// Invariant: Elements are declaration elements.
+ // TODO(johnniwinther): [_directlyInstantiatedClasses] and
+ // [_instantiatedTypes] sets should be merged.
+ final Set<ClassElement> _directlyInstantiatedClasses =
+ new Set<ClassElement>();
+
+ /// The set of all directly instantiated types, that is, the types of the
+ /// directly instantiated classes.
+ ///
+ /// See [_directlyInstantiatedClasses].
+ final Set<DartType> _instantiatedTypes = new Set<DartType>();
+
+ /// Classes implemented by directly instantiated classes.
+ final Set<ClassElement> _implementedClasses = new Set<ClassElement>();
+
+ /// The set of all referenced static fields.
+ ///
+ /// Invariant: Elements are declaration elements.
+ final Set<FieldElement> allReferencedStaticFields = new Set<FieldElement>();
+
+ /**
+ * Documentation wanted -- johnniwinther
+ *
+ * Invariant: Elements are declaration elements.
+ */
+ final Set<FunctionElement> staticFunctionsNeedingGetter =
+ new Set<FunctionElement>();
+ final Set<FunctionElement> methodsNeedingSuperGetter =
+ new Set<FunctionElement>();
+ final Map<String, Map<Selector, SelectorConstraints>> _invokedNames =
+ <String, Map<Selector, SelectorConstraints>>{};
+ final Map<String, Map<Selector, SelectorConstraints>> _invokedGetters =
+ <String, Map<Selector, SelectorConstraints>>{};
+ final Map<String, Map<Selector, SelectorConstraints>> _invokedSetters =
+ <String, Map<Selector, SelectorConstraints>>{};
+
+ final Set<DartType> isChecks = new Set<DartType>();
+
+ final SelectorConstraintsStrategy selectorConstraintsStrategy;
+
+ CodegenUniverseImpl(this.selectorConstraintsStrategy);
+
+ /// All directly instantiated classes, that is, classes with a generative
+ /// constructor that has been called directly and not only through a
+ /// super-call.
+ // TODO(johnniwinther): Improve semantic precision.
+ Iterable<ClassElement> get directlyInstantiatedClasses {
+ return _directlyInstantiatedClasses;
+ }
+
+ /// All directly instantiated types, that is, the types of the directly
+ /// instantiated classes.
+ ///
+ /// See [directlyInstantiatedClasses].
+ // TODO(johnniwinther): Improve semantic precision.
+ Iterable<DartType> get instantiatedTypes => _instantiatedTypes;
+
+ /// Register [type] as (directly) instantiated.
+ ///
+ /// If [byMirrors] is `true`, the instantiation is through mirrors.
+ // TODO(johnniwinther): Fully enforce the separation between exact, through
+ // subclass and through subtype instantiated types/classes.
+ // TODO(johnniwinther): Support unknown type arguments for generic types.
+ void registerTypeInstantiation(InterfaceType type,
+ {bool byMirrors: false,
+ bool isNative: false,
+ void onImplemented(ClassElement cls)}) {
+ _instantiatedTypes.add(type);
+ ClassElement cls = type.element;
+ if (!cls.isAbstract
+ // We can't use the closed-world assumption with native abstract
+ // classes; a native abstract class may have non-abstract subclasses
+ // not declared to the program. Instances of these classes are
+ // indistinguishable from the abstract class.
+ ||
+ isNative
+ // Likewise, if this registration comes from the mirror system,
+ // all bets are off.
+ // TODO(herhut): Track classes required by mirrors seperately.
+ ||
+ byMirrors) {
+ _directlyInstantiatedClasses.add(cls);
+ }
+
+ // TODO(johnniwinther): Replace this by separate more specific mappings that
+ // include the type arguments.
+ if (_implementedClasses.add(cls)) {
+ onImplemented(cls);
+ cls.allSupertypes.forEach((InterfaceType supertype) {
+ if (_implementedClasses.add(supertype.element)) {
+ onImplemented(supertype.element);
+ }
+ });
+ }
+ }
+
+ bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors,
+ Element member, World world) {
+ if (selectors == null) return false;
+ for (Selector selector in selectors.keys) {
+ if (selector.appliesUnnamed(member, world)) {
+ SelectorConstraints masks = selectors[selector];
+ if (masks.applies(member, selector, world)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ bool hasInvocation(Element member, World world) {
+ return _hasMatchingSelector(_invokedNames[member.name], member, world);
+ }
+
+ bool hasInvokedGetter(Element member, World world) {
+ return _hasMatchingSelector(_invokedGetters[member.name], member, world) ||
+ member.isFunction && methodsNeedingSuperGetter.contains(member);
+ }
+
+ bool hasInvokedSetter(Element member, World world) {
+ return _hasMatchingSelector(_invokedSetters[member.name], member, world);
+ }
+
+ bool registerDynamicUse(DynamicUse dynamicUse) {
+ switch (dynamicUse.kind) {
+ case DynamicUseKind.INVOKE:
+ return _registerNewSelector(dynamicUse, _invokedNames);
+ case DynamicUseKind.GET:
+ return _registerNewSelector(dynamicUse, _invokedGetters);
+ case DynamicUseKind.SET:
+ return _registerNewSelector(dynamicUse, _invokedSetters);
+ }
+ }
+
+ bool _registerNewSelector(DynamicUse dynamicUse,
+ Map<String, Map<Selector, SelectorConstraints>> selectorMap) {
+ Selector selector = dynamicUse.selector;
+ String name = selector.name;
+ ReceiverConstraint mask = dynamicUse.mask;
+ Map<Selector, SelectorConstraints> selectors = selectorMap.putIfAbsent(
+ name, () => new Maplet<Selector, SelectorConstraints>());
+ UniverseSelectorConstraints constraints =
+ selectors.putIfAbsent(selector, () {
+ return selectorConstraintsStrategy.createSelectorConstraints(selector);
+ });
+ return constraints.addReceiverConstraint(mask);
+ }
+
Map<Selector, SelectorConstraints> _asUnmodifiable(
Map<Selector, SelectorConstraints> map) {
if (map == null) return null;
@@ -359,30 +642,19 @@ class Universe {
case StaticUseKind.STATIC_TEAR_OFF:
staticFunctionsNeedingGetter.add(element);
break;
- case StaticUseKind.FIELD_GET:
- fieldGetters.add(element);
- break;
- case StaticUseKind.SUPER_FIELD_SET:
- case StaticUseKind.FIELD_SET:
- fieldSetters.add(element);
- break;
case StaticUseKind.SUPER_TEAR_OFF:
methodsNeedingSuperGetter.add(element);
break;
+ case StaticUseKind.SUPER_FIELD_SET:
+ case StaticUseKind.FIELD_SET:
case StaticUseKind.GENERAL:
- break;
case StaticUseKind.CLOSURE:
- allClosures.add(element);
+ case StaticUseKind.FIELD_GET:
break;
}
}
void forgetElement(Element element, Compiler compiler) {
- allClosures.remove(element);
- slowDirectlyNestedClosures(element).forEach(compiler.forgetElement);
- closurizedMembers.remove(element);
- fieldSetters.remove(element);
- fieldGetters.remove(element);
_directlyInstantiatedClasses.remove(element);
if (element is ClassElement) {
assert(invariant(element, element.thisType.isRaw,
@@ -390,14 +662,4 @@ class Universe {
_instantiatedTypes..remove(element.rawType)..remove(element.thisType);
}
}
-
- // TODO(ahe): Replace this method with something that is O(1), for example,
- // by using a map.
- List<LocalFunctionElement> slowDirectlyNestedClosures(Element element) {
- // Return new list to guard against concurrent modifications.
- return new List<LocalFunctionElement>.from(
- allClosures.where((LocalFunctionElement closure) {
- return closure.executableContext == element;
- }));
- }
}
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698