// 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 js_backend;

const VERBOSE_OPTIMIZER_HINTS = false;

class JavaScriptItemCompilationContext extends ItemCompilationContext {
  final Set<HInstruction> boundsChecked = new Set<HInstruction>();
  final Set<HInstruction> allocatedFixedLists = new Set<HInstruction>();
}

abstract class FunctionCompiler {
  /// Generates JavaScript code for `work.element`.
  jsAst.Fun compile(CodegenWorkItem work);

  Iterable get tasks;
}

/*
 * Invariants:
 *   canInline(function) implies canInline(function, insideLoop:true)
 *   !canInline(function, insideLoop: true) implies !canInline(function)
 */
class FunctionInlineCache {
  static const int _unknown = -1;
  static const int _mustNotInline = 0;
  // May-inline-in-loop means that the function may not be inlined outside loops
  // but may be inlined in a loop.
  static const int _mayInlineInLoopMustNotOutside = 1;
  // The function can be inlined in a loop, but not outside.
  static const int _canInlineInLoopMustNotOutside = 2;
  // May-inline means that we know that it can be inlined inside a loop, but
  // don't know about the general case yet.
  static const int _canInlineInLoopMayInlineOutside = 3;
  static const int _canInline = 4;
  static const int _mustInline = 5;

  final Map<FunctionElement, int> _cachedDecisions =
      new Map<FunctionElement, int>();

  // Returns `true`/`false` if we have a cached decision.
  // Returns `null` otherwise.
  bool canInline(FunctionElement element, {bool insideLoop}) {
    int decision = _cachedDecisions[element];

    if (decision == null) {
      // These synthetic elements are not yet present when we initially compute
      // this cache from metadata annotations, so look for their parent.
      if (element is ConstructorBodyElement) {
        ConstructorBodyElement body = element;
        decision = _cachedDecisions[body.constructor];
      }
      if (decision == null) {
        decision = _unknown;
      }
    }

    if (insideLoop) {
      switch (decision) {
        case _mustNotInline:
          return false;

        case _unknown:
        case _mayInlineInLoopMustNotOutside:
          // We know we can't inline outside a loop, but don't know for the
          // loop case. Return `null` to indicate that we don't know yet.
          return null;

        case _canInlineInLoopMustNotOutside:
        case _canInlineInLoopMayInlineOutside:
        case _canInline:
        case _mustInline:
          return true;
      }
    } else {
      switch (decision) {
        case _mustNotInline:
        case _mayInlineInLoopMustNotOutside:
        case _canInlineInLoopMustNotOutside:
          return false;

        case _unknown:
        case _canInlineInLoopMayInlineOutside:
          // We know we can inline inside a loop, but don't know for the
          // non-loop case. Return `null` to indicate that we don't know yet.
          return null;

        case _canInline:
        case _mustInline:
          return true;
      }
    }

    // Quiet static checker.
    return null;
  }

  void markAsInlinable(FunctionElement element, {bool insideLoop}) {
    int oldDecision = _cachedDecisions[element];

    if (oldDecision == null) {
      oldDecision = _unknown;
    }

    if (insideLoop) {
      switch (oldDecision) {
        case _mustNotInline:
          throw new SpannableAssertionFailure(element,
              "Can't mark a function as non-inlinable and inlinable at the "
              "same time.");

        case _unknown:
          // We know that it can be inlined in a loop, but don't know about the
          // non-loop case yet.
          _cachedDecisions[element] = _canInlineInLoopMayInlineOutside;
          break;

        case _mayInlineInLoopMustNotOutside:
          _cachedDecisions[element] = _canInlineInLoopMustNotOutside;
          break;

        case _canInlineInLoopMustNotOutside:
        case _canInlineInLoopMayInlineOutside:
        case _canInline:
        case _mustInline:
          // Do nothing.
          break;
      }
    } else {
      switch (oldDecision) {
        case _mustNotInline:
        case _mayInlineInLoopMustNotOutside:
        case _canInlineInLoopMustNotOutside:
          throw new SpannableAssertionFailure(element,
              "Can't mark a function as non-inlinable and inlinable at the "
              "same time.");

        case _unknown:
        case _canInlineInLoopMayInlineOutside:
          _cachedDecisions[element] = _canInline;
          break;

        case _canInline:
        case _mustInline:
          // Do nothing.
          break;

      }
    }
  }

  void markAsNonInlinable(FunctionElement element, {bool insideLoop: true}) {
    int oldDecision = _cachedDecisions[element];

    if (oldDecision == null) {
      oldDecision = _unknown;
    }

    if (insideLoop) {
      switch (oldDecision) {
        case _canInlineInLoopMustNotOutside:
        case _canInlineInLoopMayInlineOutside:
        case _canInline:
        case _mustInline:
          throw new SpannableAssertionFailure(element,
              "Can't mark a function as non-inlinable and inlinable at the "
              "same time.");

        case _mayInlineInLoopMustNotOutside:
        case _unknown:
          _cachedDecisions[element] = _mustNotInline;
          break;

        case _mustNotInline:
          // Do nothing.
          break;
      }
    } else {
      switch (oldDecision) {
        case _canInline:
        case _mustInline:
          throw new SpannableAssertionFailure(element,
              "Can't mark a function as non-inlinable and inlinable at the "
              "same time.");

        case _unknown:
          // We can't inline outside a loop, but we might still be allowed to do
          // so outside.
          _cachedDecisions[element] = _mayInlineInLoopMustNotOutside;
          break;

        case _canInlineInLoopMayInlineOutside:
          // We already knew that the function could be inlined inside a loop,
          // but didn't have information about the non-loop case. Now we know
          // that it can't be inlined outside a loop.
          _cachedDecisions[element] = _canInlineInLoopMustNotOutside;
          break;

        case _mayInlineInLoopMustNotOutside:
        case _canInlineInLoopMustNotOutside:
        case _mustNotInline:
          // Do nothing.
          break;
      }
    }
  }

  void markAsMustInline(FunctionElement element) {
    _cachedDecisions[element] = _mustInline;
  }
}

enum SyntheticConstantKind {
  DUMMY_INTERCEPTOR,
  EMPTY_VALUE,
  TYPEVARIABLE_REFERENCE,  // Reference to a type in reflection data.
  NAME
}

class JavaScriptBackend extends Backend {
  String get patchVersion => emitter.patchVersion;

  bool get supportsReflection => emitter.emitter.supportsReflection;

  final Annotations annotations;


  /// Set of classes that need to be considered for reflection although not
  /// otherwise visible during resolution.
  Iterable<ClassElement> get classesRequiredForReflection {
    // TODO(herhut): Clean this up when classes needed for rti are tracked.
    return [helpers.closureClass, helpers.jsIndexableClass];
  }

  FunctionCompiler functionCompiler;

  CodeEmitterTask emitter;

  /**
   * The generated code as a js AST for compiled methods.
   */
  Map<Element, jsAst.Expression> get generatedCode {
    return compiler.enqueuer.codegen.generatedCode;
  }

  FunctionInlineCache inlineCache = new FunctionInlineCache();

  /// If [true], the compiler will emit code that logs whenever a method is
  /// called. When TRACE_METHOD is 'console' this will be logged
  /// directly in the JavaScript console. When TRACE_METHOD is 'post' the
  /// information will be sent to a server via a POST request.
  static const String TRACE_METHOD = const String.fromEnvironment('traceCalls');
  static const bool TRACE_CALLS =
    TRACE_METHOD == 'post' || TRACE_METHOD == 'console';
  Element traceHelper;

  TypeMask get stringType => compiler.typesTask.stringType;
  TypeMask get doubleType => compiler.typesTask.doubleType;
  TypeMask get intType => compiler.typesTask.intType;
  TypeMask get uint32Type => compiler.typesTask.uint32Type;
  TypeMask get uint31Type => compiler.typesTask.uint31Type;
  TypeMask get positiveIntType => compiler.typesTask.positiveIntType;
  TypeMask get numType => compiler.typesTask.numType;
  TypeMask get boolType => compiler.typesTask.boolType;
  TypeMask get dynamicType => compiler.typesTask.dynamicType;
  TypeMask get nullType => compiler.typesTask.nullType;
  TypeMask get emptyType => const TypeMask.nonNullEmpty();

  TypeMask _indexablePrimitiveTypeCache;
  TypeMask get indexablePrimitiveType {
    if (_indexablePrimitiveTypeCache == null) {
      _indexablePrimitiveTypeCache = new TypeMask.nonNullSubtype(
          helpers.jsIndexableClass, compiler.world);
    }
    return _indexablePrimitiveTypeCache;
  }

  TypeMask _readableArrayTypeCache;
  TypeMask get readableArrayType {
    if (_readableArrayTypeCache == null) {
      _readableArrayTypeCache = new TypeMask.nonNullSubclass(
          helpers.jsArrayClass, compiler.world);
    }
    return _readableArrayTypeCache;
  }

  TypeMask _mutableArrayTypeCache;
  TypeMask get mutableArrayType {
    if (_mutableArrayTypeCache == null) {
      _mutableArrayTypeCache = new TypeMask.nonNullSubclass(
          helpers.jsMutableArrayClass, compiler.world);
    }
    return _mutableArrayTypeCache;
  }

  TypeMask _fixedArrayTypeCache;
  TypeMask get fixedArrayType {
    if (_fixedArrayTypeCache == null) {
      _fixedArrayTypeCache = new TypeMask.nonNullExact(
          helpers.jsFixedArrayClass, compiler.world);
    }
    return _fixedArrayTypeCache;
  }

  TypeMask _extendableArrayTypeCache;
  TypeMask get extendableArrayType {
    if (_extendableArrayTypeCache == null) {
      _extendableArrayTypeCache = new TypeMask.nonNullExact(
          helpers.jsExtendableArrayClass, compiler.world);
    }
    return _extendableArrayTypeCache;
  }

  TypeMask _unmodifiableArrayTypeCache;
  TypeMask get unmodifiableArrayType {
    if (_unmodifiableArrayTypeCache == null) {
      _unmodifiableArrayTypeCache = new TypeMask.nonNullExact(
          helpers.jsUnmodifiableArrayClass, compiler.world);
    }
    return _fixedArrayTypeCache;
  }

  TypeMask _nonNullTypeCache;
  TypeMask get nonNullType {
    if (_nonNullTypeCache == null) {
      _nonNullTypeCache =
          compiler.typesTask.dynamicType.nonNullable();
    }
    return _nonNullTypeCache;
  }

  /// Maps special classes to their implementation (JSXxx) class.
  Map<ClassElement, ClassElement> implementationClasses;

  bool needToInitializeIsolateAffinityTag = false;
  bool needToInitializeDispatchProperty = false;

  final Namer namer;

  /**
   * A collection of selectors that must have a one shot interceptor
   * generated.
   */
  final Map<jsAst.Name, Selector> oneShotInterceptors;

  /**
   * The members of instantiated interceptor classes: maps a member name to the
   * list of members that have that name. This map is used by the codegen to
   * know whether a send must be intercepted or not.
   */
  final Map<String, Set<Element>> interceptedElements;

  /**
   * The members of mixin classes that are mixed into an instantiated
   * interceptor class.  This is a cached subset of [interceptedElements].
   *
   * Mixin methods are not specialized for the class they are mixed into.
   * Methods mixed into intercepted classes thus always make use of the explicit
   * receiver argument, even when mixed into non-interceptor classes.
   *
   * These members must be invoked with a correct explicit receiver even when
   * the receiver is not an intercepted class.
   */
  final Map<String, Set<Element>> interceptedMixinElements =
      new Map<String, Set<Element>>();

  /**
   * A map of specialized versions of the [getInterceptorMethod].
   * Since [getInterceptorMethod] is a hot method at runtime, we're
   * always specializing it based on the incoming type. The keys in
   * the map are the names of these specialized versions. Note that
   * the generic version that contains all possible type checks is
   * also stored in this map.
   */
  final Map<jsAst.Name, Set<ClassElement>> specializedGetInterceptors;

  /**
   * Set of classes whose methods are intercepted.
   */
  final Set<ClassElement> _interceptedClasses = new Set<ClassElement>();

  /**
   * Set of classes used as mixins on intercepted (native and primitive)
   * classes.  Methods on these classes might also be mixed in to regular Dart
   * (unintercepted) classes.
   */
  final Set<ClassElement> classesMixedIntoInterceptedClasses =
      new Set<ClassElement>();

  /**
   * Set of classes whose `operator ==` methods handle `null` themselves.
   */
  final Set<ClassElement> specialOperatorEqClasses = new Set<ClassElement>();

  /**
   * A set of members that are called from subclasses via `super`.
   */
  final Set<FunctionElement> aliasedSuperMembers =
      new Setlet<FunctionElement>();

  List<CompilerTask> get tasks {
    List<CompilerTask> result = functionCompiler.tasks;
    result.add(emitter);
    result.add(patchResolverTask);
    return result;
  }

  final RuntimeTypes rti;
  final RuntimeTypesEncoder rtiEncoder;

  /// True if a call to preserveMetadataMarker has been seen.  This means that
  /// metadata must be retained for dart:mirrors to work correctly.
  bool mustRetainMetadata = false;

  /// True if any metadata has been retained.  This is slightly different from
  /// [mustRetainMetadata] and tells us if any metadata was retained.  For
  /// example, if [mustRetainMetadata] is true but there is no metadata in the
  /// program, this variable will stil be false.
  bool hasRetainedMetadata = false;

  /// True if a call to preserveUris has been seen and the preserve-uris flag
  /// is set.
  bool mustPreserveUris = false;

  /// True if a call to preserveLibraryNames has been seen.
  bool mustRetainLibraryNames = false;

  /// True if a call to preserveNames has been seen.
  bool mustPreserveNames = false;

  /// True if a call to disableTreeShaking has been seen.
  bool isTreeShakingDisabled = false;

  /// True if there isn't sufficient @MirrorsUsed data.
  bool hasInsufficientMirrorsUsed = false;

  /// True if a core-library function requires the preamble file to function.
  bool requiresPreamble = false;

  /// True if the html library has been loaded.
  bool htmlLibraryIsLoaded = false;

  /// List of constants from metadata.  If metadata must be preserved,
  /// these constants must be registered.
  final List<Dependency> metadataConstants = <Dependency>[];

