// 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.

library js_backend.backend;

import '../common.dart';
import '../common/backend_api.dart' show ImpactTransformer;
import '../common/codegen.dart';
import '../common/names.dart' show Uris;
import '../common/tasks.dart' show CompilerTask;
import '../common/work.dart';
import '../common_elements.dart' show CommonElements, ElementEnvironment;
import '../compiler.dart' show Compiler;
import '../deferred_load.dart' show DeferredLoadTask;
import '../dump_info.dart' show DumpInfoTask;
import '../elements/entities.dart';
import '../enqueue.dart' show Enqueuer, EnqueueTask, ResolutionEnqueuer;
import '../frontend_strategy.dart';
import '../inferrer/types.dart';
import '../io/source_information.dart' show SourceInformationStrategy;
import '../js/js.dart' as jsAst;
import '../js_model/elements.dart';
import '../js_emitter/js_emitter.dart' show CodeEmitterTask;
import '../kernel/dart2js_target.dart';
import '../native/enqueue.dart';
import '../serialization/serialization.dart';
import '../ssa/ssa.dart' show SsaFunctionCompiler;
import '../tracer.dart';
import '../universe/class_hierarchy.dart'
    show ClassHierarchyBuilder, ClassQueries;
import '../universe/codegen_world_builder.dart';
import '../universe/world_builder.dart';
import '../universe/world_impact.dart'
    show ImpactStrategy, ImpactUseCase, WorldImpact, WorldImpactVisitor;
import '../world.dart' show JClosedWorld;
import 'field_analysis.dart';
import 'annotations.dart';
import 'backend_impact.dart';
import 'backend_usage.dart';
import 'checked_mode_helpers.dart';
import 'codegen_listener.dart';
import 'custom_elements_analysis.dart';
import 'enqueuer.dart';
import 'impact_transformer.dart';
import 'inferred_data.dart';
import 'interceptor_data.dart';
import 'namer.dart';
import 'native_data.dart';
import 'no_such_method_registry.dart';
import 'resolution_listener.dart';
import 'runtime_types.dart';

abstract class FunctionCompiler {
  void initialize(
      GlobalTypeInferenceResults globalInferenceResults, CodegenInputs codegen);

  /// Generates JavaScript code for [member].
  CodegenResult compile(MemberEntity member);

  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;

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

  final Set<FunctionEntity> _tryInlineFunctions = new Set<FunctionEntity>();

  FunctionInlineCache(AnnotationsData annotationsData) {
    annotationsData.forEachNoInline((FunctionEntity function) {
      markAsNonInlinable(function);
    });
    annotationsData.forEachTryInline((FunctionEntity function) {
      markAsTryInline(function);
    });
  }

  /// Checks that [method] is the canonical representative for this method.
  ///
  /// For a [MethodElement] this means it must be the declaration element.
  bool checkFunction(FunctionEntity method) {
    return '$method'.startsWith(jsElementPrefix);
  }

  /// Returns the current cache decision. This should only be used for testing.
  int getCurrentCacheDecisionForTesting(FunctionEntity element) {
    assert(checkFunction(element), failedAt(element));
    return _cachedDecisions[element];
  }

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

