| Index: sdk/lib/_internal/compiler/implementation/world.dart
|
| diff --git a/sdk/lib/_internal/compiler/implementation/world.dart b/sdk/lib/_internal/compiler/implementation/world.dart
|
| deleted file mode 100644
|
| index 4391cdb3fc3de33dca1f69415ef7f0c8eb849599..0000000000000000000000000000000000000000
|
| --- a/sdk/lib/_internal/compiler/implementation/world.dart
|
| +++ /dev/null
|
| @@ -1,524 +0,0 @@
|
| -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
| -// for details. All rights reserved. Use of this source code is governed by a
|
| -// BSD-style license that can be found in the LICENSE file.
|
| -
|
| -part of dart2js;
|
| -
|
| -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;
|
| -
|
| - /// Returns `true` if [cls] is instantiated.
|
| - bool isInstantiated(ClassElement cls);
|
| -
|
| - /// Returns `true` if the class world is closed.
|
| - bool get isClosed;
|
| -
|
| - /// Return `true` if [x] is a subclass of [y].
|
| - bool isSubclassOf(ClassElement x, ClassElement y);
|
| -
|
| - /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an
|
| - /// instance of [y].
|
| - bool isSubtypeOf(ClassElement x, ClassElement y);
|
| -
|
| - /// Returns an iterable over the live classes that extend [cls] including
|
| - /// [cls] itself.
|
| - Iterable<ClassElement> subclassesOf(ClassElement cls);
|
| -
|
| - /// Returns an iterable over the live classes that extend [cls] _not_
|
| - /// including [cls] itself.
|
| - Iterable<ClassElement> strictSubclassesOf(ClassElement cls);
|
| -
|
| - /// Returns an iterable over the live classes that implement [cls] including
|
| - /// [cls] if it is live.
|
| - Iterable<ClassElement> subtypesOf(ClassElement cls);
|
| -
|
| - /// Returns an iterable over the live classes that implement [cls] _not_
|
| - /// including [cls] if it is live.
|
| - Iterable<ClassElement> strictSubtypesOf(ClassElement cls);
|
| -
|
| - /// Returns `true` if any live class extends [cls].
|
| - bool hasAnySubclass(ClassElement cls);
|
| -
|
| - /// Returns `true` if any live class other than [cls] extends [cls].
|
| - bool hasAnyStrictSubclass(ClassElement cls);
|
| -
|
| - /// Returns `true` if any live class implements [cls].
|
| - bool hasAnySubtype(ClassElement cls);
|
| -
|
| - /// Returns `true` if any live class other than [cls] implements [cls].
|
| - bool hasAnyStrictSubtype(ClassElement cls);
|
| -
|
| - /// Returns `true` if all live classes that implement [cls] extend it.
|
| - bool hasOnlySubclasses(ClassElement cls);
|
| -
|
| - /// Returns an iterable over the common supertypes of the [classes].
|
| - Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes);
|
| -
|
| - /// Returns an iterable over the live mixin applications that mixin [cls].
|
| - Iterable<MixinApplicationElement> mixinUsesOf(ClassElement cls);
|
| -
|
| - /// Returns `true` if [cls] is mixed into a live class.
|
| - bool isUsedAsMixin(ClassElement cls);
|
| -
|
| - /// Returns `true` if any live class that mixes in [cls] implements [type].
|
| - bool hasAnySubclassOfMixinUseThatImplements(ClassElement cls,
|
| - ClassElement type);
|
| -
|
| - /// Returns `true` if any live class that mixes in [mixin] is also a subclass
|
| - /// of [superclass].
|
| - bool hasAnySubclassThatMixes(ClassElement superclass, ClassElement mixin);
|
| -
|
| - /// Returns `true` if any subclass of [superclass] implements [type].
|
| - bool hasAnySubclassThatImplements(ClassElement superclass, ClassElement type);
|
| -}
|
| -
|
| -class World implements ClassWorld {
|
| - ClassElement get objectClass => compiler.objectClass;
|
| - ClassElement get functionClass => compiler.functionClass;
|
| - ClassElement get boolClass => compiler.boolClass;
|
| - ClassElement get numClass => compiler.numClass;
|
| - ClassElement get intClass => compiler.intClass;
|
| - ClassElement get doubleClass => compiler.doubleClass;
|
| - ClassElement get stringClass => compiler.stringClass;
|
| -
|
| - 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.') &&
|
| - (!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 == objectClass) return true;
|
| - if (x == objectClass) return false;
|
| - if (x.asInstanceOf(y) != null) return true;
|
| - if (y != 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 == objectClass) return true;
|
| - if (x == objectClass) return false;
|
| - while (x != null && x.hierarchyDepth >= y.hierarchyDepth) {
|
| - if (x == y) return true;
|
| - x = x.superclass;
|
| - }
|
| - return false;
|
| - }
|
| -
|
| - /// Returns `true` if [cls] is instantiated.
|
| - bool isInstantiated(ClassElement cls) {
|
| - return compiler.resolverWorld.isInstantiated(cls);
|
| - }
|
| -
|
| - /// Returns an iterable over the live classes that extend [cls] including
|
| - /// [cls] itself.
|
| - Iterable<ClassElement> subclassesOf(ClassElement cls) {
|
| - Set<ClassElement> subclasses = _subclasses[cls.declaration];
|
| - if (subclasses == null) return const <ClassElement>[];
|
| - assert(invariant(cls, isInstantiated(cls.declaration),
|
| - message: 'Class $cls has not been instantiated.'));
|
| - return subclasses;
|
| - }
|
| -
|
| - /// Returns an iterable over the live classes that extend [cls] _not_
|
| - /// including [cls] itself.
|
| - Iterable<ClassElement> strictSubclassesOf(ClassElement cls) {
|
| - return subclassesOf(cls).where((c) => c != cls);
|
| - }
|
| -
|
| - /// Returns an iterable over the live classes that implement [cls] including
|
| - /// [cls] if it is live.
|
| - Iterable<ClassElement> subtypesOf(ClassElement cls) {
|
| - Set<ClassElement> subtypes = _subtypes[cls.declaration];
|
| - return subtypes != null ? subtypes : const <ClassElement>[];
|
| - }
|
| -
|
| - /// Returns an iterable over the live classes that implement [cls] _not_
|
| - /// including [cls] if it is live.
|
| - Iterable<ClassElement> strictSubtypesOf(ClassElement cls) {
|
| - return subtypesOf(cls).where((c) => c != cls);
|
| - }
|
| -
|
| - /// Returns `true` if any live class extends [cls].
|
| - bool hasAnySubclass(ClassElement cls) {
|
| - return !subclassesOf(cls).isEmpty;
|
| - }
|
| -
|
| - /// Returns `true` if any live class other than [cls] extends [cls].
|
| - bool hasAnyStrictSubclass(ClassElement cls) {
|
| - return !strictSubclassesOf(cls).isEmpty;
|
| - }
|
| -
|
| - /// Returns `true` if any live class implements [cls].
|
| - bool hasAnySubtype(ClassElement cls) {
|
| - return !subtypesOf(cls).isEmpty;
|
| - }
|
| -
|
| - /// Returns `true` if any live class other than [cls] implements [cls].
|
| - bool hasAnyStrictSubtype(ClassElement cls) {
|
| - return !strictSubtypesOf(cls).isEmpty;
|
| - }
|
| -
|
| - /// Returns `true` if all live classes that implement [cls] extend it.
|
| - bool hasOnlySubclasses(ClassElement cls) {
|
| - Iterable<ClassElement> subtypes = subtypesOf(cls);
|
| - if (subtypes == null) return true;
|
| - Iterable<ClassElement> subclasses = subclassesOf(cls);
|
| - return subclasses != null && (subclasses.length == subtypes.length);
|
| - }
|
| -
|
| - /// 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));
|
| - OrderedTypeSet typeSet = cls.allSupertypesAndSelf;
|
| - if (!iterator.moveNext()) return typeSet.types.map((type) => type.element);
|
| -
|
| - int depth = typeSet.maxDepth;
|
| - Link<OrderedTypeSet> otherTypeSets = const Link<OrderedTypeSet>();
|
| - do {
|
| - ClassElement otherClass = iterator.current;
|
| - assert(checkInvariants(otherClass));
|
| - OrderedTypeSet otherTypeSet = otherClass.allSupertypesAndSelf;
|
| - otherTypeSets = otherTypeSets.prepend(otherTypeSet);
|
| - if (otherTypeSet.maxDepth < depth) {
|
| - depth = otherTypeSet.maxDepth;
|
| - }
|
| - } while (iterator.moveNext());
|
| -
|
| - List<ClassElement> commonSupertypes = <ClassElement>[];
|
| - OUTER: for (Link<DartType> link = typeSet[depth];
|
| - link.head.element != objectClass;
|
| - link = link.tail) {
|
| - ClassElement cls = link.head.element;
|
| - for (Link<OrderedTypeSet> link = otherTypeSets;
|
| - !link.isEmpty;
|
| - link = link.tail) {
|
| - if (link.head.asInstanceOf(cls) == null) {
|
| - continue OUTER;
|
| - }
|
| - }
|
| - commonSupertypes.add(cls);
|
| - }
|
| - commonSupertypes.add(objectClass);
|
| - return commonSupertypes;
|
| - }
|
| -
|
| - /// Returns an iterable over all mixin applications that mixin [cls].
|
| - Iterable<MixinApplicationElement> allMixinUsesOf(ClassElement cls) {
|
| - Iterable<MixinApplicationElement> uses = _mixinUses[cls];
|
| - return uses != null ? uses : const <MixinApplicationElement>[];
|
| - }
|
| -
|
| - /// Returns an iterable over the live mixin applications that mixin [cls].
|
| - Iterable<MixinApplicationElement> mixinUsesOf(ClassElement cls) {
|
| - assert(isClosed);
|
| - if (_liveMixinUses == null) {
|
| - _liveMixinUses = new Map<ClassElement, List<MixinApplicationElement>>();
|
| - for (ClassElement mixin in _mixinUses.keys) {
|
| - Iterable<MixinApplicationElement> uses =
|
| - _mixinUses[mixin].where(isInstantiated);
|
| - if (uses.isNotEmpty) _liveMixinUses[mixin] = uses.toList();
|
| - }
|
| - }
|
| - Iterable<MixinApplicationElement> uses = _liveMixinUses[cls];
|
| - return uses != null ? uses : const <MixinApplicationElement>[];
|
| - }
|
| -
|
| - /// Returns `true` if [cls] is mixed into a live class.
|
| - bool isUsedAsMixin(ClassElement cls) {
|
| - return !mixinUsesOf(cls).isEmpty;
|
| - }
|
| -
|
| - /// Returns `true` if any live class that mixes in [cls] implements [type].
|
| - bool hasAnySubclassOfMixinUseThatImplements(ClassElement cls,
|
| - ClassElement 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(ClassElement superclass, ClassElement mixin) {
|
| - return mixinUsesOf(mixin).any((each) => each.isSubclassOf(superclass));
|
| - }
|
| -
|
| - /// Returns `true` if any subclass of [superclass] implements [type].
|
| - bool hasAnySubclassThatImplements(ClassElement superclass,
|
| - ClassElement type) {
|
| - Set<ClassElement> subclasses = typesImplementedBySubclassesOf(superclass);
|
| - if (subclasses == null) return false;
|
| - return subclasses.contains(type);
|
| - }
|
| -
|
| - final Compiler compiler;
|
| - Backend get backend => compiler.backend;
|
| - final FunctionSet allFunctions;
|
| - final Set<Element> functionsCalledInLoop = new Set<Element>();
|
| - final Map<Element, SideEffects> sideEffects = new Map<Element, SideEffects>();
|
| -
|
| - final Set<TypedefElement> allTypedefs = new Set<TypedefElement>();
|
| -
|
| - final Map<ClassElement, List<MixinApplicationElement>> _mixinUses =
|
| - new Map<ClassElement, List<MixinApplicationElement>>();
|
| - Map<ClassElement, List<MixinApplicationElement>> _liveMixinUses;
|
| -
|
| - final Map<ClassElement, Set<ClassElement>> _typesImplementedBySubclasses =
|
| - new Map<ClassElement, Set<ClassElement>>();
|
| -
|
| - // We keep track of subtype and subclass relationships in four
|
| - // distinct sets to make class hierarchy analysis faster.
|
| - final Map<ClassElement, Set<ClassElement>> _subclasses =
|
| - new Map<ClassElement, Set<ClassElement>>();
|
| - final Map<ClassElement, Set<ClassElement>> _subtypes =
|
| - new Map<ClassElement, Set<ClassElement>>();
|
| -
|
| - final Set<Element> sideEffectsFreeElements = new Set<Element>();
|
| -
|
| - final Set<Element> elementsThatCannotThrow = new Set<Element>();
|
| -
|
| - final Set<Element> functionsThatMightBePassedToApply =
|
| - new Set<FunctionElement>();
|
| -
|
| - final Set<Element> alreadyPopulated;
|
| -
|
| - bool get isClosed => compiler.phase > Compiler.PHASE_RESOLVING;
|
| -
|
| - // Used by selectors.
|
| - bool isAssertMethod(Element element) {
|
| - return compiler.backend.isAssertMethod(element);
|
| - }
|
| -
|
| - // Used by selectors.
|
| - bool isForeign(Element element) {
|
| - return element.isForeign(compiler.backend);
|
| - }
|
| -
|
| - Set<ClassElement> typesImplementedBySubclassesOf(ClassElement cls) {
|
| - return _typesImplementedBySubclasses[cls.declaration];
|
| - }
|
| -
|
| - World(Compiler compiler)
|
| - : allFunctions = new FunctionSet(compiler),
|
| - this.compiler = compiler,
|
| - alreadyPopulated = compiler.cacheStrategy.newSet();
|
| -
|
| - void populate() {
|
| - void addSubtypes(ClassElement cls) {
|
| - if (compiler.hasIncrementalSupport && !alreadyPopulated.add(cls)) {
|
| - return;
|
| - }
|
| - assert(cls.isDeclaration);
|
| - if (!cls.isResolved) {
|
| - compiler.internalError(cls, 'Class "${cls.name}" is not resolved.');
|
| - }
|
| -
|
| - for (DartType type in cls.allSupertypes) {
|
| - Set<Element> subtypesOfSupertype =
|
| - _subtypes.putIfAbsent(type.element, () => new Set<ClassElement>());
|
| - subtypesOfSupertype.add(cls);
|
| - }
|
| -
|
| - // Walk through the superclasses, and record the types
|
| - // implemented by that type on the superclasses.
|
| - ClassElement superclass = cls.superclass;
|
| - while (superclass != null) {
|
| - Set<Element> subclassesOfSuperclass =
|
| - _subclasses.putIfAbsent(superclass, () => new Set<ClassElement>());
|
| - subclassesOfSuperclass.add(cls);
|
| -
|
| - Set<Element> typesImplementedBySubclassesOfCls =
|
| - _typesImplementedBySubclasses.putIfAbsent(
|
| - superclass, () => new Set<ClassElement>());
|
| - for (DartType current in cls.allSupertypes) {
|
| - typesImplementedBySubclassesOfCls.add(current.element);
|
| - }
|
| - superclass = superclass.superclass;
|
| - }
|
| - }
|
| -
|
| - // Use the [:seenClasses:] set to include non-instantiated
|
| - // 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);
|
| - }
|
| -
|
| - void registerMixinUse(MixinApplicationElement mixinApplication,
|
| - ClassElement mixin) {
|
| - // TODO(johnniwinther): Add map restricted to live classes.
|
| - // We don't support patch classes as mixin.
|
| - assert(mixin.isDeclaration);
|
| - List<MixinApplicationElement> users =
|
| - _mixinUses.putIfAbsent(mixin, () =>
|
| - new List<MixinApplicationElement>());
|
| - users.add(mixinApplication);
|
| - }
|
| -
|
| - bool hasAnyUserDefinedGetter(Selector selector) {
|
| - return allFunctions.filter(selector).any((each) => each.isGetter);
|
| - }
|
| -
|
| - void registerUsedElement(Element element) {
|
| - if (element.isInstanceMember && !element.isAbstract) {
|
| - allFunctions.add(element);
|
| - }
|
| - }
|
| -
|
| - VariableElement locateSingleField(Selector selector) {
|
| - Element result = locateSingleElement(selector);
|
| - return (result != null && result.isField) ? result : null;
|
| - }
|
| -
|
| - Element locateSingleElement(Selector selector) {
|
| - ti.TypeMask mask = selector.mask == null
|
| - ? compiler.typesTask.dynamicType
|
| - : selector.mask;
|
| - return mask.locateSingleElement(selector, compiler);
|
| - }
|
| -
|
| - void addFunctionCalledInLoop(Element element) {
|
| - functionsCalledInLoop.add(element.declaration);
|
| - }
|
| -
|
| - bool isCalledInLoop(Element element) {
|
| - return functionsCalledInLoop.contains(element.declaration);
|
| - }
|
| -
|
| - bool fieldNeverChanges(Element element) {
|
| - if (!element.isField) return false;
|
| - if (element.isNative) {
|
| - // 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;
|
| - }
|
| -
|
| - return element.isFinal
|
| - || element.isConst
|
| - || (element.isInstanceMember
|
| - && !compiler.resolverWorld.hasInvokedSetter(element, this));
|
| - }
|
| -
|
| - SideEffects getSideEffectsOfElement(Element element) {
|
| - // The type inferrer (where the side effects are being computed),
|
| - // does not see generative constructor bodies because they are
|
| - // created by the backend. Also, it does not make any distinction
|
| - // between a constructor and its body for side effects. This
|
| - // implies that currently, the side effects of a constructor body
|
| - // contain the side effects of the initializers.
|
| - assert(!element.isGenerativeConstructorBody);
|
| - assert(!element.isField);
|
| - return sideEffects.putIfAbsent(element.declaration, () {
|
| - return new SideEffects();
|
| - });
|
| - }
|
| -
|
| - void registerSideEffects(Element element, SideEffects effects) {
|
| - if (sideEffectsFreeElements.contains(element)) return;
|
| - sideEffects[element.declaration] = effects;
|
| - }
|
| -
|
| - void registerSideEffectsFree(Element element) {
|
| - sideEffects[element.declaration] = new SideEffects.empty();
|
| - sideEffectsFreeElements.add(element);
|
| - }
|
| -
|
| - SideEffects getSideEffectsOfSelector(Selector selector) {
|
| - // We're not tracking side effects of closures.
|
| - if (selector.isClosureCall) return new SideEffects();
|
| - SideEffects sideEffects = new SideEffects.empty();
|
| - for (Element e in allFunctions.filter(selector)) {
|
| - 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 registerCannotThrow(Element element) {
|
| - elementsThatCannotThrow.add(element);
|
| - }
|
| -
|
| - bool getCannotThrow(Element element) {
|
| - return elementsThatCannotThrow.contains(element);
|
| - }
|
| -
|
| - void registerImplicitSuperCall(Registry registry,
|
| - FunctionElement superConstructor) {
|
| - registry.registerDependency(superConstructor);
|
| - }
|
| -
|
| - void registerMightBePassedToApply(Element element) {
|
| - functionsThatMightBePassedToApply.add(element);
|
| - }
|
| -
|
| - bool getMightBePassedToApply(Element element) {
|
| - // We have to check whether the element we look at was created after
|
| - // type inference ran. This is currently only the case for the call
|
| - // method of function classes that were generated for function
|
| - // expressions. In such a case, we have to look at the original
|
| - // function expressions's element.
|
| - // TODO(herhut): Generate classes for function expressions earlier.
|
| - if (element is closureMapping.SynthesizedCallMethodElementX) {
|
| - return getMightBePassedToApply(element.expression);
|
| - }
|
| - return functionsThatMightBePassedToApply.contains(element);
|
| - }
|
| -}
|
|
|