  /// List of elements that the user has requested for reflection.
  final Set<Element> targetsUsed = new Set<Element>();

  /// List of annotations provided by user that indicate that the annotated
  /// element must be retained.
  final Set<Element> metaTargetsUsed = new Set<Element>();

  /// Set of methods that are needed by reflection. Computed using
  /// [computeMembersNeededForReflection] on first use.
  Set<Element> _membersNeededForReflection = null;
  Iterable<Element> get membersNeededForReflection {
    assert(_membersNeededForReflection != null);
    return _membersNeededForReflection;
  }

  /// List of symbols that the user has requested for reflection.
  final Set<String> symbolsUsed = new Set<String>();

  /// List of elements that the backend may use.
  final Set<Element> helpersUsed = new Set<Element>();

  /// All the checked mode helpers.
  static const checkedModeHelpers = CheckedModeHelper.helpers;

  // Checked mode helpers indexed by name.
  Map<String, CheckedModeHelper> checkedModeHelperByName =
      new Map<String, CheckedModeHelper>.fromIterable(
          checkedModeHelpers,
          key: (helper) => helper.name);

  TypeVariableHandler typeVariableHandler;

  /// Number of methods compiled before considering reflection.
  int preMirrorsMethodCount = 0;

  /// Resolution and codegen support for generating table of interceptors and
  /// constructors for custom elements.
  CustomElementsAnalysis customElementsAnalysis;

  /// Codegen support for tree-shaking entries of `LookupMap`.
  LookupMapAnalysis lookupMapAnalysis;

  /// Codegen support for typed JavaScript interop.
  JsInteropAnalysis jsInteropAnalysis;

  /// Support for classifying `noSuchMethod` implementations.
  NoSuchMethodRegistry noSuchMethodRegistry;

  JavaScriptConstantTask constantCompilerTask;

  JavaScriptImpactTransformer impactTransformer;

  PatchResolverTask patchResolverTask;

  bool enabledNoSuchMethod = false;

  SourceInformationStrategy sourceInformationStrategy;

  JavaScriptBackendSerialization serialization;

  final NativeData nativeData = new NativeData();

  final BackendHelpers helpers;
  final BackendImpacts impacts;

  JavaScriptBackend(Compiler compiler,
                    {bool generateSourceMap: true,
                     bool useStartupEmitter: false,
                     bool useNewSourceInfo: false})
      : namer = determineNamer(compiler),
        oneShotInterceptors = new Map<jsAst.Name, Selector>(),
        interceptedElements = new Map<String, Set<Element>>(),
        rti = new _RuntimeTypes(compiler),
        rtiEncoder = new _RuntimeTypesEncoder(compiler),
        specializedGetInterceptors = new Map<jsAst.Name, Set<ClassElement>>(),
        annotations = new Annotations(compiler),
        this.sourceInformationStrategy =
            generateSourceMap
                ? (useNewSourceInfo
                     ? new PositionSourceInformationStrategy()
                     : const StartEndSourceInformationStrategy())
                : const JavaScriptSourceInformationStrategy(),
        helpers = new BackendHelpers(compiler),
        impacts = new BackendImpacts(compiler),
        super(compiler) {
    emitter = new CodeEmitterTask(
        compiler, namer, generateSourceMap, useStartupEmitter);
    typeVariableHandler = new TypeVariableHandler(compiler);
    customElementsAnalysis = new CustomElementsAnalysis(this);
    lookupMapAnalysis = new LookupMapAnalysis(this, reporter);
    jsInteropAnalysis = new JsInteropAnalysis(this);

    noSuchMethodRegistry = new NoSuchMethodRegistry(this);
    constantCompilerTask = new JavaScriptConstantTask(compiler);
    impactTransformer = new JavaScriptImpactTransformer(this);
    patchResolverTask = new PatchResolverTask(compiler);
    functionCompiler = compiler.options.useCpsIr
         ? new CpsFunctionCompiler(
             compiler, this, sourceInformationStrategy)
         : new SsaFunctionCompiler(this, sourceInformationStrategy);
    serialization = new JavaScriptBackendSerialization(this);
  }

  ConstantSystem get constantSystem => constants.constantSystem;

  DiagnosticReporter get reporter => compiler.reporter;

  CoreClasses get coreClasses => compiler.coreClasses;

  CoreTypes get coreTypes => compiler.coreTypes;

  Resolution get resolution => compiler.resolution;

  /// Returns constant environment for the JavaScript interpretation of the
  /// constants.
  JavaScriptConstantCompiler get constants {
    return constantCompilerTask.jsConstantCompiler;
  }

  MethodElement resolveExternalFunction(MethodElement element) {
    if (isForeign(element)) {
      return element;
    }
    if (isJsInterop(element))  {
      if (element.memberName == const PublicName('[]') ||
          element.memberName == const PublicName('[]=')) {
        reporter.reportErrorMessage(element,
            MessageKind.JS_INTEROP_INDEX_NOT_SUPPORTED);
      }
      return element;
    }
    return patchResolverTask.measure(() {
      return patchResolverTask.resolveExternalFunction(element);
    });
  }

  bool isForeign(Element element) => element.library == helpers.foreignLibrary;

  bool isBackendLibrary(LibraryElement library) {
    return library == helpers.interceptorsLibrary ||
           library == helpers.jsHelperLibrary;
  }

  static Namer determineNamer(Compiler compiler) {
    return compiler.options.enableMinification ?
        compiler.options.useFrequencyNamer ?
            new FrequencyBasedNamer(compiler) :
            new MinifyNamer(compiler) :
        new Namer(compiler);
  }

  /// The backend must *always* call this method when enqueuing an
  /// element. Calls done by the backend are not seen by global
  /// optimizations, so they would make these optimizations unsound.
  /// Therefore we need to collect the list of helpers the backend may
  /// use.
  // TODO(johnniwinther): Replace this with a more precise modelling; type
  // inference of these elements is disabled.
  Element registerBackendUse(Element element) {
    if (element == null) return null;
    assert(invariant(element, _isValidBackendUse(element),
        message: "Backend use of $element is not allowed."));
    helpersUsed.add(element.declaration);
    if (element.isClass && element.isPatched) {
      // Both declaration and implementation may declare fields, so we
      // add both to the list of helpers.
      helpersUsed.add(element.implementation);
    }
    return element;
  }

  bool _isValidBackendUse(Element element) {
    assert(invariant(element, element.isDeclaration,
        message: ""));
    if (element == helpers.streamIteratorConstructor ||
        element == helpers.compiler.symbolConstructor ||
        element == helpers.compiler.symbolValidatedConstructor ||
        element == helpers.syncCompleterConstructor ||
        element == coreClasses.symbolClass ||
        element == helpers.objectNoSuchMethod) {
      // TODO(johnniwinther): These are valid but we could be more precise.
      return true;
    } else if (element.implementationLibrary.isPatch ||
               // Needed to detect deserialized injected elements, that is
               // element declared in patch files.
               (element.library.isPlatformLibrary &&
                element.sourcePosition.uri.path.contains(
                    '_internal/js_runtime/lib/')) ||
               element.library == helpers.jsHelperLibrary ||
               element.library == helpers.interceptorsLibrary ||
               element.library == helpers.isolateHelperLibrary) {
      // TODO(johnniwinther): We should be more precise about these.
      return true;
    } else if (element == coreClasses.listClass ||
               element == helpers.mapLiteralClass ||
               element == coreClasses.functionClass ||
               element == coreClasses.stringClass) {
      // TODO(johnniwinther): Avoid these.
      return true;
    }
    return false;
  }

  bool usedByBackend(Element element) {
    if (element.isParameter
        || element.isInitializingFormal
        || element.isField) {
      if (usedByBackend(element.enclosingElement)) return true;
    }
    return helpersUsed.contains(element.declaration);
  }

  bool invokedReflectively(Element element) {
    if (element.isParameter || element.isInitializingFormal) {
      ParameterElement parameter = element;
      if (invokedReflectively(parameter.functionDeclaration)) return true;
    }

    if (element.isField) {
      if (Elements.isStaticOrTopLevel(element)
          && (element.isFinal || element.isConst)) {
        return false;
      }
    }

    return isAccessibleByReflection(element.declaration);
  }

  bool canBeUsedForGlobalOptimizations(Element element) {
    return !usedByBackend(element) && !invokedReflectively(element);
  }

  bool isInterceptorClass(ClassElement element) {
    if (element == null) return false;
    if (isNativeOrExtendsNative(element)) return true;
    if (interceptedClasses.contains(element)) return true;
    if (classesMixedIntoInterceptedClasses.contains(element)) return true;
    return false;
  }

  jsAst.Name registerOneShotInterceptor(Selector selector) {
    Set<ClassElement> classes = getInterceptedClassesOn(selector.name);
    jsAst.Name name = namer.nameForGetOneShotInterceptor(selector, classes);
    if (!oneShotInterceptors.containsKey(name)) {
      registerSpecializedGetInterceptor(classes);
      oneShotInterceptors[name] = selector;
    }
    return name;
  }

  /**
   * Record that [method] is called from a subclass via `super`.
   */
  bool maybeRegisterAliasedSuperMember(Element member, Selector selector) {
    if (!canUseAliasedSuperMember(member, selector)) {
      // Invoking a super getter isn't supported, this would require changes to
      // compact field descriptors in the emitter.
      // We also turn off this optimization in incremental compilation, to
      // avoid having to regenerate a method just because someone started
      // calling it through super.
      return false;
    }
    aliasedSuperMembers.add(member);
    return true;
  }

  bool canUseAliasedSuperMember(Element member, Selector selector) {
    return !selector.isGetter && !compiler.options.hasIncrementalSupport;
  }

  /**
   * Returns `true` if [member] is called from a subclass via `super`.
   */
  bool isAliasedSuperMember(FunctionElement member) {
    return aliasedSuperMembers.contains(member);
  }

  /// Returns `true` if [element] is part of JsInterop.
  @override
  bool isJsInterop(Element element) => nativeData.isJsInterop(element);

  /// Whether [element] corresponds to a native JavaScript construct either
  /// through the native mechanism (`@Native(...)` or the `native` pseudo
  /// keyword) which is only allowed for internal libraries or via the typed
  /// JavaScriptInterop mechanism which is allowed for user libraries.
  @override
  bool isNative(Element element) => nativeData.isNative(element);

  bool isNativeOrExtendsNative(ClassElement element) {
    if (element == null) return false;
    if (isNative(element) || isJsInterop(element)) {
      return true;
    }
    assert(element.isResolved);
    return isNativeOrExtendsNative(element.superclass);
  }

  bool isInterceptedMethod(Element element) {
    if (!element.isInstanceMember) return false;
    if (element.isGenerativeConstructorBody) {
      return isNativeOrExtendsNative(element.enclosingClass);
    }
    return interceptedElements[element.name] != null;
  }

  bool fieldHasInterceptedGetter(Element element) {
    assert(element.isField);
    return interceptedElements[element.name] != null;
  }

  bool fieldHasInterceptedSetter(Element element) {
    assert(element.isField);
    return interceptedElements[element.name] != null;
  }

  bool isInterceptedName(String name) {
    return interceptedElements[name] != null;
  }

  bool isInterceptedSelector(Selector selector) {
    return interceptedElements[selector.name] != null;
  }

  /**
   * Returns `true` iff [selector] matches an element defined in a class mixed
   * into an intercepted class.  These selectors are not eligible for the 'dummy
   * explicit receiver' optimization.
   */
  bool isInterceptedMixinSelector(Selector selector, TypeMask mask) {
    Set<Element> elements = interceptedMixinElements.putIfAbsent(
        selector.name,
        () {
          Set<Element> elements = interceptedElements[selector.name];
          if (elements == null) return null;
          return elements
              .where((element) =>
                  classesMixedIntoInterceptedClasses.contains(
                      element.enclosingClass))
              .toSet();
        });

    if (elements == null) return false;
    if (elements.isEmpty) return false;
    return elements.any((element) {
      return selector.applies(element, compiler.world) &&
             (mask == null || mask.canHit(element, selector, compiler.world));
    });
  }

  /// True if the given class is an internal class used for type inference
  /// and never exists at runtime.
  bool isCompileTimeOnlyClass(ClassElement class_) {
    return class_ == helpers.jsPositiveIntClass ||
           class_ == helpers.jsUInt32Class ||
           class_ == helpers.jsUInt31Class ||
           class_ == helpers.jsFixedArrayClass ||
           class_ == helpers.jsUnmodifiableArrayClass ||
           class_ == helpers.jsMutableArrayClass ||
           class_ == helpers.jsExtendableArrayClass;
  }

  /// Maps compile-time classes to their runtime class.  The runtime class is
  /// always a superclass or the class itself.
  ClassElement getRuntimeClass(ClassElement class_) {
    if (class_.isSubclassOf(helpers.jsIntClass)) return helpers.jsIntClass;
    if (class_.isSubclassOf(helpers.jsArrayClass)) return helpers.jsArrayClass;
    return class_;
  }

  final Map<String, Set<ClassElement>> interceptedClassesCache =
      new Map<String, Set<ClassElement>>();
  final Set<ClassElement> _noClasses = new Set<ClassElement>();

  /// Returns a set of interceptor classes that contain a member named [name]
  ///
  /// Returns an empty set if there is no class. Do not modify the returned set.
  Set<ClassElement> getInterceptedClassesOn(String name) {
    Set<Element> intercepted = interceptedElements[name];
    if (intercepted == null) return _noClasses;
    return interceptedClassesCache.putIfAbsent(name, () {
      // Populate the cache by running through all the elements and
      // determine if the given selector applies to them.
      Set<ClassElement> result = new Set<ClassElement>();
      for (Element element in intercepted) {
        ClassElement classElement = element.enclosingClass;
        if (isCompileTimeOnlyClass(classElement)) continue;
        if (isNativeOrExtendsNative(classElement)
            || interceptedClasses.contains(classElement)) {
          result.add(classElement);
        }
        if (classesMixedIntoInterceptedClasses.contains(classElement)) {
          Set<ClassElement> nativeSubclasses =
              nativeSubclassesOfMixin(classElement);
          if (nativeSubclasses != null) result.addAll(nativeSubclasses);
        }
      }
      return result;
    });
  }

