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

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

Issue 2314703002: Split World usage into open, inference, and closed world. (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/universe/function_set.dart ('k') | tests/compiler/dart2js/class_set_test.dart » ('j') | 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 87090deb797ef77020dc2caf090676d0e593a610..6ce4b16ccc34c0a5acaba7ce20bacf790ea1591e 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -19,7 +19,7 @@ import 'elements/elements.dart'
TypedefElement,
VariableElement;
import 'ordered_typeset.dart';
-import 'types/masks.dart' show TypeMask, FlatTypeMask;
+import 'types/masks.dart' show CommonMasks, FlatTypeMask, TypeMask;
import 'universe/class_set.dart';
import 'universe/function_set.dart' show FunctionSet;
import 'universe/selector.dart' show Selector;
@@ -38,30 +38,7 @@ abstract class ClassWorld {
// TODO(johnniwinther): Refine this into a `BackendClasses` interface.
Backend get backend;
- // TODO(johnniwinther): Remove the need for this getter.
- @deprecated
- Compiler get compiler;
-
- /// The [ClassElement] for the [Object] class defined in 'dart:core'.
- ClassElement get objectClass;
-
- /// The [ClassElement] for the [Function] class defined in 'dart:core'.
- ClassElement get functionClass;
-
- /// The [ClassElement] for the [bool] class defined in 'dart:core'.
- ClassElement get boolClass;
-
- /// The [ClassElement] for the [num] class defined in 'dart:core'.
- ClassElement get numClass;
-
- /// The [ClassElement] for the [int] class defined in 'dart:core'.
- ClassElement get intClass;
-
- /// The [ClassElement] for the [double] class defined in 'dart:core'.
- ClassElement get doubleClass;
-
- /// The [ClassElement] for the [String] class defined in 'dart:core'.
- ClassElement get stringClass;
+ CoreClasses get coreClasses;
/// Returns `true` if [cls] is either directly or indirectly instantiated.
bool isInstantiated(ClassElement cls);
@@ -185,18 +162,98 @@ abstract class ClassWorld {
///
/// If [cls] is provided, the dump will contain only classes related to [cls].
String dump([ClassElement cls]);
+
+ /// 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 [ClassWorld].
+ ClassHierarchyNode getClassHierarchyNode(ClassElement cls);
+}
+
+/// The [ClosedWorld] represents the information known about a program when
+/// compiling with closed-world semantics.
+///
+/// This expands [ClassWorld] with information about live functions,
+/// side effects, and selectors with known single targets.
+abstract class ClosedWorld extends ClassWorld {
+ /// Returns the [FunctionSet] containing all live functions in the closed
+ /// world.
+ FunctionSet get allFunctions;
+
+ /// Returns `true` if the field [element] is known to be effectively final.
+ bool fieldNeverChanges(Element element);
+
+ /// Extends the receiver type [mask] for calling [selector] to take live
+ /// `noSuchMethod` handlers into account.
+ TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask);
+
+ /// Returns all resolved typedefs.
+ Iterable<TypedefElement> get allTypedefs;
+
+ /// Returns the single [Element] that matches a call to [selector] on a
+ /// receiver of type [mask]. If multiple targets exist, `null` is returned.
+ Element locateSingleElement(Selector selector, TypeMask mask);
+
+ /// Returns the single field that matches a call to [selector] on a
+ /// receiver of type [mask]. If multiple targets exist or the single target
+ /// is not a field, `null` is returned.
+ VariableElement locateSingleField(Selector selector, TypeMask mask);
+
+ /// Returns the side effects of executing [element].
+ SideEffects getSideEffectsOfElement(Element element);
+
+ /// Returns the side effects of calling [selector] on a receiver of type
+ /// [mask].
+ SideEffects getSideEffectsOfSelector(Selector selector, TypeMask mask);
+
+ /// Returns `true` if [element] is guaranteed not to throw an exception.
+ bool getCannotThrow(Element element);
+
+ /// Returns `true` if [element] is called in a loop.
+ // TODO(johnniwinther): Is this 'potentially called' or 'known to be called'?
+ bool isCalledInLoop(Element element);
+
+ /// Returns `true` if [element] might be passed to `Function.apply`.
+ // TODO(johnniwinther): Is this 'passed invocation target` or
+ // `passed as argument`?
+ bool getMightBePassedToApply(Element element);
}
-class World implements ClassWorld {
- ClassElement get objectClass => coreClasses.objectClass;
- ClassElement get functionClass => coreClasses.functionClass;
- ClassElement get boolClass => coreClasses.boolClass;
- ClassElement get numClass => coreClasses.numClass;
- ClassElement get intClass => coreClasses.intClass;
- ClassElement get doubleClass => coreClasses.doubleClass;
- ClassElement get stringClass => coreClasses.stringClass;
- ClassElement get nullClass => coreClasses.nullClass;
+/// Interface for computing side effects and uses of elements. This is used
+/// during type inference to compute the [ClosedWorld] for code generation.
+abstract class ClosedWorldRefiner {
+ /// Registers the side [effects] of executing [element].
+ void registerSideEffects(Element element, SideEffects effects);
+ /// Registers the executing of [element] as without side effects.
+ void registerSideEffectsFree(Element element);
+
+ /// Returns the currently known side effects of executing [element].
+ SideEffects getCurrentlyKnownSideEffects(Element element);
+
+ /// Registers that [element] might be passed to `Function.apply`.
+ // TODO(johnniwinther): Is this 'passed invocation target` or
+ // `passed as argument`?
+ void registerMightBePassedToApply(Element element);
+
+ /// Returns `true` if [element] might be passed to `Function.apply` given the
+ /// currently inferred information.
+ bool getCurrentlyKnownMightBePassedToApply(Element element);
+
+ /// Registers that [element] is called in a loop.
+ // TODO(johnniwinther): Is this 'potentially called' or 'known to be called'?
+ void addFunctionCalledInLoop(Element element);
+
+ /// Registers that [element] is guaranteed not to throw an exception.
+ void registerCannotThrow(Element element);
+
+ /// Adds the closure class [cls] to the inference world. The class is
+ /// considered directly instantiated.
+ void registerClosureClass(ClassElement cls);
+}
+
+class World implements ClosedWorld, ClosedWorldRefiner {
/// Cache of [FlatTypeMask]s grouped by the 8 possible values of the
/// `FlatTypeMask.flags` property.
List<Map<ClassElement, TypeMask>> canonicalizedTypeMasks =
@@ -221,10 +278,10 @@ class World implements ClassWorld {
assert(checkInvariants(x));
assert(checkInvariants(y, mustBeInstantiated: false));
- if (y == objectClass) return true;
- if (x == objectClass) return false;
+ if (y == coreClasses.objectClass) return true;
+ if (x == coreClasses.objectClass) return false;
if (x.asInstanceOf(y) != null) return true;
- if (y != functionClass) return false;
+ if (y != coreClasses.functionClass) return false;
return x.callType != null;
}
@@ -233,8 +290,8 @@ class World implements ClassWorld {
assert(checkInvariants(x));
assert(checkInvariants(y));
- if (y == objectClass) return true;
- if (x == objectClass) return false;
+ if (y == coreClasses.objectClass) return true;
+ if (x == coreClasses.objectClass) return false;
while (x != null && x.hierarchyDepth >= y.hierarchyDepth) {
if (x == y) return true;
x = x.superclass;
@@ -262,7 +319,7 @@ class World implements ClassWorld {
/// Returns `true` if [cls] is implemented by an instantiated class.
bool isImplemented(ClassElement cls) {
- return compiler.resolverWorld.isImplemented(cls);
+ return _compiler.resolverWorld.isImplemented(cls);
}
/// Returns an iterable over the directly instantiated classes that extend
@@ -394,7 +451,7 @@ class World implements ClassWorld {
/// extend it.
bool hasOnlySubclasses(ClassElement cls) {
// TODO(johnniwinther): move this to ClassSet?
- if (cls == objectClass) return true;
+ if (cls == coreClasses.objectClass) return true;
ClassSet classSet = _classSets[cls.declaration];
if (classSet == null) {
// Vacuously true.
@@ -442,7 +499,7 @@ class World implements ClassWorld {
List<ClassElement> commonSupertypes = <ClassElement>[];
OUTER:
for (Link<DartType> link = typeSet[depth];
- link.head.element != objectClass;
+ link.head.element != coreClasses.objectClass;
link = link.tail) {
ClassElement cls = link.head.element;
for (Link<OrderedTypeSet> link = otherTypeSets;
@@ -454,7 +511,7 @@ class World implements ClassWorld {
}
commonSupertypes.add(cls);
}
- commonSupertypes.add(objectClass);
+ commonSupertypes.add(coreClasses.objectClass);
return commonSupertypes;
}
@@ -547,8 +604,9 @@ class World implements ClassWorld {
return subclasses.contains(type);
}
- final Compiler compiler;
- Backend get backend => compiler.backend;
+ final Compiler _compiler;
+ Backend get backend => _compiler.backend;
+ CommonMasks get commonMasks => _compiler.commonMasks;
final FunctionSet allFunctions;
final Set<Element> functionsCalledInLoop = new Set<Element>();
final Map<Element, SideEffects> sideEffects = new Map<Element, SideEffects>();
@@ -580,11 +638,11 @@ class World implements ClassWorld {
final Set<Element> alreadyPopulated;
- bool get isClosed => compiler.phase > Compiler.PHASE_RESOLVING;
+ bool get isClosed => _compiler.phase > Compiler.PHASE_RESOLVING;
// Used by selectors.
bool isForeign(Element element) {
- return compiler.backend.isForeign(element);
+ return backend.isForeign(element);
}
Set<ClassElement> typesImplementedBySubclassesOf(ClassElement cls) {
@@ -593,18 +651,24 @@ class World implements ClassWorld {
World(Compiler compiler)
: allFunctions = new FunctionSet(compiler),
- this.compiler = compiler,
+ this._compiler = compiler,
alreadyPopulated = compiler.cacheStrategy.newSet();
- CoreClasses get coreClasses => compiler.coreClasses;
+ CoreClasses get coreClasses => _compiler.coreClasses;
- DiagnosticReporter get reporter => compiler.reporter;
+ DiagnosticReporter get reporter => _compiler.reporter;
/// Called to add [cls] to the set of known classes.
///
/// This ensures that class hierarchy queries can be performed on [cls] and
/// classes that extend or implement it.
- void registerClass(ClassElement cls, {bool isDirectlyInstantiated: false}) {
+ void registerClass(ClassElement cls) => _registerClass(cls);
+
+ void registerClosureClass(ClassElement cls) {
+ _registerClass(cls, isDirectlyInstantiated: true);
+ }
+
+ void _registerClass(ClassElement cls, {bool isDirectlyInstantiated: false}) {
_ensureClassSet(cls);
if (isDirectlyInstantiated) {
_updateClassHierarchyNodeForClass(cls, directlyInstantiated: true);
@@ -693,7 +757,7 @@ class World implements ClassWorld {
/// properties of the [ClassHierarchyNode] for [cls].
void addSubtypes(ClassElement cls) {
- if (compiler.options.hasIncrementalSupport &&
+ if (_compiler.options.hasIncrementalSupport &&
!alreadyPopulated.add(cls)) {
return;
}
@@ -722,7 +786,7 @@ class World implements ClassWorld {
// classes: if the superclass of these classes require RTI, then
// they also need RTI, so that a constructor passes the type
// variables to the super constructor.
- compiler.resolverWorld.directlyInstantiatedClasses.forEach(addSubtypes);
+ _compiler.resolverWorld.directlyInstantiatedClasses.forEach(addSubtypes);
}
@override
@@ -764,17 +828,17 @@ class World implements ClassWorld {
}
Element locateSingleElement(Selector selector, TypeMask mask) {
- mask ??= compiler.commonMasks.dynamicType;
- return mask.locateSingleElement(selector, compiler);
+ mask ??= commonMasks.dynamicType;
+ return mask.locateSingleElement(selector, _compiler);
}
TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask) {
bool canReachAll = true;
if (mask != null) {
- canReachAll = compiler.enabledInvokeOn &&
+ canReachAll = _compiler.enabledInvokeOn &&
mask.needsNoSuchMethodHandling(selector, this);
}
- return canReachAll ? compiler.commonMasks.dynamicType : mask;
+ return canReachAll ? commonMasks.dynamicType : mask;
}
void addFunctionCalledInLoop(Element element) {
@@ -799,8 +863,8 @@ class World implements ClassWorld {
return true;
}
if (element.isInstanceMember) {
- return !compiler.resolverWorld.hasInvokedSetter(element, this) &&
- !compiler.resolverWorld.fieldSetters.contains(element);
+ return !_compiler.resolverWorld.hasInvokedSetter(element, this) &&
+ !_compiler.resolverWorld.fieldSetters.contains(element);
}
return false;
}
@@ -819,6 +883,11 @@ class World implements ClassWorld {
});
}
+ @override
+ SideEffects getCurrentlyKnownSideEffects(Element element) {
+ return getSideEffectsOfElement(element);
+ }
+
void registerSideEffects(Element element, SideEffects effects) {
if (sideEffectsFreeElements.contains(element)) return;
sideEffects[element.declaration] = effects;
@@ -878,5 +947,10 @@ class World implements ClassWorld {
return functionsThatMightBePassedToApply.contains(element);
}
- bool get hasClosedWorldAssumption => !compiler.options.hasIncrementalSupport;
+ @override
+ bool getCurrentlyKnownMightBePassedToApply(Element element) {
+ return getMightBePassedToApply(element);
+ }
+
+ bool get hasClosedWorldAssumption => !_compiler.options.hasIncrementalSupport;
}
« no previous file with comments | « pkg/compiler/lib/src/universe/function_set.dart ('k') | tests/compiler/dart2js/class_set_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698