    if (decision == null) {
      // TODO(sra): Have annotations for mustInline / noInline for constructor
      // bodies. (There used to be some logic here to have constructor bodies,
      // inherit the settings from annotations on the generative
      // constructor. This was conflated with the heuristic decisions, leading
      // to lack of inlining where it was beneficial.)
      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:
          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:
          return true;
      }
    }

    // Quiet static checker.
    return null;
  }

  void markAsInlinable(FunctionEntity element, {bool insideLoop}) {
    assert(checkFunction(element), failedAt(element));
    int oldDecision = _cachedDecisions[element];

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

    if (insideLoop) {
      switch (oldDecision) {
        case _mustNotInline:
          throw failedAt(
              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:
          // Do nothing.
          break;
      }
    } else {
      switch (oldDecision) {
        case _mustNotInline:
        case _mayInlineInLoopMustNotOutside:
        case _canInlineInLoopMustNotOutside:
          throw failedAt(
              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:
          // Do nothing.
          break;
      }
    }
  }

  void markAsNonInlinable(FunctionEntity element, {bool insideLoop: true}) {
    assert(checkFunction(element), failedAt(element));
    int oldDecision = _cachedDecisions[element];

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

    if (insideLoop) {
      switch (oldDecision) {
        case _canInlineInLoopMustNotOutside:
        case _canInlineInLoopMayInlineOutside:
        case _canInline:
          throw failedAt(
              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:
          throw failedAt(
              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 markAsTryInline(FunctionEntity element) {
    assert(checkFunction(element), failedAt(element));
    _tryInlineFunctions.add(element);
  }

  bool markedAsTryInline(FunctionEntity element) {
    assert(checkFunction(element), failedAt(element));
    return _tryInlineFunctions.contains(element);
  }
}

class JavaScriptBackend {
  static const String JS = 'JS';
  static const String JS_BUILTIN = 'JS_BUILTIN';
  static const String JS_EMBEDDED_GLOBAL = 'JS_EMBEDDED_GLOBAL';
  static const String JS_INTERCEPTOR_CONSTANT = 'JS_INTERCEPTOR_CONSTANT';
  static const String JS_STRING_CONCAT = 'JS_STRING_CONCAT';

  final Compiler compiler;

  FrontendStrategy get frontendStrategy => compiler.frontendStrategy;

  FunctionCompiler functionCompiler;

  CodeEmitterTask emitterTask;

  /// The generated code as a js AST for compiled methods.
  final Map<MemberEntity, jsAst.Expression> generatedCode =
      <MemberEntity, jsAst.Expression>{};

  Namer _namer;

  Namer get namerForTesting => _namer;

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

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

  RuntimeTypesChecksBuilder _rtiChecksBuilder;

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

  /// Resolution support for generating table of interceptors and
  /// constructors for custom elements.
  CustomElementsResolutionAnalysis _customElementsResolutionAnalysis;

  /// Codegen support for generating table of interceptors and
  /// constructors for custom elements.
  CustomElementsCodegenAnalysis _customElementsCodegenAnalysis;

  KFieldAnalysis _fieldAnalysis;

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

  /// Backend transformation methods for the world impacts.
  ImpactTransformer impactTransformer;

  CodegenImpactTransformer _codegenImpactTransformer;

  /// The strategy used for collecting and emitting source information.
  SourceInformationStrategy sourceInformationStrategy;

  NativeDataBuilderImpl _nativeDataBuilder;
  NativeDataBuilder get nativeDataBuilder => _nativeDataBuilder;
  BackendUsageBuilder _backendUsageBuilder;

  NativeResolutionEnqueuer _nativeResolutionEnqueuer;
  NativeCodegenEnqueuer _nativeCodegenEnqueuer;

  JavaScriptBackend(this.compiler,
      {bool generateSourceMap: true,
      bool useMultiSourceInfo: false,
      bool useNewSourceInfo: false})
      : this.sourceInformationStrategy =
            compiler.backendStrategy.sourceInformationStrategy {
    CommonElements commonElements = compiler.frontendStrategy.commonElements;
    _backendUsageBuilder =
        new BackendUsageBuilderImpl(compiler.frontendStrategy);
    emitterTask = new CodeEmitterTask(compiler, generateSourceMap);
    noSuchMethodRegistry = new NoSuchMethodRegistryImpl(
        commonElements, compiler.frontendStrategy.createNoSuchMethodResolver());
    functionCompiler = new SsaFunctionCompiler(
        compiler.options,
        compiler.reporter,
        compiler.backendStrategy,
        compiler.measurer,
        sourceInformationStrategy);
  }

  DiagnosticReporter get reporter => compiler.reporter;

  ImpactCacheDeleter get impactCacheDeleter => compiler.impactCacheDeleter;

  KFieldAnalysis get fieldAnalysisForTesting => _fieldAnalysis;

  /// Resolution support for generating table of interceptors and
  /// constructors for custom elements.
  CustomElementsResolutionAnalysis get customElementsResolutionAnalysis {
    assert(
        _customElementsResolutionAnalysis != null,
        failedAt(NO_LOCATION_SPANNABLE,
            "CustomElementsResolutionAnalysis has not been created yet."));
    return _customElementsResolutionAnalysis;
  }

  /// Codegen support for generating table of interceptors and
  /// constructors for custom elements.
  CustomElementsCodegenAnalysis get customElementsCodegenAnalysis {
    assert(
        _customElementsCodegenAnalysis != null,
        failedAt(NO_LOCATION_SPANNABLE,
            "CustomElementsCodegenAnalysis has not been created yet."));
    return _customElementsCodegenAnalysis;
  }

  RuntimeTypesChecksBuilder get rtiChecksBuilder {
    assert(
        _rtiChecksBuilder != null,
        failedAt(NO_LOCATION_SPANNABLE,
            "RuntimeTypesChecksBuilder has not been created yet."));
    assert(
        !_rtiChecksBuilder.rtiChecksBuilderClosed,
        failedAt(NO_LOCATION_SPANNABLE,
            "RuntimeTypesChecks has already been computed."));
    return _rtiChecksBuilder;
  }

  RuntimeTypesChecksBuilder get rtiChecksBuilderForTesting => _rtiChecksBuilder;

  void validateInterceptorImplementsAllObjectMethods(
      ClassEntity interceptorClass) {
    if (interceptorClass == null) return;
    ClassEntity objectClass = frontendStrategy.commonElements.objectClass;
    frontendStrategy.elementEnvironment.forEachClassMember(objectClass,
        (_, MemberEntity member) {
      MemberEntity interceptorMember = frontendStrategy.elementEnvironment
          .lookupLocalClassMember(interceptorClass, member.name);
      // Interceptors must override all Object methods due to calling convention
      // differences.
      assert(
          interceptorMember.enclosingClass == interceptorClass,
          failedAt(
              interceptorMember,
              "Member ${member.name} not overridden in ${interceptorClass}. "
              "Found $interceptorMember from "
              "${interceptorMember.enclosingClass}."));
    });
  }

  /// Called before processing of the resolution queue is started.
  void onResolutionStart() {
    // TODO(johnniwinther): Avoid the compiler.elementEnvironment.getThisType
    // calls. Currently needed to ensure resolution of the classes for various
    // queries in native behavior computation, inference and codegen.
    frontendStrategy.elementEnvironment
        .getThisType(frontendStrategy.commonElements.jsArrayClass);
    frontendStrategy.elementEnvironment
        .getThisType(frontendStrategy.commonElements.jsExtendableArrayClass);

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

  /// Called when the resolution queue has been closed.
  void onResolutionEnd() {
    frontendStrategy.annotationProcessor.processJsInteropAnnotations(
        frontendStrategy.nativeBasicData, nativeDataBuilder);
  }

  ResolutionEnqueuer createResolutionEnqueuer(
      CompilerTask task, Compiler compiler) {
    ElementEnvironment elementEnvironment =
        compiler.frontendStrategy.elementEnvironment;
    CommonElements commonElements = compiler.frontendStrategy.commonElements;
    NativeBasicData nativeBasicData = compiler.frontendStrategy.nativeBasicData;
    RuntimeTypesNeedBuilder rtiNeedBuilder =
        compiler.frontendStrategy.createRuntimeTypesNeedBuilder();
    BackendImpacts impacts = new BackendImpacts(commonElements);
    _nativeResolutionEnqueuer = new NativeResolutionEnqueuer(
        compiler.options,
        elementEnvironment,
        commonElements,
        compiler.frontendStrategy.dartTypes,
        compiler.frontendStrategy.createNativeClassFinder(nativeBasicData));
    _nativeDataBuilder = new NativeDataBuilderImpl(nativeBasicData);
    _customElementsResolutionAnalysis = new CustomElementsResolutionAnalysis(
        elementEnvironment,
        commonElements,
        nativeBasicData,
        _backendUsageBuilder);
    _fieldAnalysis = new KFieldAnalysis(compiler.frontendStrategy);
    ClassQueries classQueries = compiler.frontendStrategy.createClassQueries();
    ClassHierarchyBuilder classHierarchyBuilder =
        new ClassHierarchyBuilder(commonElements, classQueries);
    impactTransformer = new JavaScriptImpactTransformer(
        compiler.options,
        elementEnvironment,
        commonElements,
        impacts,
        nativeBasicData,
        _nativeResolutionEnqueuer,
        _backendUsageBuilder,
        customElementsResolutionAnalysis,
        rtiNeedBuilder,
        classHierarchyBuilder);
    InterceptorDataBuilder interceptorDataBuilder =
        new InterceptorDataBuilderImpl(
            nativeBasicData, elementEnvironment, commonElements);
    AnnotationsDataBuilder annotationsDataBuilder =
        new AnnotationsDataBuilder();
    return new ResolutionEnqueuer(
        task,
        compiler.options,
        compiler.reporter,
        new ResolutionEnqueuerListener(
            compiler.options,
            elementEnvironment,
            commonElements,
            impacts,
            nativeBasicData,
            interceptorDataBuilder,
            _backendUsageBuilder,
            noSuchMethodRegistry,
            customElementsResolutionAnalysis,
            _nativeResolutionEnqueuer,
            _fieldAnalysis,
            compiler.deferredLoadTask),
        compiler.frontendStrategy.createResolutionWorldBuilder(
            nativeBasicData,
            _nativeDataBuilder,
            interceptorDataBuilder,
            _backendUsageBuilder,
            rtiNeedBuilder,
            _fieldAnalysis,
            _nativeResolutionEnqueuer,
            noSuchMethodRegistry,
            annotationsDataBuilder,
            const StrongModeWorldStrategy(),
            classHierarchyBuilder,
            classQueries),
        compiler.frontendStrategy.createResolutionWorkItemBuilder(
            nativeBasicData,
            _nativeDataBuilder,
            annotationsDataBuilder,
            impactTransformer,
            compiler.impactCache,
            _fieldAnalysis));
  }

  /// Creates an [Enqueuer] for code generation specific to this backend.
  CodegenEnqueuer createCodegenEnqueuer(
      CompilerTask task,
      Compiler compiler,
      JClosedWorld closedWorld,
      GlobalTypeInferenceResults globalInferenceResults,
      CodegenInputs codegen) {
    OneShotInterceptorData oneShotInterceptorData = new OneShotInterceptorData(
        closedWorld.interceptorData,
        closedWorld.commonElements,
        closedWorld.nativeData);
    _onCodegenEnqueuerStart(
        globalInferenceResults, codegen, oneShotInterceptorData);
    ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
    CommonElements commonElements = closedWorld.commonElements;
    BackendImpacts impacts = new BackendImpacts(commonElements);
    _customElementsCodegenAnalysis = new CustomElementsCodegenAnalysis(
        commonElements, elementEnvironment, closedWorld.nativeData);
    return new CodegenEnqueuer(
        task,
        compiler.options,
        compiler.backendStrategy.createCodegenWorldBuilder(
            closedWorld.nativeData,
            closedWorld,
            compiler.abstractValueStrategy.createSelectorStrategy(),
            oneShotInterceptorData),
        compiler.backendStrategy.createCodegenWorkItemBuilder(closedWorld),
        new CodegenEnqueuerListener(
            elementEnvironment,
            commonElements,
            impacts,
            closedWorld.backendUsage,
            closedWorld.rtiNeed,
            customElementsCodegenAnalysis,
            nativeCodegenEnqueuer));
  }

  Map<MemberEntity, WorldImpact> codegenImpactsForTesting;

  WorldImpact generateCode(WorkItem work, JClosedWorld closedWorld,
      EntityLookup entityLookup, ComponentLookup componentLookup) {
    MemberEntity member = work.element;
    CodegenResult result = functionCompiler.compile(member);
    if (compiler.options.testMode) {
      bool useDataKinds = true;
      List<Object> data = [];
      DataSink sink = new ObjectSink(data, useDataKinds: useDataKinds);
      sink.registerCodegenWriter(new CodegenWriterImpl(closedWorld));
      result.writeToDataSink(sink);
      DataSource source = new ObjectSource(data, useDataKinds: useDataKinds);
      List<ModularName> modularNames = [];
      List<ModularExpression> modularExpression = [];
      source.registerCodegenReader(
          new CodegenReaderImpl(closedWorld, modularNames, modularExpression));
      source.registerEntityLookup(entityLookup);
      source.registerComponentLookup(componentLookup);
      result = CodegenResult.readFromDataSource(
          source, modularNames, modularExpression);
    }
    if (result.code != null) {
      generatedCode[member] = result.code;
    }
    if (retainDataForTesting) {
      codegenImpactsForTesting ??= <MemberEntity, WorldImpact>{};
      codegenImpactsForTesting[member] = result.impact;
    }
    WorldImpact worldImpact =
        _codegenImpactTransformer.transformCodegenImpact(result.impact);
    compiler.dumpInfoTask.registerImpact(member, worldImpact);
    result.applyModularState(_namer, emitterTask.emitter);
    return worldImpact;
  }

  NativeResolutionEnqueuer get nativeResolutionEnqueuerForTesting =>
      _nativeResolutionEnqueuer;

  NativeEnqueuer get nativeCodegenEnqueuer => _nativeCodegenEnqueuer;

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

  /// Generates the output and returns the total size of the generated code.
  int assembleProgram(JClosedWorld closedWorld, InferredData inferredData,
      CodegenInputs codegen, CodegenWorld codegenWorld) {
    int programSize = emitterTask.assembleProgram(
        _namer, closedWorld, inferredData, codegen, codegenWorld);
    closedWorld.noSuchMethodData.emitDiagnostic(reporter);
    return programSize;
  }

  /// This method is called immediately after the [library] and its parts have
  /// been loaded.
  void setAnnotations(LibraryEntity library) {
    AnnotationProcessor processor =
        compiler.frontendStrategy.annotationProcessor;
    if (maybeEnableNative(library.canonicalUri)) {
      processor.extractNativeAnnotations(library);
    }
    processor.extractJsInteropAnnotations(library);
    Uri uri = library.canonicalUri;
    if (uri == Uris.dart_html) {
      _backendUsageBuilder.registerHtmlIsLoaded();
    }
  }

  /// Called when the compiler starts running the codegen.
  ///
  /// Returns the [CodegenInputs] objects with the needed data.
  CodegenInputs onCodegenStart(
      GlobalTypeInferenceResults globalTypeInferenceResults) {
    JClosedWorld closedWorld = globalTypeInferenceResults.closedWorld;
    RuntimeTypeTags rtiTags = const RuntimeTypeTags();
    FixedNames fixedNames = compiler.options.enableMinification
        ? const MinifiedFixedNames()
        : const FixedNames();

    Tracer tracer = new Tracer(closedWorld, compiler.outputProvider);
    RuntimeTypesEncoder rtiEncoder = new RuntimeTypesEncoderImpl(
        rtiTags,
        closedWorld.nativeData,
        closedWorld.elementEnvironment,
        closedWorld.commonElements,
        closedWorld.rtiNeed);
    RuntimeTypesSubstitutions rtiSubstitutions;
    if (compiler.options.disableRtiOptimization) {
      rtiSubstitutions = new TrivialRuntimeTypesSubstitutions(closedWorld);
      _rtiChecksBuilder =
          new TrivialRuntimeTypesChecksBuilder(closedWorld, rtiSubstitutions);
    } else {
      RuntimeTypesImpl runtimeTypesImpl = new RuntimeTypesImpl(closedWorld);
      _rtiChecksBuilder = runtimeTypesImpl;
      rtiSubstitutions = runtimeTypesImpl;
    }

    CodegenInputs codegen = new CodegenInputsImpl(
        rtiSubstitutions, rtiEncoder, tracer, rtiTags, fixedNames);

    functionCompiler.initialize(globalTypeInferenceResults, codegen);
    return codegen;
  }

  /// Called before the compiler starts running the codegen enqueuer.
  void _onCodegenEnqueuerStart(
      GlobalTypeInferenceResults globalTypeInferenceResults,
      CodegenInputs codegen,
      OneShotInterceptorData oneShotInterceptorData) {
    JClosedWorld closedWorld = globalTypeInferenceResults.closedWorld;
    RuntimeTypeTags rtiTags = codegen.rtiTags;
    FixedNames fixedNames = codegen.fixedNames;
    _namer = compiler.options.enableMinification
        ? compiler.options.useFrequencyNamer
            ? new FrequencyBasedNamer(closedWorld, rtiTags, fixedNames)
            : new MinifyNamer(closedWorld, rtiTags, fixedNames)
        : new Namer(closedWorld, rtiTags, fixedNames);
    _nativeCodegenEnqueuer = new NativeCodegenEnqueuer(
        compiler.options,
        closedWorld.elementEnvironment,
        closedWorld.commonElements,
        closedWorld.dartTypes,
        emitterTask,
        closedWorld.liveNativeClasses,
        closedWorld.nativeData);
    emitterTask.createEmitter(_namer, codegen, closedWorld);
    // TODO(johnniwinther): Share the impact object created in
    // createCodegenEnqueuer.
    BackendImpacts impacts = new BackendImpacts(closedWorld.commonElements);

    _codegenImpactTransformer = new CodegenImpactTransformer(
        compiler.options,
        closedWorld,
        closedWorld.elementEnvironment,
        closedWorld.commonElements,
        impacts,
        closedWorld.nativeData,
        closedWorld.backendUsage,
        closedWorld.rtiNeed,
        nativeCodegenEnqueuer,
        _namer,
        oneShotInterceptorData,
        rtiChecksBuilder,
        emitterTask.nativeEmitter);
  }

  /// Called when code generation has been completed.
  void onCodegenEnd(CodegenInputs codegen) {
    sourceInformationStrategy.onComplete();
    codegen.tracer.close();
  }

  /// Creates an impact strategy to use for compilation.
  ImpactStrategy createImpactStrategy(
      {bool supportDeferredLoad: true, bool supportDumpInfo: true}) {
    return new JavaScriptImpactStrategy(
        impactCacheDeleter, compiler.dumpInfoTask,
        supportDeferredLoad: supportDeferredLoad,
        supportDumpInfo: supportDumpInfo);
  }

  EnqueueTask makeEnqueuer() => new EnqueueTask(compiler);
}

class JavaScriptImpactStrategy extends ImpactStrategy {
  final ImpactCacheDeleter impactCacheDeleter;
  final DumpInfoTask dumpInfoTask;
  final bool supportDeferredLoad;
  final bool supportDumpInfo;

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

  @override
  void visitImpact(var impactSource, WorldImpact impact,
      WorldImpactVisitor visitor, ImpactUseCase impactUse) {
    // TODO(johnniwinther): Compute the application strategy once for each use.
    if (impactUse == ResolutionEnqueuer.IMPACT_USE) {
      if (supportDeferredLoad) {
        impact.apply(visitor);
      } else {
        impact.apply(visitor);
      }
    } 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(impactSource);
    } else {
      impact.apply(visitor);
    }
  }

  @override
  void onImpactUsed(ImpactUseCase impactUse) {
    if (impactUse == DeferredLoadTask.IMPACT_USE) {
      impactCacheDeleter.emptyCache();
    }
  }
}

/// Interface for resources only used during code generation.
abstract class CodegenInputs {
  CheckedModeHelpers get checkedModeHelpers;
  RuntimeTypesSubstitutions get rtiSubstitutions;
  RuntimeTypesEncoder get rtiEncoder;
  Tracer get tracer;
  RuntimeTypeTags get rtiTags;
  FixedNames get fixedNames;
}

class CodegenInputsImpl implements CodegenInputs {
  @override
  final CheckedModeHelpers checkedModeHelpers = new CheckedModeHelpers();

  @override
  final RuntimeTypesSubstitutions rtiSubstitutions;

  @override
  final RuntimeTypesEncoder rtiEncoder;

  @override
  final Tracer tracer;

  @override
  final RuntimeTypeTags rtiTags;

  @override
  final FixedNames fixedNames;

  CodegenInputsImpl(this.rtiSubstitutions, this.rtiEncoder, this.tracer,
      this.rtiTags, this.fixedNames);
}