  Set<ClassElement> nativeSubclassesOfMixin(ClassElement mixin) {
    ClassWorld classWorld = compiler.world;
    Iterable<MixinApplicationElement> uses = classWorld.mixinUsesOf(mixin);
    Set<ClassElement> result = null;
    for (MixinApplicationElement use in uses) {
      classWorld.forEachStrictSubclassOf(use, (ClassElement subclass) {
        if (isNativeOrExtendsNative(subclass)) {
          if (result == null) result = new Set<ClassElement>();
          result.add(subclass);
        }
      });
    }
    return result;
  }

  bool operatorEqHandlesNullArgument(FunctionElement operatorEqfunction) {
    return specialOperatorEqClasses.contains(
        operatorEqfunction.enclosingClass);
  }

  void validateInterceptorImplementsAllObjectMethods(
      ClassElement interceptorClass) {
    if (interceptorClass == null) return;
    interceptorClass.ensureResolved(resolution);
    coreClasses.objectClass.forEachMember((_, Element member) {
      if (member.isGenerativeConstructor) return;
      Element interceptorMember = interceptorClass.lookupMember(member.name);
      // Interceptors must override all Object methods due to calling convention
      // differences.
      assert(invariant(
          interceptorMember,
          interceptorMember.enclosingClass == interceptorClass,
          message:
            "Member ${member.name} not overridden in ${interceptorClass}. "
            "Found $interceptorMember from "
            "${interceptorMember.enclosingClass}."));
    });
  }

  void addInterceptorsForNativeClassMembers(
      ClassElement cls, Enqueuer enqueuer) {
    if (enqueuer.isResolutionQueue) {
      cls.ensureResolved(resolution);
      cls.forEachMember((ClassElement classElement, Element member) {
        if (member.name == Identifiers.call) {
          reporter.reportErrorMessage(
              member,
              MessageKind.CALL_NOT_SUPPORTED_ON_NATIVE_CLASS);
          return;
        }
        if (member.isSynthesized) return;
        // All methods on [Object] are shadowed by [Interceptor].
        if (classElement == coreClasses.objectClass) return;
        Set<Element> set = interceptedElements.putIfAbsent(
            member.name, () => new Set<Element>());
        set.add(member);
      },
      includeSuperAndInjectedMembers: true);

      // Walk superclass chain to find mixins.
      for (; cls != null; cls = cls.superclass) {
        if (cls.isMixinApplication) {
          MixinApplicationElement mixinApplication = cls;
          classesMixedIntoInterceptedClasses.add(mixinApplication.mixin);
        }
      }
    }
  }

  void addInterceptors(ClassElement cls,
                       Enqueuer enqueuer,
                       Registry registry) {
    if (enqueuer.isResolutionQueue) {
      _interceptedClasses.add(helpers.jsInterceptorClass);
      _interceptedClasses.add(cls);
      cls.ensureResolved(resolution);
      cls.forEachMember((ClassElement classElement, Element member) {
          // All methods on [Object] are shadowed by [Interceptor].
          if (classElement == coreClasses.objectClass) return;
          Set<Element> set = interceptedElements.putIfAbsent(
              member.name, () => new Set<Element>());
          set.add(member);
        },
        includeSuperAndInjectedMembers: true);
    }
    enqueueClass(enqueuer, cls, registry);
  }

  Set<ClassElement> get interceptedClasses {
    assert(compiler.enqueuer.resolution.queueIsClosed);
    return _interceptedClasses;
  }

  void registerSpecializedGetInterceptor(Set<ClassElement> classes) {
    jsAst.Name name = namer.nameForGetInterceptor(classes);
    if (classes.contains(helpers.jsInterceptorClass)) {
      // We can't use a specialized [getInterceptorMethod], so we make
      // sure we emit the one with all checks.
      specializedGetInterceptors[name] = interceptedClasses;
    } else {
      specializedGetInterceptors[name] = classes;
    }
  }

  void registerCompileTimeConstant(ConstantValue constant, Registry registry) {
    registerCompileTimeConstantInternal(constant, registry);

    if (!registry.isForResolution &&
        lookupMapAnalysis.isLookupMap(constant)) {
      // Note: internally, this registration will temporarily remove the
      // constant dependencies and add them later on-demand.
      lookupMapAnalysis.registerLookupMapReference(constant);
    }

    for (ConstantValue dependency in constant.getDependencies()) {
      registerCompileTimeConstant(dependency, registry);
    }
  }

  void addCompileTimeConstantForEmission(ConstantValue constant) {
    constants.addCompileTimeConstantForEmission(constant);
  }

  void registerCompileTimeConstantInternal(ConstantValue constant,
                                           Registry registry) {
    DartType type = constant.getType(compiler.coreTypes);
    registerInstantiatedConstantType(type, registry);

    if (constant.isFunction) {
      FunctionConstantValue function = constant;
      registry.registerStaticUse(new StaticUse.staticTearOff(function.element));
    } else if (constant.isInterceptor) {
      // An interceptor constant references the class's prototype chain.
      InterceptorConstantValue interceptor = constant;
      registerInstantiatedConstantType(interceptor.dispatchedType, registry);
    } else if (constant.isType) {
      enqueueInResolution(helpers.createRuntimeType, registry);
      registry.registerInstantiation(typeImplementation.rawType);
    }
    lookupMapAnalysis.registerConstantKey(constant);
  }

  void registerInstantiatedConstantType(DartType type, Registry registry) {
    DartType instantiatedType =
        type.isFunctionType ? coreTypes.functionType : type;
    if (type is InterfaceType) {
      registry.registerInstantiation(instantiatedType);
      if (!type.treatAsRaw && classNeedsRti(type.element)) {
        registry.registerStaticUse(
            new StaticUse.staticInvoke(
                // TODO(johnniwinther): Find the right [CallStructure].
                helpers.setRuntimeTypeInfo, null));
      }
      if (type.element == typeImplementation) {
        // If we use a type literal in a constant, the compile time
        // constant emitter will generate a call to the createRuntimeType
        // helper so we register a use of that.
        registry.registerStaticUse(
            new StaticUse.staticInvoke(
                // TODO(johnniwinther): Find the right [CallStructure].

                helpers.createRuntimeType, null));
      }
    }
  }

  void registerMetadataConstant(MetadataAnnotation metadata,
                                Element annotatedElement,
                                Registry registry) {
    assert(registry.isForResolution);
    ConstantValue constant = constants.getConstantValueForMetadata(metadata);
    registerCompileTimeConstant(constant, registry);
    metadataConstants.add(new Dependency(constant, annotatedElement));
  }

  void registerInstantiatedClass(ClassElement cls,
                                 Enqueuer enqueuer,
                                 Registry registry) {
    _processClass(cls, enqueuer, registry);
  }

  void registerImplementedClass(ClassElement cls,
                                Enqueuer enqueuer,
                                Registry registry) {
    _processClass(cls, enqueuer, registry);
  }

  void _processClass(ClassElement cls,
                     Enqueuer enqueuer,
                     Registry registry) {
    if (!cls.typeVariables.isEmpty) {
      typeVariableHandler.registerClassWithTypeVariables(cls, enqueuer,
                                                         registry);
    }

    // Register any helper that will be needed by the backend.
    if (enqueuer.isResolutionQueue) {
      if (cls == coreClasses.intClass ||
          cls == coreClasses.doubleClass ||
          cls == coreClasses.numClass) {
        // The backend will try to optimize number operations and use the
        // `iae` helper directly.
        enqueue(enqueuer, helpers.throwIllegalArgumentException, registry);
      } else if (cls == coreClasses.listClass ||
                 cls == coreClasses.stringClass) {
        // The backend will try to optimize array and string access and use the
        // `ioore` and `iae` helpers directly.
        enqueue(enqueuer, helpers.throwIndexOutOfRangeException, registry);
        enqueue(enqueuer, helpers.throwIllegalArgumentException, registry);
      } else if (cls == coreClasses.functionClass) {
        enqueueClass(enqueuer, helpers.closureClass, registry);
      } else if (cls == coreClasses.mapClass) {
        // The backend will use a literal list to initialize the entries
        // of the map.
        enqueueClass(enqueuer, coreClasses.listClass, registry);
        enqueueClass(enqueuer, helpers.mapLiteralClass, registry);
        // For map literals, the dependency between the implementation class
        // and [Map] is not visible, so we have to add it manually.
        rti.registerRtiDependency(helpers.mapLiteralClass, cls);
      } else if (cls == helpers.boundClosureClass) {
        // TODO(johnniwinther): Is this a noop?
        enqueueClass(enqueuer, helpers.boundClosureClass, registry);
      } else if (isNativeOrExtendsNative(cls)) {
        enqueue(enqueuer, helpers.getNativeInterceptorMethod, registry);
        enqueueClass(enqueuer, helpers.jsInterceptorClass,
            compiler.globalDependencies);
        enqueueClass(enqueuer, helpers.jsJavaScriptObjectClass, registry);
        enqueueClass(enqueuer, helpers.jsPlainJavaScriptObjectClass, registry);
        enqueueClass(enqueuer, helpers.jsJavaScriptFunctionClass, registry);
      } else if (cls == helpers.mapLiteralClass) {
        // For map literals, the dependency between the implementation class
        // and [Map] is not visible, so we have to add it manually.
        Element getFactory(String name, int arity) {
          // The constructor is on the patch class, but dart2js unit tests don't
          // have a patch class.
          ClassElement implementation = cls.implementation;
          ConstructorElement ctor = implementation.lookupConstructor(name);
          if (ctor == null ||
              (Name.isPrivateName(name) &&
               ctor.library != helpers.mapLiteralClass.library)) {
            reporter.internalError(
                helpers.mapLiteralClass,
                "Map literal class ${helpers.mapLiteralClass} missing "
                "'$name' constructor"
                "  ${helpers.mapLiteralClass.constructors}");
          }
          return ctor;
        }
        Element getMember(String name) {
          // The constructor is on the patch class, but dart2js unit tests don't
          // have a patch class.
          ClassElement implementation = cls.implementation;
          Element element = implementation.lookupLocalMember(name);
          if (element == null || !element.isFunction || !element.isStatic) {
            reporter.internalError(helpers.mapLiteralClass,
                "Map literal class ${helpers.mapLiteralClass} missing "
                "'$name' static member function");
          }
          return element;
        }
        helpers.mapLiteralConstructor = getFactory('_literal', 1);
        helpers.mapLiteralConstructorEmpty = getFactory('_empty', 0);
        enqueueInResolution(helpers.mapLiteralConstructor, registry);
        enqueueInResolution(helpers.mapLiteralConstructorEmpty, registry);

        helpers.mapLiteralUntypedMaker = getMember('_makeLiteral');
        helpers.mapLiteralUntypedEmptyMaker = getMember('_makeEmpty');
        enqueueInResolution(helpers.mapLiteralUntypedMaker, registry);
        enqueueInResolution(helpers.mapLiteralUntypedEmptyMaker, registry);
      }
    }
    if (cls == helpers.closureClass) {
      enqueue(enqueuer, helpers.closureFromTearOff, registry);
    }
    if (cls == coreClasses.stringClass ||
        cls == helpers.jsStringClass) {
      addInterceptors(helpers.jsStringClass, enqueuer, registry);
    } else if (cls == coreClasses.listClass ||
               cls == helpers.jsArrayClass ||
               cls == helpers.jsFixedArrayClass ||
               cls == helpers.jsExtendableArrayClass ||
               cls == helpers.jsUnmodifiableArrayClass) {
      addInterceptors(helpers.jsArrayClass, enqueuer, registry);
      addInterceptors(helpers.jsMutableArrayClass, enqueuer, registry);
      addInterceptors(helpers.jsFixedArrayClass, enqueuer, registry);
      addInterceptors(helpers.jsExtendableArrayClass, enqueuer, registry);
      addInterceptors(helpers.jsUnmodifiableArrayClass, enqueuer, registry);
      // Literal lists can be translated into calls to these functions:
      enqueueInResolution(helpers.jsArrayTypedConstructor, registry);
      enqueueInResolution(helpers.setRuntimeTypeInfo, registry);
      enqueueInResolution(helpers.getTypeArgumentByIndex, registry);
    } else if (cls == coreClasses.intClass ||
               cls == helpers.jsIntClass) {
      addInterceptors(helpers.jsIntClass, enqueuer, registry);
      addInterceptors(helpers.jsPositiveIntClass, enqueuer, registry);
      addInterceptors(helpers.jsUInt32Class, enqueuer, registry);
      addInterceptors(helpers.jsUInt31Class, enqueuer, registry);
      addInterceptors(helpers.jsNumberClass, enqueuer, registry);
    } else if (cls == coreClasses.doubleClass ||
               cls == helpers.jsDoubleClass) {
      addInterceptors(helpers.jsDoubleClass, enqueuer, registry);
      addInterceptors(helpers.jsNumberClass, enqueuer, registry);
    } else if (cls == coreClasses.boolClass ||
               cls == helpers.jsBoolClass) {
      addInterceptors(helpers.jsBoolClass, enqueuer, registry);
    } else if (cls == coreClasses.nullClass ||
               cls == helpers.jsNullClass) {
      addInterceptors(helpers.jsNullClass, enqueuer, registry);
    } else if (cls == coreClasses.numClass ||
               cls == helpers.jsNumberClass) {
      addInterceptors(helpers.jsIntClass, enqueuer, registry);
      addInterceptors(helpers.jsPositiveIntClass, enqueuer, registry);
      addInterceptors(helpers.jsUInt32Class, enqueuer, registry);
      addInterceptors(helpers.jsUInt31Class, enqueuer, registry);
      addInterceptors(helpers.jsDoubleClass, enqueuer, registry);
      addInterceptors(helpers.jsNumberClass, enqueuer, registry);
    } else if (cls == helpers.jsJavaScriptObjectClass) {
      addInterceptors(helpers.jsJavaScriptObjectClass, enqueuer, registry);
    } else if (cls == helpers.jsPlainJavaScriptObjectClass) {
      addInterceptors(helpers.jsPlainJavaScriptObjectClass, enqueuer, registry);
    } else if (cls == helpers.jsUnknownJavaScriptObjectClass) {
      addInterceptors(helpers.jsUnknownJavaScriptObjectClass, enqueuer, registry);
    } else if (cls == helpers.jsJavaScriptFunctionClass) {
      addInterceptors(helpers.jsJavaScriptFunctionClass, enqueuer, registry);
    } else if (isNativeOrExtendsNative(cls)) {
      addInterceptorsForNativeClassMembers(cls, enqueuer);
    } else if (cls == helpers.jsIndexingBehaviorInterface) {
      // These two helpers are used by the emitter and the codegen.
      // Because we cannot enqueue elements at the time of emission,
      // we make sure they are always generated.
      enqueue(enqueuer, helpers.isJsIndexable, registry);
    }

    customElementsAnalysis.registerInstantiatedClass(cls, enqueuer);
    if (!enqueuer.isResolutionQueue) {
      lookupMapAnalysis.registerInstantiatedClass(cls);
    }
  }

