| 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; | 
| -    })); | 
| -  } | 
| } | 
|  |