  void registerInstantiatedType(InterfaceType type,
                                Enqueuer enqueuer,
                                Registry registry,
                                {bool mirrorUsage: false}) {
    lookupMapAnalysis.registerInstantiatedType(type, registry);
    super.registerInstantiatedType(
        type, enqueuer, registry, mirrorUsage: mirrorUsage);
  }

  void registerUseInterceptor(Enqueuer enqueuer) {
    assert(!enqueuer.isResolutionQueue);
    if (!enqueuer.nativeEnqueuer.hasInstantiatedNativeClasses()) return;
    Registry registry = compiler.globalDependencies;
    enqueue(enqueuer, helpers.getNativeInterceptorMethod, registry);
    enqueueClass(enqueuer, helpers.jsJavaScriptObjectClass, registry);
    enqueueClass(enqueuer, helpers.jsPlainJavaScriptObjectClass, registry);
    enqueueClass(enqueuer, helpers.jsJavaScriptFunctionClass, registry);
    needToInitializeIsolateAffinityTag = true;
    needToInitializeDispatchProperty = true;
  }

  JavaScriptItemCompilationContext createItemCompilationContext() {
    return new JavaScriptItemCompilationContext();
  }

  void enqueueHelpers(ResolutionEnqueuer world, Registry registry) {
    assert(helpers.interceptorsLibrary != null);
    // TODO(ngeoffray): Not enqueuing those two classes currently make
    // the compiler potentially crash. However, any reasonable program
    // will instantiate those two classes.
    addInterceptors(helpers.jsBoolClass, world, registry);
    addInterceptors(helpers.jsNullClass, world, registry);
    if (compiler.options.enableTypeAssertions) {
      // Unconditionally register the helper that checks if the
      // expression in an if/while/for is a boolean.
      // TODO(ngeoffray): Should we have the resolver register those instead?
      Element e = helpers.boolConversionCheck;
      if (e != null) enqueue(world, e, registry);
    }

    if (TRACE_CALLS) {
      traceHelper = TRACE_METHOD == 'console'
          ? helpers.consoleTraceHelper : helpers.postTraceHelper;
      assert(traceHelper != null);
      enqueueInResolution(traceHelper, registry);
    }
    enqueueInResolution(helpers.assertUnreachableMethod, registry);
    registerCheckedModeHelpers(registry);
  }

  onResolutionComplete() {
    super.onResolutionComplete();
    computeMembersNeededForReflection();
    rti.computeClassesNeedingRti();
  }

  onTypeInferenceComplete() {
    super.onTypeInferenceComplete();
    noSuchMethodRegistry.onTypeInferenceComplete();
  }

  void registerGetRuntimeTypeArgument(Registry registry) {
    enqueueImpact(
        compiler.enqueuer.resolution,
        impacts.getRuntimeTypeArgument,
        registry);
  }

  void registerCallMethodWithFreeTypeVariables(
      Element callMethod,
      Enqueuer enqueuer,
      Registry registry) {
    if (enqueuer.isResolutionQueue || methodNeedsRti(callMethod)) {
      registerComputeSignature(enqueuer, registry);
    }
  }

  void registerClosureWithFreeTypeVariables(
      Element closure,
      Enqueuer enqueuer,
      Registry registry) {
    if (enqueuer.isResolutionQueue || methodNeedsRti(closure)) {
      registerComputeSignature(enqueuer, registry);
    }
    super.registerClosureWithFreeTypeVariables(closure, enqueuer, registry);
  }

  void registerBoundClosure(Enqueuer enqueuer) {
    helpers.boundClosureClass.ensureResolved(resolution);
    registerInstantiatedType(
        helpers.boundClosureClass.rawType,
        enqueuer,
        // Precise dependency is not important here.
        compiler.globalDependencies);
  }

  void registerGetOfStaticFunction(Enqueuer enqueuer) {
    helpers.closureClass.ensureResolved(resolution);
    registerInstantiatedType(
        helpers.closureClass.rawType,
        enqueuer,
        compiler.globalDependencies);
  }

  void registerComputeSignature(Enqueuer enqueuer, Registry registry) {
    // Calls to [:computeSignature:] are generated by the emitter and we
    // therefore need to enqueue the used elements in the codegen enqueuer as
    // well as in the resolution enqueuer.
    enqueueImpact(enqueuer, impacts.computeSignature, registry);
  }

  void registerRuntimeType(Enqueuer enqueuer, Registry registry) {
    registerComputeSignature(enqueuer, registry);
    enqueueInResolution(helpers.setRuntimeTypeInfo, registry);
    registerGetRuntimeTypeArgument(registry);
    enqueueInResolution(helpers.getRuntimeTypeInfo, registry);
    enqueueClass(enqueuer, coreClasses.listClass, registry);
  }

  void registerTypeVariableBoundsSubtypeCheck(DartType typeArgument,
                                              DartType bound) {
    rti.registerTypeVariableBoundsSubtypeCheck(typeArgument, bound);
  }

  void registerCheckDeferredIsLoaded(Registry registry) {
    enqueueInResolution(helpers.checkDeferredIsLoaded, registry);
    // Also register the types of the arguments passed to this method.
    enqueueClass(
        compiler.enqueuer.resolution, coreClasses.stringClass, registry);
  }

  void registerNoSuchMethod(FunctionElement noSuchMethod) {
    noSuchMethodRegistry.registerNoSuchMethod(noSuchMethod);
  }

  /// Called when resolving a call to a foreign function.
  void registerForeignCall(Send node,
                           Element element,
                           CallStructure callStructure,
                           ForeignResolver resolver) {
    native.NativeResolutionEnqueuer nativeEnqueuer =
        compiler.enqueuer.resolution.nativeEnqueuer;
    if (element.name == 'JS') {
      nativeEnqueuer.registerJsCall(node, resolver);
    } else if (element.name == 'JS_EMBEDDED_GLOBAL') {
      nativeEnqueuer.registerJsEmbeddedGlobalCall(node, resolver);
    } else if (element.name == 'JS_BUILTIN') {
      nativeEnqueuer.registerJsBuiltinCall(node, resolver);
    } else if (element.name == 'JS_INTERCEPTOR_CONSTANT') {
      // The type constant that is an argument to JS_INTERCEPTOR_CONSTANT names
      // a class that will be instantiated outside the program by attaching a
      // native class dispatch record referencing the interceptor.
      if (!node.argumentsNode.isEmpty) {
        Node argument = node.argumentsNode.nodes.head;
        ConstantExpression constant = resolver.getConstant(argument);
        if (constant != null && constant.kind == ConstantExpressionKind.TYPE) {
          TypeConstantExpression typeConstant = constant;
          if (typeConstant.type is InterfaceType) {
            resolver.registerInstantiatedType(typeConstant.type);
            return;
          }
        }
      }
      reporter.reportErrorMessage(
          node,
          MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT);
    }
  }

  void enableNoSuchMethod(Enqueuer world) {
    enqueue(world, helpers.createInvocationMirror, compiler.globalDependencies);
    world.registerDynamicUse(
        new DynamicUse(Selectors.noSuchMethod_, null));
  }

  void enableIsolateSupport(Enqueuer enqueuer) {
    // TODO(floitsch): We should also ensure that the class IsolateMessage is
    // instantiated. Currently, just enabling isolate support works.
    if (compiler.mainFunction != null) {
      // The JavaScript backend implements [Isolate.spawn] by looking up
      // top-level functions by name. So all top-level function tear-off
      // closures have a private name field.
      //
      // The JavaScript backend of [Isolate.spawnUri] uses the same internal
      // implementation as [Isolate.spawn], and fails if it cannot look main up
      // by name.
      enqueuer.registerStaticUse(
          new StaticUse.staticTearOff(compiler.mainFunction));
    }
    if (enqueuer.isResolutionQueue) {

      void enqueue(Element element) {
        enqueuer.addToWorkList(element);
        compiler.globalDependencies.registerDependency(element);
        helpersUsed.add(element.declaration);
      }

      enqueue(helpers.startRootIsolate);
      enqueue(helpers.currentIsolate);
      enqueue(helpers.callInIsolate);
    } else {
      enqueuer.addToWorkList(helpers.startRootIsolate);
    }
  }

  bool classNeedsRti(ClassElement cls) {
    return rti.classesNeedingRti.contains(cls.declaration) ||
        compiler.enabledRuntimeType;
  }

  bool isComplexNoSuchMethod(FunctionElement element) =>
    noSuchMethodRegistry.isComplex(element);

  bool isDefaultEqualityImplementation(Element element) {
    assert(element.name == '==');
    ClassElement classElement = element.enclosingClass;
    return classElement == coreClasses.objectClass
        || classElement == helpers.jsInterceptorClass
        || classElement == helpers.jsNullClass;
  }

  bool methodNeedsRti(FunctionElement function) {
    return rti.methodsNeedingRti.contains(function) ||
           compiler.enabledRuntimeType;
  }

  /// Enqueue [e] in [enqueuer].
  ///
  /// This method calls [registerBackendUse].
  void enqueue(Enqueuer enqueuer, Element e, Registry registry) {
    if (e == null) return;
    registerBackendUse(e);
    enqueuer.addToWorkList(e);
    registry.registerDependency(e);
  }

  /// Enqueue [e] in the resolution enqueuer.
  ///
  /// This method calls [registerBackendUse].
  void enqueueInResolution(Element e, Registry registry) {
    if (e == null) return;
    ResolutionEnqueuer enqueuer = compiler.enqueuer.resolution;
    enqueue(enqueuer, e, registry);
  }

  /// Register instantiation of [cls] in [enqueuer].
  ///
  /// This method calls [registerBackendUse].
  void enqueueClass(Enqueuer enqueuer, ClassElement cls, Registry registry) {
    if (cls == null) return;
    registerBackendUse(cls);
    helpersUsed.add(cls.declaration);
    if (cls.declaration != cls.implementation) {
      helpersUsed.add(cls.implementation);
    }
    cls.ensureResolved(resolution);
    registerInstantiatedType(cls.rawType, enqueuer, registry);
  }

  /// Register instantiation of [type] in [enqueuer].
  ///
  /// This method calls [registerBackendUse].
  void enqueueType(Enqueuer enqueuer, InterfaceType type, Registry registry) {
    if (type == null) return;
    ClassElement cls = type.element;
    registerBackendUse(cls);
    helpersUsed.add(cls.declaration);
    if (cls.declaration != cls.implementation) {
      helpersUsed.add(cls.implementation);
    }
    cls.ensureResolved(resolution);
    registerInstantiatedType(type, enqueuer, registry);
  }

  void enqueueImpact(Enqueuer enqueuer,
                     BackendImpact impact,
                     Registry registry) {
    for (Element staticUse in impact.staticUses) {
      enqueue(enqueuer, staticUse, registry);
    }
    for (InterfaceType type in impact.instantiatedTypes) {
      enqueueType(enqueuer, type, registry);
    }
    for (ClassElement cls in impact.instantiatedClasses) {
      enqueueClass(enqueuer, cls, registry);
    }
    for (BackendImpact otherImpact in impact.otherImpacts) {
      enqueueImpact(enqueuer, otherImpact, registry);
    }
  }

  WorldImpact codegen(CodegenWorkItem work) {
    Element element = work.element;
    if (compiler.elementHasCompileTimeError(element)) {
      generatedCode[element] = jsAst.js(
          "function () { throw new Error('Compile time error in $element') }");
      return const CodegenImpact();
    }
    var kind = element.kind;
    if (kind == ElementKind.TYPEDEF) {
      return const WorldImpact();
    }
    if (element.isConstructor &&
        element.enclosingClass == helpers.jsNullClass) {
      // Work around a problem compiling JSNull's constructor.
      return const CodegenImpact();
    }
    if (kind.category == ElementCategory.VARIABLE) {
      ConstantValue initialValue =
          constants.getConstantValueForVariable(element);
      if (initialValue != null) {
        registerCompileTimeConstant(initialValue, work.registry);
        addCompileTimeConstantForEmission(initialValue);
        // We don't need to generate code for static or top-level
        // variables. For instance variables, we may need to generate
        // the checked setter.
        if (Elements.isStaticOrTopLevel(element)) {
          return impactTransformer.transformCodegenImpact(
              work.registry.worldImpact);
        }
      } else {
        // If the constant-handler was not able to produce a result we have to
        // go through the builder (below) to generate the lazy initializer for
        // the static variable.
        // We also need to register the use of the cyclic-error helper.
        compiler.enqueuer.codegen.registerStaticUse(
            new StaticUse.staticInvoke(
                helpers.cyclicThrowHelper, CallStructure.ONE_ARG));
      }
    }

    jsAst.Fun function = functionCompiler.compile(work);
    if (function.sourceInformation == null) {
      function = function.withSourceInformation(
          sourceInformationStrategy.buildSourceMappedMarker());
    }
    generatedCode[element] = function;
    WorldImpact worldImpact =
        impactTransformer.transformCodegenImpact(work.registry.worldImpact);
    compiler.dumpInfoTask.registerImpact(element, worldImpact);
    return worldImpact;
  }

  native.NativeEnqueuer nativeResolutionEnqueuer(Enqueuer world) {
    return new native.NativeResolutionEnqueuer(world, compiler);
  }

  native.NativeEnqueuer nativeCodegenEnqueuer(Enqueuer world) {
    return new native.NativeCodegenEnqueuer(world, compiler, emitter);
  }

  ClassElement defaultSuperclass(ClassElement element) {
    if (isJsInterop(element)) {
      return helpers.jsJavaScriptObjectClass;
    }
    // Native classes inherit from Interceptor.
    return isNative(element)
        ? helpers.jsInterceptorClass : coreClasses.objectClass;
  }

  /**
   * Unit test hook that returns code of an element as a String.
   *
   * Invariant: [element] must be a declaration element.
   */
  String getGeneratedCode(Element element) {
    assert(invariant(element, element.isDeclaration));
    return jsAst.prettyPrint(generatedCode[element], compiler);
  }

  int assembleProgram() {
    int programSize = emitter.assembleProgram();
    noSuchMethodRegistry.emitDiagnostic();
    int totalMethodCount = generatedCode.length;
    if (totalMethodCount != preMirrorsMethodCount) {
      int mirrorCount = totalMethodCount - preMirrorsMethodCount;
      double percentage = (mirrorCount / totalMethodCount) * 100;
      DiagnosticMessage hint = reporter.createMessage(
          compiler.mainApp, MessageKind.MIRROR_BLOAT,
          {'count': mirrorCount,
           'total': totalMethodCount,
           'percentage': percentage.round()});

      List<DiagnosticMessage> infos = <DiagnosticMessage>[];
      for (LibraryElement library in compiler.libraryLoader.libraries) {
        if (library.isInternalLibrary) continue;
        for (ImportElement import in library.imports) {
          LibraryElement importedLibrary = import.importedLibrary;
          if (importedLibrary != compiler.mirrorsLibrary) continue;
          MessageKind kind =
              compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(library)
              ? MessageKind.MIRROR_IMPORT
              : MessageKind.MIRROR_IMPORT_NO_USAGE;
          reporter.withCurrentElement(library, () {
            infos.add(reporter.createMessage(import, kind));
          });
        }
      }
      reporter.reportHint(hint, infos);
    }
    return programSize;
  }

  Element getDartClass(Element element) {
    for (ClassElement dartClass in implementationClasses.keys) {
      if (element == implementationClasses[dartClass]) {
        return dartClass;
      }
    }
    return element;
  }

  /**
   * Returns the checked mode helper that will be needed to do a type check/type
   * cast on [type] at runtime. Note that this method is being called both by
   * the resolver with interface types (int, String, ...), and by the SSA
   * backend with implementation types (JSInt, JSString, ...).
   */
  CheckedModeHelper getCheckedModeHelper(DartType type, {bool typeCast}) {
    return getCheckedModeHelperInternal(
        type, typeCast: typeCast, nativeCheckOnly: false);
  }

  /**
   * Returns the native checked mode helper that will be needed to do a type
   * check/type cast on [type] at runtime. If no native helper exists for
   * [type], [:null:] is returned.
   */
  CheckedModeHelper getNativeCheckedModeHelper(DartType type, {bool typeCast}) {
    return getCheckedModeHelperInternal(
        type, typeCast: typeCast, nativeCheckOnly: true);
  }

  /**
   * Returns the checked mode helper for the type check/type cast for [type]. If
   * [nativeCheckOnly] is [:true:], only names for native helpers are returned.
   */
  CheckedModeHelper getCheckedModeHelperInternal(DartType type,
                                                 {bool typeCast,
                                                  bool nativeCheckOnly}) {
    String name = getCheckedModeHelperNameInternal(type,
        typeCast: typeCast, nativeCheckOnly: nativeCheckOnly);
    if (name == null) return null;
    CheckedModeHelper helper = checkedModeHelperByName[name];
    assert(helper != null);
    return helper;
  }

  String getCheckedModeHelperNameInternal(DartType type,
                                          {bool typeCast,
                                           bool nativeCheckOnly}) {
    assert(type.kind != TypeKind.TYPEDEF);
    if (type.isMalformed) {
      // The same error is thrown for type test and type cast of a malformed
      // type so we only need one check method.
      return 'checkMalformedType';
    }
    Element element = type.element;
    bool nativeCheck = nativeCheckOnly ||
        emitter.nativeEmitter.requiresNativeIsCheck(element);

    // TODO(13955), TODO(9731).  The test for non-primitive types should use an
    // interceptor.  The interceptor should be an argument to HTypeConversion so
    // that it can be optimized by standard interceptor optimizations.
    nativeCheck = true;

    if (type.isVoid) {
      assert(!typeCast); // Cannot cast to void.
      if (nativeCheckOnly) return null;
      return 'voidTypeCheck';
    } else if (element == helpers.jsStringClass ||
               element == coreClasses.stringClass) {
      if (nativeCheckOnly) return null;
      return typeCast
          ? 'stringTypeCast'
          : 'stringTypeCheck';
    } else if (element == helpers.jsDoubleClass ||
               element == coreClasses.doubleClass) {
      if (nativeCheckOnly) return null;
      return typeCast
          ? 'doubleTypeCast'
          : 'doubleTypeCheck';
    } else if (element == helpers.jsNumberClass ||
               element == coreClasses.numClass) {
      if (nativeCheckOnly) return null;
      return typeCast
          ? 'numTypeCast'
          : 'numTypeCheck';
    } else if (element == helpers.jsBoolClass ||
               element == coreClasses.boolClass) {
      if (nativeCheckOnly) return null;
      return typeCast
          ? 'boolTypeCast'
          : 'boolTypeCheck';
    } else if (element == helpers.jsIntClass ||
               element == coreClasses.intClass ||
               element == helpers.jsUInt32Class ||
               element == helpers.jsUInt31Class ||
               element == helpers.jsPositiveIntClass) {
      if (nativeCheckOnly) return null;
      return typeCast
          ? 'intTypeCast'
          : 'intTypeCheck';
    } else if (Elements.isNumberOrStringSupertype(element, compiler)) {
      if (nativeCheck) {
        return typeCast
            ? 'numberOrStringSuperNativeTypeCast'
            : 'numberOrStringSuperNativeTypeCheck';
      } else {
        return typeCast
          ? 'numberOrStringSuperTypeCast'
          : 'numberOrStringSuperTypeCheck';
      }
    } else if (Elements.isStringOnlySupertype(element, compiler)) {
      if (nativeCheck) {
        return typeCast
            ? 'stringSuperNativeTypeCast'
            : 'stringSuperNativeTypeCheck';
      } else {
        return typeCast
            ? 'stringSuperTypeCast'
            : 'stringSuperTypeCheck';
      }
    } else if ((element == coreClasses.listClass ||
                element == helpers.jsArrayClass) &&
               type.treatAsRaw) {
      if (nativeCheckOnly) return null;
      return typeCast
          ? 'listTypeCast'
          : 'listTypeCheck';
    } else {
      if (Elements.isListSupertype(element, compiler)) {
        if (nativeCheck) {
          return typeCast
              ? 'listSuperNativeTypeCast'
              : 'listSuperNativeTypeCheck';
        } else {
          return typeCast
              ? 'listSuperTypeCast'
              : 'listSuperTypeCheck';
        }
      } else {
        if (type.isInterfaceType && !type.treatAsRaw) {
          return typeCast
              ? 'subtypeCast'
              : 'assertSubtype';
        } else if (type.isTypeVariable) {
          return typeCast
              ? 'subtypeOfRuntimeTypeCast'
              : 'assertSubtypeOfRuntimeType';
        } else if (type.isFunctionType) {
          return null;
        } else {
          if (nativeCheck) {
            // TODO(karlklose): can we get rid of this branch when we use
            // interceptors?
            return typeCast
                ? 'interceptedTypeCast'
                : 'interceptedTypeCheck';
          } else {
            return typeCast
                ? 'propertyTypeCast'
                : 'propertyTypeCheck';
          }
        }
      }
    }
  }

  void registerCheckedModeHelpers(Registry registry) {
    // We register all the helpers in the resolution queue.
    // TODO(13155): Find a way to register fewer helpers.
    for (CheckedModeHelper helper in checkedModeHelpers) {
      enqueueInResolution(helper.getStaticUse(compiler).element, registry);
    }
  }

  /**
   * Returns [:true:] if the checking of [type] is performed directly on the
   * object and not on an interceptor.
   */
  bool hasDirectCheckFor(DartType type) {
    Element element = type.element;
    return element == coreClasses.stringClass ||
        element == coreClasses.boolClass ||
        element == coreClasses.numClass ||
        element == coreClasses.intClass ||
        element == coreClasses.doubleClass ||
        element == helpers.jsArrayClass ||
        element == helpers.jsMutableArrayClass ||
        element == helpers.jsExtendableArrayClass ||
        element == helpers.jsFixedArrayClass ||
        element == helpers.jsUnmodifiableArrayClass;
  }

  bool mayGenerateInstanceofCheck(DartType type) {
    // We can use an instanceof check for raw types that have no subclass that
    // is mixed-in or in an implements clause.

    if (!type.isRaw) return false;
    ClassElement classElement = type.element;
    if (isInterceptorClass(classElement)) return false;
    return compiler.world.hasOnlySubclasses(classElement);
  }

  bool isNullImplementation(ClassElement cls) {
    return cls == helpers.jsNullClass;
  }

  ClassElement get intImplementation => helpers.jsIntClass;
  ClassElement get uint32Implementation => helpers.jsUInt32Class;
  ClassElement get uint31Implementation => helpers.jsUInt31Class;
  ClassElement get positiveIntImplementation => helpers.jsPositiveIntClass;
  ClassElement get doubleImplementation => helpers.jsDoubleClass;
  ClassElement get numImplementation => helpers.jsNumberClass;
  ClassElement get stringImplementation => helpers.jsStringClass;
  ClassElement get listImplementation => helpers.jsArrayClass;
  ClassElement get constListImplementation => helpers.jsUnmodifiableArrayClass;
  ClassElement get fixedListImplementation => helpers.jsFixedArrayClass;
  ClassElement get growableListImplementation => helpers.jsExtendableArrayClass;
  ClassElement get mapImplementation => helpers.mapLiteralClass;
  ClassElement get constMapImplementation => helpers.constMapLiteralClass;
  ClassElement get typeImplementation => helpers.typeLiteralClass;
  ClassElement get boolImplementation => helpers.jsBoolClass;
  ClassElement get nullImplementation => helpers.jsNullClass;
  ClassElement get syncStarIterableImplementation => helpers.syncStarIterable;
  ClassElement get asyncFutureImplementation => helpers.futureImplementation;
  ClassElement get asyncStarStreamImplementation => helpers.controllerStream;

  void registerStaticUse(Element element, Enqueuer enqueuer) {
    if (element == helpers.disableTreeShakingMarker) {
      isTreeShakingDisabled = true;
    } else if (element == helpers.preserveNamesMarker) {
      mustPreserveNames = true;
    } else if (element == helpers.preserveMetadataMarker) {
      mustRetainMetadata = true;
    } else if (element == helpers.preserveUrisMarker) {
      if (compiler.options.preserveUris) mustPreserveUris = true;
    } else if (element == helpers.preserveLibraryNamesMarker) {
      mustRetainLibraryNames = true;
    } else if (element == helpers.getIsolateAffinityTagMarker) {
      needToInitializeIsolateAffinityTag = true;
    } else if (element.isDeferredLoaderGetter) {
      // TODO(sigurdm): Create a function registerLoadLibraryAccess.
      if (compiler.loadLibraryFunction == null) {
        compiler.loadLibraryFunction = helpers.loadLibraryWrapper;
        enqueueInResolution(compiler.loadLibraryFunction,
                            compiler.globalDependencies);
      }
    } else if (element == helpers.requiresPreambleMarker) {
      requiresPreamble = true;
    }
    customElementsAnalysis.registerStaticUse(element, enqueuer);
  }

  /// Called when [:const Symbol(name):] is seen.
  void registerConstSymbol(String name) {
    symbolsUsed.add(name);
    if (name.endsWith('=')) {
      symbolsUsed.add(name.substring(0, name.length - 1));
    }
  }

  /// Called when [:new Symbol(...):] is seen.
  void registerNewSymbol(Registry registry) {
  }

  /// Should [element] (a getter) that would normally not be generated due to
  /// treeshaking be retained for reflection?
  bool shouldRetainGetter(Element element) {
    return isTreeShakingDisabled && isAccessibleByReflection(element);
  }

  /// Should [element] (a setter) hat would normally not be generated due to
  /// treeshaking be retained for reflection?
  bool shouldRetainSetter(Element element) {
    return isTreeShakingDisabled && isAccessibleByReflection(element);
  }

  /// Should [name] be retained for reflection?
  bool shouldRetainName(String name) {
    if (hasInsufficientMirrorsUsed) return mustPreserveNames;
    if (name == '') return false;
    return symbolsUsed.contains(name);
  }

  bool retainMetadataOf(Element element) {
    if (mustRetainMetadata) hasRetainedMetadata = true;
    if (mustRetainMetadata && referencedFromMirrorSystem(element)) {
      for (MetadataAnnotation metadata in element.metadata) {
        metadata.ensureResolved(resolution);
        ConstantValue constant =
            constants.getConstantValueForMetadata(metadata);
        constants.addCompileTimeConstantForEmission(constant);
      }
      return true;
    }
    return false;
  }

  void onLibraryCreated(LibraryElement library) {
    helpers.onLibraryCreated(library);
  }

  Future onLibraryScanned(LibraryElement library, LibraryLoader loader) {
    return super.onLibraryScanned(library, loader).then((_) {
      if (library.isPlatformLibrary &&
          // Don't patch library currently disallowed.
          !library.isSynthesized &&
          !library.isPatched) {
        // Apply patch, if any.
        Uri patchUri = compiler.resolvePatchUri(library.canonicalUri.path);
        if (patchUri != null) {
          return compiler.patchParser.patchLibrary(loader, patchUri, library);
        }
      }
    }).then((_) {
      helpers.onLibraryScanned(library);
      Uri uri = library.canonicalUri;
      if (uri == Uris.dart_html) {
        htmlLibraryIsLoaded = true;
      } else if (uri == LookupMapAnalysis.PACKAGE_LOOKUP_MAP) {
        lookupMapAnalysis.init(library);
      }
      annotations.onLibraryScanned(library);
    });
  }

  Future onLibrariesLoaded(LoadedLibraries loadedLibraries) {
    if (!loadedLibraries.containsLibrary(Uris.dart_core)) {
      return new Future.value();
    }

    helpers.onLibrariesLoaded(loadedLibraries);

    implementationClasses = <ClassElement, ClassElement>{};
    implementationClasses[coreClasses.intClass] = helpers.jsIntClass;
    implementationClasses[coreClasses.boolClass] = helpers.jsBoolClass;
    implementationClasses[coreClasses.numClass] = helpers.jsNumberClass;
    implementationClasses[coreClasses.doubleClass] = helpers.jsDoubleClass;
    implementationClasses[coreClasses.stringClass] = helpers.jsStringClass;
    implementationClasses[coreClasses.listClass] = helpers.jsArrayClass;
    implementationClasses[coreClasses.nullClass] = helpers.jsNullClass;

    // These methods are overwritten with generated versions.
    inlineCache.markAsNonInlinable(
        helpers.getInterceptorMethod, insideLoop: true);

    specialOperatorEqClasses
        ..add(coreClasses.objectClass)
        ..add(helpers.jsInterceptorClass)
        ..add(helpers.jsNullClass);

    validateInterceptorImplementsAllObjectMethods(helpers.jsInterceptorClass);
    // The null-interceptor must also implement *all* methods.
    validateInterceptorImplementsAllObjectMethods(helpers.jsNullClass);

    return new Future.value();
  }

  void registerMirrorUsage(Set<String> symbols,
                           Set<Element> targets,
                           Set<Element> metaTargets) {
    if (symbols == null && targets == null && metaTargets == null) {
      // The user didn't specify anything, or there are imports of
      // 'dart:mirrors' without @MirrorsUsed.
      hasInsufficientMirrorsUsed = true;
      return;
    }
    if (symbols != null) symbolsUsed.addAll(symbols);
    if (targets != null) {
      for (Element target in targets) {
        if (target.isAbstractField) {
          AbstractFieldElement field = target;
          targetsUsed.add(field.getter);
          targetsUsed.add(field.setter);
        } else {
          targetsUsed.add(target);
        }
      }
    }
    if (metaTargets != null) metaTargetsUsed.addAll(metaTargets);
  }

  /**
   * Returns `true` if [element] can be accessed through reflection, that is,
   * is in the set of elements covered by a `MirrorsUsed` annotation.
   *
   * This property is used to tag emitted elements with a marker which is
   * checked by the runtime system to throw an exception if an element is
   * accessed (invoked, get, set) that is not accessible for the reflective
   * system.
   */
  bool isAccessibleByReflection(Element element) {
    if (element.isClass) {
      element = getDartClass(element);
    }
    return membersNeededForReflection.contains(element);
  }

  /**
   * Returns true if the element has to be resolved due to a mirrorsUsed
   * annotation. If we have insufficient mirrors used annotations, we only
   * keep additonal elements if treeshaking has been disabled.
   */
  bool requiredByMirrorSystem(Element element) {
    return hasInsufficientMirrorsUsed && isTreeShakingDisabled ||
           matchesMirrorsMetaTarget(element) ||
           targetsUsed.contains(element);
  }

  /**
   * Returns true if the element matches a mirrorsUsed annotation. If
   * we have insufficient mirrorsUsed information, this returns true for
   * all elements, as they might all be potentially referenced.
   */
  bool referencedFromMirrorSystem(Element element, [recursive = true]) {
    Element enclosing = recursive ? element.enclosingElement : null;

    return hasInsufficientMirrorsUsed ||
           matchesMirrorsMetaTarget(element) ||
           targetsUsed.contains(element) ||
           (enclosing != null && referencedFromMirrorSystem(enclosing));
  }

  /**
   * Returns `true` if the element is needed because it has an annotation
   * of a type that is used as a meta target for reflection.
   */
  bool matchesMirrorsMetaTarget(Element element) {
    if (metaTargetsUsed.isEmpty) return false;
    for (MetadataAnnotation metadata in element.metadata) {
      // TODO(kasperl): It would be nice if we didn't have to resolve
      // all metadata but only stuff that potentially would match one
      // of the used meta targets.
      metadata.ensureResolved(resolution);
      ConstantValue value =
          compiler.constants.getConstantValue(metadata.constant);
      if (value == null) continue;
      DartType type = value.getType(compiler.coreTypes);
      if (metaTargetsUsed.contains(type.element)) return true;
    }
    return false;
  }

  /**
   * Visits all classes and computes whether its members are needed for
   * reflection.
   *
   * We have to precompute this set as we cannot easily answer the need for
   * reflection locally when looking at the member: We lack the information by
   * which classes a member is inherited. Called after resolution is complete.
   *
   * We filter out private libraries here, as their elements should not
   * be visible by reflection unless some other interfaces makes them
   * accessible.
   */
  computeMembersNeededForReflection() {
    if (_membersNeededForReflection != null) return;
    if (compiler.mirrorsLibrary == null) {
      _membersNeededForReflection = const ImmutableEmptySet<Element>();
      return;
    }
    // Compute a mapping from class to the closures it contains, so we
    // can include the correct ones when including the class.
    Map<ClassElement, List<LocalFunctionElement>> closureMap =
        new Map<ClassElement, List<LocalFunctionElement>>();
    for (LocalFunctionElement closure in compiler.resolverWorld.allClosures) {
      closureMap.putIfAbsent(closure.enclosingClass, () => []).add(closure);
    }
    bool foundClosure = false;
    Set<Element> reflectableMembers = new Set<Element>();
    ResolutionEnqueuer resolution = compiler.enqueuer.resolution;
    for (ClassElement cls in resolution.universe.directlyInstantiatedClasses) {
      // Do not process internal classes.
      if (cls.library.isInternalLibrary || cls.isInjected) continue;
      if (referencedFromMirrorSystem(cls)) {
        Set<Name> memberNames = new Set<Name>();
        // 1) the class (should be resolved)
        assert(invariant(cls, cls.isResolved));
        reflectableMembers.add(cls);
        // 2) its constructors (if resolved)
        cls.constructors.forEach((Element constructor) {
          if (resolution.hasBeenProcessed(constructor)) {
            reflectableMembers.add(constructor);
          }
        });
        // 3) all members, including fields via getter/setters (if resolved)
        cls.forEachClassMember((Member member) {
          if (resolution.hasBeenProcessed(member.element)) {
            memberNames.add(member.name);
            reflectableMembers.add(member.element);
          }
        });
        // 4) all overriding members of subclasses/subtypes (should be resolved)
        if (compiler.world.hasAnyStrictSubtype(cls)) {
          compiler.world.forEachStrictSubtypeOf(cls, (ClassElement subcls) {
            subcls.forEachClassMember((Member member) {
              if (memberNames.contains(member.name)) {
                // TODO(20993): find out why this assertion fails.
                // assert(invariant(member.element,
                //    resolution.hasBeenProcessed(member.element)));
                if (resolution.hasBeenProcessed(member.element)) {
                  reflectableMembers.add(member.element);
                }
              }
            });
          });
        }
        // 5) all its closures
        List<LocalFunctionElement> closures = closureMap[cls];
        if (closures != null) {
          reflectableMembers.addAll(closures);
          foundClosure = true;
        }
      } else {
        // check members themselves
        cls.constructors.forEach((ConstructorElement element) {
          if (!resolution.hasBeenProcessed(element)) return;
          if (referencedFromMirrorSystem(element, false)) {
            reflectableMembers.add(element);
          }
        });
        cls.forEachClassMember((Member member) {
          if (!resolution.hasBeenProcessed(member.element)) return;
          if (referencedFromMirrorSystem(member.element, false)) {
            reflectableMembers.add(member.element);
          }
        });
        // Also add in closures. Those might be reflectable is their enclosing
        // member is.
        List<LocalFunctionElement> closures = closureMap[cls];
        if (closures != null) {
          for (LocalFunctionElement closure in closures) {
            if (referencedFromMirrorSystem(closure.memberContext, false)) {
              reflectableMembers.add(closure);
              foundClosure = true;
            }
          }
        }
      }
    }
    // We also need top-level non-class elements like static functions and
    // global fields. We use the resolution queue to decide which elements are
    // part of the live world.
    for (LibraryElement lib in compiler.libraryLoader.libraries) {
      if (lib.isInternalLibrary) continue;
      lib.forEachLocalMember((Element member) {
        if (!member.isClass &&
            resolution.hasBeenProcessed(member) &&
            referencedFromMirrorSystem(member)) {
          reflectableMembers.add(member);
        }
      });
    }
    // And closures inside top-level elements that do not have a surrounding
    // class. These will be in the [:null:] bucket of the [closureMap].
    if (closureMap.containsKey(null)) {
      for (Element closure in closureMap[null]) {
        if (referencedFromMirrorSystem(closure)) {
          reflectableMembers.add(closure);
          foundClosure = true;
        }
      }
    }
    // As we do not think about closures as classes, yet, we have to make sure
    // their superclasses are available for reflection manually.
    if (foundClosure) {
      reflectableMembers.add(helpers.closureClass);
    }
    Set<Element> closurizedMembers = compiler.resolverWorld.closurizedMembers;
    if (closurizedMembers.any(reflectableMembers.contains)) {
      reflectableMembers.add(helpers.boundClosureClass);
    }
    // Add typedefs.
    reflectableMembers
        .addAll(compiler.world.allTypedefs.where(referencedFromMirrorSystem));
    // Register all symbols of reflectable elements
    for (Element element in reflectableMembers) {
      symbolsUsed.add(element.name);
    }
    _membersNeededForReflection = reflectableMembers;
  }

  // TODO(20791): compute closure classes after resolution and move this code to
  // [computeMembersNeededForReflection].
  void maybeMarkClosureAsNeededForReflection(
      ClosureClassElement globalizedElement,
      FunctionElement callFunction,
      FunctionElement function) {
    if (!_membersNeededForReflection.contains(function)) return;
    _membersNeededForReflection.add(callFunction);
    _membersNeededForReflection.add(globalizedElement);
  }

  jsAst.Call generateIsJsIndexableCall(jsAst.Expression use1,
                                       jsAst.Expression use2) {
    String dispatchPropertyName = embeddedNames.DISPATCH_PROPERTY_NAME;
    jsAst.Expression dispatchProperty =
        emitter.generateEmbeddedGlobalAccess(dispatchPropertyName);

    // We pass the dispatch property record to the isJsIndexable
    // helper rather than reading it inside the helper to increase the
    // chance of making the dispatch record access monomorphic.
    jsAst.PropertyAccess record =
        new jsAst.PropertyAccess(use2, dispatchProperty);

    List<jsAst.Expression> arguments = <jsAst.Expression>[use1, record];
    FunctionElement helper = helpers.isJsIndexable;
    jsAst.Expression helperExpression = emitter.staticFunctionAccess(helper);
    return new jsAst.Call(helperExpression, arguments);
  }

  bool isTypedArray(TypeMask mask) {
    // Just checking for [:TypedData:] is not sufficient, as it is an
    // abstract class any user-defined class can implement. So we also
    // check for the interface [JavaScriptIndexingBehavior].
    return
        compiler.typedDataClass != null &&
        compiler.world.isInstantiated(compiler.typedDataClass) &&
        mask.satisfies(compiler.typedDataClass, compiler.world) &&
        mask.satisfies(helpers.jsIndexingBehaviorInterface, compiler.world);
  }

  bool couldBeTypedArray(TypeMask mask) {
    bool intersects(TypeMask type1, TypeMask type2) =>
        !type1.intersection(type2, compiler.world).isEmpty;
    // TODO(herhut): Maybe cache the TypeMask for typedDataClass and
    //               jsIndexingBehaviourInterface.
    return
        compiler.typedDataClass != null &&
        compiler.world.isInstantiated(compiler.typedDataClass) &&
        intersects(mask,
            new TypeMask.subtype(compiler.typedDataClass, compiler.world)) &&
        intersects(mask,
            new TypeMask.subtype(helpers.jsIndexingBehaviorInterface, compiler.world));
  }

  /// Returns all static fields that are referenced through [targetsUsed].
  /// If the target is a library or class all nested static fields are
  /// included too.
  Iterable<Element> _findStaticFieldTargets() {
    List staticFields = [];

    void addFieldsInContainer(ScopeContainerElement container) {
      container.forEachLocalMember((Element member) {
        if (!member.isInstanceMember && member.isField) {
          staticFields.add(member);
        } else if (member.isClass) {
          addFieldsInContainer(member);
        }
      });
    }

    for (Element target in targetsUsed) {
      if (target == null) continue;
      if (target.isField) {
        staticFields.add(target);
      } else if (target.isLibrary || target.isClass) {
        addFieldsInContainer(target);
      }
    }
    return staticFields;
  }

  /// Called when [enqueuer] is empty, but before it is closed.
  bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassElement> recentClasses) {
    // Add elements referenced only via custom elements.  Return early if any
    // elements are added to avoid counting the elements as due to mirrors.
    customElementsAnalysis.onQueueEmpty(enqueuer);
    if (!enqueuer.queueIsEmpty) return false;

    noSuchMethodRegistry.onQueueEmpty();
    if (!enabledNoSuchMethod &&
        (noSuchMethodRegistry.hasThrowingNoSuchMethod ||
         noSuchMethodRegistry.hasComplexNoSuchMethod)) {
      enableNoSuchMethod(enqueuer);
      enabledNoSuchMethod = true;
    }

    if (compiler.options.hasIncrementalSupport) {
      // Always enable tear-off closures during incremental compilation.
      Element e = helpers.closureFromTearOff;
      if (e != null && !enqueuer.isProcessed(e)) {
        registerBackendUse(e);
        enqueuer.addToWorkList(e);
      }
    }

    if (!enqueuer.isResolutionQueue && preMirrorsMethodCount == 0) {
      preMirrorsMethodCount = generatedCode.length;
    }

    if (isTreeShakingDisabled) {
      enqueuer.enqueueReflectiveElements(recentClasses);
    } else if (!targetsUsed.isEmpty && enqueuer.isResolutionQueue) {
      // Add all static elements (not classes) that have been requested for
      // reflection. If there is no mirror-usage these are probably not
      // necessary, but the backend relies on them being resolved.
      enqueuer.enqueueReflectiveStaticFields(_findStaticFieldTargets());
    }

    if (mustPreserveNames) reporter.log('Preserving names.');

    if (mustRetainMetadata) {
      reporter.log('Retaining metadata.');

      compiler.libraryLoader.libraries.forEach(retainMetadataOf);
      for (Dependency dependency in metadataConstants) {
        registerCompileTimeConstant(
            dependency.constant,
            new EagerRegistry('EagerRegistry for ${dependency}', enqueuer));
      }
      if (!enqueuer.isResolutionQueue) {
        metadataConstants.clear();
      }
    }
    return true;
  }

  void onQueueClosed() {
    lookupMapAnalysis.onQueueClosed();
    jsInteropAnalysis.onQueueClosed();
  }

  void onCodegenStart() {
    lookupMapAnalysis.onCodegenStart();
  }

  void onElementResolved(Element element, TreeElements elements) {
    if (element.isMalformed) {
      // Elements that are marker as malformed during parsing or resolution
      // might be registered here. These should just be ignored.
      return;
    }

    if ((element.isFunction || element.isConstructor) &&
        annotations.noInline(element)) {
      inlineCache.markAsNonInlinable(element);
    }

    LibraryElement library = element.library;
    if (!library.isPlatformLibrary && !canLibraryUseNative(library)) return;
    bool hasNoInline = false;
    bool hasForceInline = false;
    bool hasNoThrows = false;
    bool hasNoSideEffects = false;
    for (MetadataAnnotation metadata in element.implementation.metadata) {
      metadata.ensureResolved(resolution);
      ConstantValue constantValue =
          compiler.constants.getConstantValue(metadata.constant);
      if (!constantValue.isConstructedObject) continue;
      ObjectConstantValue value = constantValue;
      ClassElement cls = value.type.element;
      if (cls == helpers.forceInlineClass) {
        hasForceInline = true;
        if (VERBOSE_OPTIMIZER_HINTS) {
          reporter.reportHintMessage(
              element,
              MessageKind.GENERIC,
              {'text': "Must inline"});
        }
        inlineCache.markAsMustInline(element);
      } else if (cls == helpers.noInlineClass) {
        hasNoInline = true;
        if (VERBOSE_OPTIMIZER_HINTS) {
          reporter.reportHintMessage(
              element,
              MessageKind.GENERIC,
              {'text': "Cannot inline"});
        }
        inlineCache.markAsNonInlinable(element);
      } else if (cls == helpers.noThrowsClass) {
        hasNoThrows = true;
        if (!Elements.isStaticOrTopLevelFunction(element) &&
            !element.isFactoryConstructor) {
          reporter.internalError(element,
              "@NoThrows() is currently limited to top-level"
              " or static functions and factory constructors.");
        }
        if (VERBOSE_OPTIMIZER_HINTS) {
          reporter.reportHintMessage(
              element,
              MessageKind.GENERIC,
              {'text': "Cannot throw"});
        }
        compiler.world.registerCannotThrow(element);
      } else if (cls == helpers.noSideEffectsClass) {
        hasNoSideEffects = true;
        if (VERBOSE_OPTIMIZER_HINTS) {
          reporter.reportHintMessage(
              element,
              MessageKind.GENERIC,
              {'text': "Has no side effects"});
        }
        compiler.world.registerSideEffectsFree(element);
      }
    }
    if (hasForceInline && hasNoInline) {
      reporter.internalError(element,
          "@ForceInline() must not be used with @NoInline.");
    }
    if (hasNoThrows && !hasNoInline) {
      reporter.internalError(element,
          "@NoThrows() should always be combined with @NoInline.");
    }
    if (hasNoSideEffects && !hasNoInline) {
      reporter.internalError(element,
          "@NoSideEffects() should always be combined with @NoInline.");
    }
    if (element == helpers.invokeOnMethod) {
      compiler.enabledInvokeOn = true;
    }
  }
/*
  CodeBuffer codeOf(Element element) {
    return generatedCode.containsKey(element)
        ? jsAst.prettyPrint(generatedCode[element], compiler)
        : null;
  }
*/
  FunctionElement helperForBadMain() => helpers.badMain;

  FunctionElement helperForMissingMain() => helpers.missingMain;

  FunctionElement helperForMainArity() => helpers.mainHasTooManyParameters;

  void forgetElement(Element element) {
    constants.forgetElement(element);
    constantCompilerTask.dartConstantCompiler.forgetElement(element);
    aliasedSuperMembers.remove(element);
  }

  void registerMainHasArguments(Enqueuer enqueuer) {
    // If the main method takes arguments, this compilation could be the target
    // of Isolate.spawnUri. Strictly speaking, that can happen also if main
    // takes no arguments, but in this case the spawned isolate can't
    // communicate with the spawning isolate.
    enqueuer.enableIsolateSupport();
  }

  /// Returns the filename for the output-unit named [name].
  ///
  /// The filename is of the form "<main output file>_<name>.part.js".
  /// If [addExtension] is false, the ".part.js" suffix is left out.
  String deferredPartFileName(String name, {bool addExtension: true}) {
    assert(name != "");
    String outPath = compiler.options.outputUri != null
        ? compiler.options.outputUri.path
        : "out";
    String outName = outPath.substring(outPath.lastIndexOf('/') + 1);
    String extension = addExtension ? ".part.js" : "";
    return "${outName}_$name$extension";
  }

  @override
  bool enableDeferredLoadingIfSupported(Spannable node, Registry registry) {
    registerCheckDeferredIsLoaded(registry);
    return true;
  }

  @override
  bool enableCodegenWithErrorsIfSupported(Spannable node) {
    if (compiler.options.useCpsIr) {
      // TODO(25747): Support code generation with compile-time errors.
      reporter.reportHintMessage(
          node,
          MessageKind.GENERIC,
          {'text': "Generation of code with compile time errors is currently "
                   "not supported with the CPS IR."});
      return false;
    }
    return true;
  }

  jsAst.Expression rewriteAsync(FunctionElement element,
                                jsAst.Expression code) {
    AsyncRewriterBase rewriter = null;
    jsAst.Name name = namer.methodPropertyName(element);
    switch (element.asyncMarker) {
      case AsyncMarker.ASYNC:
        rewriter = new AsyncRewriter(
            reporter,
            element,
            asyncHelper:
                emitter.staticFunctionAccess(helpers.asyncHelper),
            wrapBody:
                emitter.staticFunctionAccess(helpers.wrapBody),
            newCompleter: emitter.staticFunctionAccess(
                helpers.syncCompleterConstructor),
            safeVariableName: namer.safeVariablePrefixForAsyncRewrite,
            bodyName: namer.deriveAsyncBodyName(name));
        break;
      case AsyncMarker.SYNC_STAR:
        rewriter = new SyncStarRewriter(
            reporter,
            element,
            endOfIteration: emitter.staticFunctionAccess(
                helpers.endOfIteration),
            newIterable: emitter.staticFunctionAccess(
                helpers.syncStarIterableConstructor),
            yieldStarExpression: emitter.staticFunctionAccess(
                helpers.yieldStar),
            uncaughtErrorExpression: emitter.staticFunctionAccess(
                helpers.syncStarUncaughtError),
            safeVariableName: namer.safeVariablePrefixForAsyncRewrite,
            bodyName: namer.deriveAsyncBodyName(name));
         break;
      case AsyncMarker.ASYNC_STAR:
        rewriter = new AsyncStarRewriter(
            reporter,
            element,
            asyncStarHelper: emitter.staticFunctionAccess(
                helpers.asyncStarHelper),
            streamOfController: emitter.staticFunctionAccess(
                helpers.streamOfController),
            wrapBody:
                emitter.staticFunctionAccess(helpers.wrapBody),
            newController: emitter.staticFunctionAccess(
                helpers.asyncStarControllerConstructor),
            safeVariableName: namer.safeVariablePrefixForAsyncRewrite,
            yieldExpression: emitter.staticFunctionAccess(
                helpers.yieldSingle),
            yieldStarExpression: emitter.staticFunctionAccess(
                helpers.yieldStar),
            bodyName: namer.deriveAsyncBodyName(name));
        break;
      default:
        assert(element.asyncMarker == AsyncMarker.SYNC);
        return code;
    }
    return rewriter.rewrite(code);
  }

  /// The locations of js patch-files relative to the sdk-descriptors.
  static const _patchLocations = const <String, String>{
    "async": "_internal/js_runtime/lib/async_patch.dart",
    "collection":  "_internal/js_runtime/lib/collection_patch.dart",
    "convert": "_internal/js_runtime/lib/convert_patch.dart",
    "core": "_internal/js_runtime/lib/core_patch.dart",
    "developer": "_internal/js_runtime/lib/developer_patch.dart",
    "io": "_internal/js_runtime/lib/io_patch.dart",
    "isolate": "_internal/js_runtime/lib/isolate_patch.dart",
    "math": "_internal/js_runtime/lib/math_patch.dart",
    "mirrors": "_internal/js_runtime/lib/mirrors_patch.dart",
    "typed_data": "_internal/js_runtime/lib/typed_data_patch.dart",
    "_internal": "_internal/js_runtime/lib/internal_patch.dart"
  };

  @override
  Uri resolvePatchUri(String libraryName, Uri platformConfigUri) {
    String patchLocation = _patchLocations[libraryName];
    if (patchLocation == null) return null;
    return platformConfigUri.resolve(patchLocation);
  }

  @override
  ImpactStrategy createImpactStrategy(
      {bool supportDeferredLoad: true,
       bool supportDumpInfo: true,
       bool supportSerialization: true}) {
    return new JavaScriptImpactStrategy(
        resolution,
        compiler.dumpInfoTask,
        supportDeferredLoad: supportDeferredLoad,
        supportDumpInfo: supportDumpInfo,
        supportSerialization: supportSerialization);
  }
}

/// Handling of special annotations for tests.
class Annotations {
  static final Uri PACKAGE_EXPECT =
      new Uri(scheme: 'package', path: 'expect/expect.dart');

  final Compiler compiler;

  ClassElement expectNoInlineClass;
  ClassElement expectTrustTypeAnnotationsClass;
  ClassElement expectAssumeDynamicClass;

  JavaScriptBackend get backend => compiler.backend;

  DiagnosticReporter get reporter => compiler.reporter;

  Annotations(this.compiler);

  void onLibraryScanned(LibraryElement library) {
    if (library.canonicalUri == PACKAGE_EXPECT) {
      expectNoInlineClass = library.find('NoInline');
      expectTrustTypeAnnotationsClass = library.find('TrustTypeAnnotations');
      expectAssumeDynamicClass = library.find('AssumeDynamic');
      if (expectNoInlineClass == null ||
          expectTrustTypeAnnotationsClass == null ||
          expectAssumeDynamicClass == null) {
        // This is not the package you're looking for.
        expectNoInlineClass = null;
        expectTrustTypeAnnotationsClass = null;
        expectAssumeDynamicClass = null;
      }
    }
  }

  /// Returns `true` if inlining is disabled for [element].
  bool noInline(Element element) {
    if (_hasAnnotation(element, expectNoInlineClass)) {
      // TODO(floitsch): restrict to elements from the test directory.
      return true;
    }
    return _hasAnnotation(element, backend.helpers.noInlineClass);
  }

  /// Returns `true` if parameter and returns types should be trusted for
  /// [element].
  bool trustTypeAnnotations(Element element) {
    return _hasAnnotation(element, expectTrustTypeAnnotationsClass);
  }

  /// Returns `true` if inference of parameter types is disabled for [element].
  bool assumeDynamic(Element element) {
    return _hasAnnotation(element, expectAssumeDynamicClass);
  }

  /// Returns `true` if [element] is annotated with [annotationClass].
  bool _hasAnnotation(Element element, ClassElement annotationClass) {
    if (annotationClass == null) return false;
    return reporter.withCurrentElement(element, () {
      for (MetadataAnnotation metadata in element.metadata) {
        assert(invariant(metadata, metadata.constant != null,
            message: "Unevaluated metadata constant."));
        ConstantValue value =
            compiler.constants.getConstantValue(metadata.constant);
        if (value.isConstructedObject) {
          ConstructedConstantValue constructedConstant = value;
          if (constructedConstant.type.element == annotationClass) {
            return true;
          }
        }
      }
      return false;
    });
  }
}

class JavaScriptImpactTransformer extends ImpactTransformer {
  final JavaScriptBackend backend;

  JavaScriptImpactTransformer(this.backend);

  BackendImpacts get impacts => backend.impacts;

  @override
  WorldImpact transformResolutionImpact(ResolutionImpact worldImpact) {
    TransformedWorldImpact transformed =
        new TransformedWorldImpact(worldImpact);
    for (Feature feature in worldImpact.features) {
      switch (feature) {
        case Feature.ABSTRACT_CLASS_INSTANTIATION:
          registerBackendImpact(
              transformed, impacts.abstractClassInstantiation);
          break;
        case Feature.ASSERT:
          registerBackendImpact(transformed, impacts.assertWithoutMessage);
          break;
        case Feature.ASSERT_WITH_MESSAGE:
          registerBackendImpact(transformed, impacts.assertWithMessage);
          break;
        case Feature.ASYNC:
          registerBackendImpact(transformed, impacts.asyncBody);
          break;
        case Feature.ASYNC_FOR_IN:
          registerBackendImpact(transformed, impacts.asyncForIn);
          break;
        case Feature.ASYNC_STAR:
          registerBackendImpact(transformed, impacts.asyncStarBody);
          break;
        case Feature.CATCH_STATEMENT:
          registerBackendImpact(transformed, impacts.catchStatement);
          break;
        case Feature.COMPILE_TIME_ERROR:
          if (backend.compiler.options.generateCodeWithCompileTimeErrors) {
            // TODO(johnniwinther): This should have its own uncatchable error.
            registerBackendImpact(transformed, impacts.throwRuntimeError);
          }
          break;
        case Feature.FALL_THROUGH_ERROR:
          registerBackendImpact(transformed, impacts.fallThroughError);
          break;
        case Feature.INC_DEC_OPERATION:
          registerBackendImpact(transformed, impacts.incDecOperation);
          break;
        case Feature.LAZY_FIELD:
          registerBackendImpact(transformed, impacts.lazyField);
          break;
        case Feature.STACK_TRACE_IN_CATCH:
          registerBackendImpact(transformed, impacts.stackTraceInCatch);
          break;
        case Feature.STRING_INTERPOLATION:
          registerBackendImpact(transformed, impacts.stringInterpolation);
          break;
        case Feature.STRING_JUXTAPOSITION:
          registerBackendImpact(transformed, impacts.stringJuxtaposition);
          break;
        case Feature.SUPER_NO_SUCH_METHOD:
          registerBackendImpact(transformed, impacts.superNoSuchMethod);
          break;
        case Feature.SYMBOL_CONSTRUCTOR:
          registerBackendImpact(transformed, impacts.symbolConstructor);
          break;
        case Feature.SYNC_FOR_IN:
          registerBackendImpact(transformed, impacts.syncForIn);
          break;
        case Feature.SYNC_STAR:
          registerBackendImpact(transformed, impacts.syncStarBody);
          break;
        case Feature.THROW_EXPRESSION:
          registerBackendImpact(transformed, impacts.throwExpression);
          break;
        case Feature.THROW_NO_SUCH_METHOD:
          registerBackendImpact(transformed, impacts.throwNoSuchMethod);
          break;
        case Feature.THROW_RUNTIME_ERROR:
          registerBackendImpact(transformed, impacts.throwRuntimeError);
          break;
        case Feature.TYPE_VARIABLE_BOUNDS_CHECK:
          registerBackendImpact(transformed, impacts.typeVariableBoundCheck);
          break;
      }
    }

    bool hasAsCast = false;
    bool hasTypeLiteral = false;
    for (TypeUse typeUse in worldImpact.typeUses) {
      DartType type = typeUse.type;
      switch (typeUse.kind) {
        case TypeUseKind.INSTANTIATION:
          registerRequiredType(type);
          break;
        case TypeUseKind.IS_CHECK:
          onIsCheck(type, transformed);
          break;
        case TypeUseKind.AS_CAST:
          onIsCheck(type, transformed);
          hasAsCast = true;
          break;
        case TypeUseKind.CHECKED_MODE_CHECK:
          if (backend.compiler.options.enableTypeAssertions) {
            onIsCheck(type, transformed);
          }
          break;
        case TypeUseKind.CATCH_TYPE:
          onIsCheck(type, transformed);
          break;
        case TypeUseKind.TYPE_LITERAL:
          backend.customElementsAnalysis.registerTypeLiteral(type);
          if (type.isTypedef) {
            backend.compiler.world.allTypedefs.add(type.element);
          }
          if (type.isTypeVariable) {
            ClassElement cls = type.element.enclosingClass;
            backend.rti.registerClassUsingTypeVariableExpression(cls);
            registerBackendImpact(transformed, impacts.typeVariableExpression);
          }
          hasTypeLiteral = true;
          break;
      }
    }

    if (hasAsCast) {
      registerBackendImpact(transformed, impacts.asCheck);
    }

    if (hasTypeLiteral) {
      transformed.registerTypeUse(new TypeUse.instantiation(
          backend.compiler.coreTypes.typeType));
      registerBackendImpact(transformed, impacts.typeLiteral);
    }

    for (MapLiteralUse mapLiteralUse in worldImpact.mapLiterals) {
      // TODO(johnniwinther): Use the [isEmpty] property when factory
      // constructors are registered directly.
      if (mapLiteralUse.isConstant) {
        registerBackendImpact(transformed, impacts.constantMapLiteral);
      } else {
        transformed.registerTypeUse(
            new TypeUse.instantiation(mapLiteralUse.type));
      }
      registerRequiredType(mapLiteralUse.type);
    }

    for (ListLiteralUse listLiteralUse in worldImpact.listLiterals) {
      // TODO(johnniwinther): Use the [isConstant] and [isEmpty] property when
      // factory constructors are registered directly.
      transformed.registerTypeUse(
          new TypeUse.instantiation(listLiteralUse.type));
      registerRequiredType(listLiteralUse.type);
    }

    if (worldImpact.constSymbolNames.isNotEmpty) {
      registerBackendImpact(transformed, impacts.constSymbol);
      for (String constSymbolName in worldImpact.constSymbolNames) {
        backend.registerConstSymbol(constSymbolName);
      }
    }

    for (StaticUse staticUse in worldImpact.staticUses) {
      if (staticUse.kind == StaticUseKind.CLOSURE) {
        registerBackendImpact(transformed, impacts.closure);
        LocalFunctionElement closure = staticUse.element;
        if (closure.type.containsTypeVariables) {
          backend.compiler.enqueuer.resolution.universe
              .closuresWithFreeTypeVariables.add(closure);
          registerBackendImpact(transformed, impacts.computeSignature);
        }
      }
    }

    for (ConstantExpression constant in worldImpact.constantLiterals) {
      switch (constant.kind) {
        case ConstantExpressionKind.NULL:
          registerBackendImpact(transformed, impacts.nullLiteral);
          break;
        case ConstantExpressionKind.BOOL:
          registerBackendImpact(transformed, impacts.boolLiteral);
          break;
        case ConstantExpressionKind.INT:
          registerBackendImpact(transformed, impacts.intLiteral);
          break;
        case ConstantExpressionKind.DOUBLE:
          registerBackendImpact(transformed, impacts.doubleLiteral);
          break;
        case ConstantExpressionKind.STRING:
          registerBackendImpact(transformed, impacts.stringLiteral);
          break;
        default:
          assert(invariant(NO_LOCATION_SPANNABLE, false,
              message: "Unexpected constant literal: ${constant.kind}."));
      }
    }

    return transformed;
  }

  void registerBackendImpact(TransformedWorldImpact worldImpact,
                             BackendImpact backendImpact) {
    for (Element staticUse in backendImpact.staticUses) {
      assert(staticUse != null);
      backend.registerBackendUse(staticUse);
      worldImpact.registerStaticUse(
          // TODO(johnniwinther): Store the correct use in impacts.
          new StaticUse.foreignUse(staticUse));
    }
    for (InterfaceType instantiatedType in backendImpact.instantiatedTypes) {
      backend.registerBackendUse(instantiatedType.element);
      worldImpact.registerTypeUse(
          new TypeUse.instantiation(instantiatedType));
    }
    for (ClassElement cls in backendImpact.instantiatedClasses) {
      cls.ensureResolved(backend.resolution);
      backend.registerBackendUse(cls);
      worldImpact.registerTypeUse(
          new TypeUse.instantiation(cls.rawType));
    }
    for (BackendImpact otherImpact in backendImpact.otherImpacts) {
      registerBackendImpact(worldImpact, otherImpact);
    }
  }

  /// Register [type] as required for the runtime type information system.
  void registerRequiredType(DartType type) {
    // If [argument] has type variables or is a type variable, this method
    // registers a RTI dependency between the class where the type variable is
    // defined (that is the enclosing class of the current element being
    // resolved) and the class of [type]. If the class of [type] requires RTI,
    // then the class of the type variable does too.
    ClassElement contextClass = Types.getClassContext(type);
    if (contextClass != null) {
      backend.rti.registerRtiDependency(type.element, contextClass);
    }
  }

  // TODO(johnniwinther): Maybe split this into [onAssertType] and [onTestType].
  void onIsCheck(DartType type, TransformedWorldImpact transformed) {
    registerRequiredType(type);
    type.computeUnaliased(backend.resolution);
    type = type.unaliased;
    registerBackendImpact(transformed, impacts.typeCheck);

    bool inCheckedMode = backend.compiler.options.enableTypeAssertions;
    if (inCheckedMode) {
      registerBackendImpact(transformed, impacts.checkedModeTypeCheck);
    }
    if (type.isMalformed) {
      registerBackendImpact(transformed, impacts.malformedTypeCheck);
    }
    if (!type.treatAsRaw || type.containsTypeVariables || type.isFunctionType) {
      registerBackendImpact(transformed, impacts.genericTypeCheck);
      if (inCheckedMode) {
        registerBackendImpact(transformed, impacts.genericCheckedModeTypeCheck);
      }
      if (type.isTypeVariable) {
        registerBackendImpact(transformed, impacts.typeVariableTypeCheck);
        if (inCheckedMode) {
          registerBackendImpact(transformed,
              impacts.typeVariableCheckedModeTypeCheck);
        }
      }
    }
    if (type is FunctionType) {
      registerBackendImpact(transformed, impacts.functionTypeCheck);
    }
    if (type.element != null && backend.isNative(type.element)) {
      registerBackendImpact(transformed, impacts.nativeTypeCheck);
    }
  }

  void onIsCheckForCodegen(DartType type, TransformedWorldImpact transformed) {
    type = type.unaliased;
    registerBackendImpact(transformed, impacts.typeCheck);

    bool inCheckedMode = backend.compiler.options.enableTypeAssertions;
    // [registerIsCheck] is also called for checked mode checks, so we
    // need to register checked mode helpers.
    if (inCheckedMode) {
      // All helpers are added to resolution queue in enqueueHelpers. These
      // calls to enqueueInResolution serve as assertions that the helper was
      // in fact added.
      // TODO(13155): Find a way to enqueue helpers lazily.
      CheckedModeHelper helper =
          backend.getCheckedModeHelper(type, typeCast: false);
      if (helper != null) {
        StaticUse staticUse = helper.getStaticUse(backend.compiler);
        transformed.registerStaticUse(staticUse);
        backend.registerBackendUse(staticUse.element);
      }
      // We also need the native variant of the check (for DOM types).
      helper = backend.getNativeCheckedModeHelper(type, typeCast: false);
      if (helper != null) {
        StaticUse staticUse = helper.getStaticUse(backend.compiler);
        transformed.registerStaticUse(staticUse);
        backend.registerBackendUse(staticUse.element);
      }
    }
    if (!type.treatAsRaw || type.containsTypeVariables) {
      registerBackendImpact(transformed, impacts.genericIsCheck);
    }
    if (type.element != null && backend.isNative(type.element)) {
      // We will neeed to add the "$is" and "$as" properties on the
      // JavaScript object prototype, so we make sure
      // [:defineProperty:] is compiled.
      registerBackendImpact(transformed, impacts.nativeTypeCheck);
    }
  }

  @override
  WorldImpact transformCodegenImpact(CodegenImpact impact) {
    TransformedWorldImpact transformed = new TransformedWorldImpact(impact);
    EagerRegistry registry = impact.registry;
    Enqueuer world = registry.world;

    for (TypeUse typeUse in impact.typeUses) {
      DartType type = typeUse.type;
      switch (typeUse.kind) {
        case TypeUseKind.INSTANTIATION:
          backend.lookupMapAnalysis.registerInstantiatedType(type, registry);
          break;
        case TypeUseKind.IS_CHECK:
          onIsCheckForCodegen(type, transformed);
          break;
        default:
      }
    }

    for (ConstantValue constant in impact.compileTimeConstants) {
      backend.registerCompileTimeConstant(constant, registry);
      backend.addCompileTimeConstantForEmission(constant);
    }

    for (Pair<DartType, DartType> check in
            impact.typeVariableBoundsSubtypeChecks) {
      backend.registerTypeVariableBoundsSubtypeCheck(check.a, check.b);
    }


    for (StaticUse staticUse in impact.staticUses) {
      if (staticUse.kind == StaticUseKind.CLOSURE) {
        LocalFunctionElement closure = staticUse.element;
        if (backend.methodNeedsRti(closure)) {
           registerBackendImpact(transformed, impacts.computeSignature);
         }
      }
    }

    for (String name in impact.constSymbols) {
      backend.registerConstSymbol(name);
    }

    for (Set<ClassElement> classes in impact.specializedGetInterceptors) {
      backend.registerSpecializedGetInterceptor(classes);
    }

    if (impact.usesInterceptor) {
      backend.registerUseInterceptor(world);
    }

    for (ClassElement element in impact.typeConstants) {
      backend.customElementsAnalysis.registerTypeConstant(element);
      backend.lookupMapAnalysis.registerTypeConstant(element);
    }

    for (FunctionElement element in impact.asyncMarkers) {
      switch (element.asyncMarker) {
        case AsyncMarker.ASYNC:
          registerBackendImpact(transformed, impacts.asyncBody);
          break;
        case AsyncMarker.SYNC_STAR:
          registerBackendImpact(transformed, impacts.syncStarBody);
          break;
        case AsyncMarker.ASYNC_STAR:
          registerBackendImpact(transformed, impacts.asyncStarBody);
          break;
      }
    }

    // TODO(johnniwinther): Remove eager registration.
    return transformed;
  }
}

/// Records that [constant] is used by the element behind [registry].
class Dependency {
  final ConstantValue constant;
  final Element annotatedElement;

  const Dependency(this.constant, this.annotatedElement);
}

class JavaScriptImpactStrategy extends ImpactStrategy {
  final Resolution resolution;
  final DumpInfoTask dumpInfoTask;
  final bool supportDeferredLoad;
  final bool supportDumpInfo;
  final bool supportSerialization;

  JavaScriptImpactStrategy(this.resolution,
                           this.dumpInfoTask,
                           {this.supportDeferredLoad,
                            this.supportDumpInfo,
                            this.supportSerialization});

  @override
  void visitImpact(Element element,
                   WorldImpact impact,
                   WorldImpactVisitor visitor,
                   ImpactUseCase impactUse) {
    // TODO(johnniwinther): Compute the application strategy once for each use.
    if (impactUse == ResolutionEnqueuer.IMPACT_USE) {
      if (supportDeferredLoad || supportSerialization) {
        impact.apply(visitor);
      } else {
        impact.apply(visitor);
        resolution.uncacheWorldImpact(element);
      }
    } else if (impactUse == DeferredLoadTask.IMPACT_USE) {
      impact.apply(visitor);
      // Impacts are uncached globally in [onImpactUsed].
    } else if (impactUse == DumpInfoTask.IMPACT_USE) {
      impact.apply(visitor);
      dumpInfoTask.unregisterImpact(element);
    } else {
      impact.apply(visitor);
    }
  }

  @override
  void onImpactUsed(ImpactUseCase impactUse) {
    if (impactUse == DeferredLoadTask.IMPACT_USE &&
        !supportSerialization) {
      // TODO(johnniwinther): Allow emptying when serialization has been
      // performed.
      resolution.emptyCache();
    }
  }
}
