Delete JavaScriptBackend

* move names to Identifiers
* move resolution parts to front end strategy
* move codegen parts to backend strategy
* remove now unneeded methods from FrontendStrategy and BackendStrategy

Change-Id: I0675d56045dd212ad195177ecd23b27b0d849a80
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/105742
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/pkg/compiler/lib/src/backend_strategy.dart b/pkg/compiler/lib/src/backend_strategy.dart
index d9a48b1..b5307e1 100644
--- a/pkg/compiler/lib/src/backend_strategy.dart
+++ b/pkg/compiler/lib/src/backend_strategy.dart
@@ -12,18 +12,24 @@
 import 'elements/entities.dart';
 import 'inferrer/types.dart';
 import 'io/source_information.dart';
+import 'js_backend/backend.dart';
+import 'js_backend/enqueuer.dart';
 import 'js_backend/inferred_data.dart';
-import 'js_backend/interceptor_data.dart';
-import 'js_backend/native_data.dart';
+import 'js_emitter/code_emitter_task.dart';
 import 'serialization/serialization.dart';
 import 'ssa/ssa.dart';
 import 'universe/codegen_world_builder.dart';
-import 'universe/world_builder.dart';
 import 'world.dart';
 
 /// Strategy pattern that defines the element model used in type inference
 /// and code generation.
 abstract class BackendStrategy {
+  List<CompilerTask> get tasks;
+
+  FunctionCompiler get functionCompiler;
+
+  CodeEmitterTask get emitterTask;
+
   /// Create the [JClosedWorld] from [closedWorld].
   JClosedWorld createJClosedWorld(
       KClosedWorld closedWorld, OutputUnitData outputUnitData);
@@ -34,24 +40,27 @@
   /// This is used to support serialization after type inference.
   void registerJClosedWorld(JClosedWorld closedWorld);
 
-  /// Creates the [CodegenWorldBuilder] used by the codegen enqueuer.
-  CodegenWorldBuilder createCodegenWorldBuilder(
-      NativeBasicData nativeBasicData,
-      JClosedWorld closedWorld,
-      SelectorConstraintsStrategy selectorConstraintsStrategy,
-      OneShotInterceptorData oneShotInterceptorData);
+  /// Called when the compiler starts running the codegen.
+  ///
+  /// Returns the [CodegenInputs] objects with the needed data.
+  CodegenInputs onCodegenStart(
+      GlobalTypeInferenceResults globalTypeInferenceResults);
 
-  /// Creates the [WorkItemBuilder] used by the codegen enqueuer.
-  WorkItemBuilder createCodegenWorkItemBuilder(
-      JClosedWorld closedWorld, CodegenResults codegenResults);
+  /// Creates an [Enqueuer] for code generation specific to this backend.
+  CodegenEnqueuer createCodegenEnqueuer(
+      CompilerTask task,
+      JClosedWorld closedWorld,
+      GlobalTypeInferenceResults globalInferenceResults,
+      CodegenInputs codegen,
+      CodegenResults codegenResults);
+
+  /// Called when code generation has been completed.
+  void onCodegenEnd(CodegenInputs codegen);
 
   /// Creates the [SsaBuilder] used for the element model.
   SsaBuilder createSsaBuilder(
       CompilerTask task, SourceInformationStrategy sourceInformationStrategy);
 
-  /// Returns the [SourceInformationStrategy] use for the element model.
-  SourceInformationStrategy get sourceInformationStrategy;
-
   /// Creates a [SourceSpan] from [spannable] in context of [currentElement].
   SourceSpan spanFromSpannable(Spannable spannable, Entity currentElement);
 
@@ -69,4 +78,8 @@
 
   /// Prepare [source] to deserialize modular code generation data.
   void prepareCodegenReader(DataSource source);
+
+  /// Generates the output and returns the total size of the generated code.
+  int assembleProgram(JClosedWorld closedWorld, InferredData inferredData,
+      CodegenInputs codegenInputs, CodegenWorld codegenWorld);
 }
diff --git a/pkg/compiler/lib/src/common/names.dart b/pkg/compiler/lib/src/common/names.dart
index a8eaea4..d567451 100644
--- a/pkg/compiler/lib/src/common/names.dart
+++ b/pkg/compiler/lib/src/common/names.dart
@@ -43,6 +43,24 @@
 
   /// The name of the signature function in closure classes.
   static const String signature = ':signature';
+
+  /// The name of the 'JS' foreign function.
+  static const String JS = 'JS';
+
+  /// The name of the 'JS_BUILTIN' foreign function.
+  static const String JS_BUILTIN = 'JS_BUILTIN';
+
+  /// The name of the 'JS_EMBEDDED_GLOBAL' foreign function.
+  static const String JS_EMBEDDED_GLOBAL = 'JS_EMBEDDED_GLOBAL';
+
+  /// The name of the 'JS_INTERCEPTOR_CONSTANT' foreign function.
+  static const String JS_INTERCEPTOR_CONSTANT = 'JS_INTERCEPTOR_CONSTANT';
+
+  /// The name of the 'JS_STRING_CONCAT' foreign function.
+  static const String JS_STRING_CONCAT = 'JS_STRING_CONCAT';
+
+  /// The name of the 'DART_CLOSURE_TO_JS' foreign function.
+  static const String DART_CLOSURE_TO_JS = 'DART_CLOSURE_TO_JS';
 }
 
 /// [Name]s commonly used.
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index ed69778..e10e024 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -32,7 +32,7 @@
 import 'inferrer/types.dart'
     show GlobalTypeInferenceResults, GlobalTypeInferenceTask;
 import 'io/source_information.dart' show SourceInformation;
-import 'js_backend/backend.dart' show CodegenInputs, JavaScriptBackend;
+import 'js_backend/backend.dart' show CodegenInputs, JavaScriptImpactStrategy;
 import 'js_backend/inferred_data.dart';
 import 'js_model/js_strategy.dart';
 import 'kernel/kernel_strategy.dart';
@@ -97,7 +97,6 @@
   List<CompilerTask> tasks;
   KernelLoaderTask kernelLoader;
   GlobalTypeInferenceTask globalInference;
-  JavaScriptBackend backend;
   CodegenWorldBuilder _codegenWorldBuilder;
 
   AbstractValueStrategy abstractValueStrategy;
@@ -148,9 +147,9 @@
       _reporter = new CompilerDiagnosticReporter(this, options);
     }
     kernelFrontEndTask = new GenericTask('Front end', measurer);
-    frontendStrategy = new KernelFrontEndStrategy(
+    frontendStrategy = new KernelFrontendStrategy(
         kernelFrontEndTask, options, reporter, environment);
-    backendStrategy = new JsBackendStrategy(this);
+    backendStrategy = createBackendStrategy();
     _impactCache = <Entity, WorldImpact>{};
     _impactCacheDeleter = new _MapImpactCacheDeleter(_impactCache);
 
@@ -158,8 +157,7 @@
       progress = new InteractiveProgress();
     }
 
-    backend = createBackend();
-    enqueuer = backend.makeEnqueuer();
+    enqueuer = new EnqueueTask(this);
 
     tasks = [
       kernelLoader = new KernelLoaderTask(
@@ -176,17 +174,14 @@
           options, reporter, provider, outputProvider, measurer),
     ];
 
-    tasks.addAll(backend.tasks);
+    tasks.addAll(backendStrategy.tasks);
   }
 
-  /// Creates the backend.
+  /// Creates the backend strategy.
   ///
-  /// Override this to mock the backend for testing.
-  JavaScriptBackend createBackend() {
-    return new JavaScriptBackend(this,
-        generateSourceMap: options.generateSourceMap,
-        useMultiSourceInfo: options.useMultiSourceInfo,
-        useNewSourceInfo: options.useNewSourceInfo);
+  /// Override this to mock the backend strategy for testing.
+  BackendStrategy createBackendStrategy() {
+    return new JsBackendStrategy(this);
   }
 
   ResolutionWorldBuilder get resolutionWorldBuilder =>
@@ -247,11 +242,6 @@
       if (options.cfeOnly) return;
 
       frontendStrategy.registerLoadedLibraries(result);
-      for (Uri uri in result.libraries) {
-        LibraryEntity library =
-            frontendStrategy.elementEnvironment.lookupLibrary(uri);
-        backend.setAnnotations(library);
-      }
 
       // TODO(efortuna, sigmund): These validation steps should be done in the
       // front end for the Kernel path since Kernel doesn't have the notion of
@@ -272,7 +262,7 @@
     backendStrategy.registerJClosedWorld(closedWorld);
     phase = PHASE_COMPILING;
     CodegenInputs codegenInputs =
-        backend.onCodegenStart(globalTypeInferenceResults);
+        backendStrategy.onCodegenStart(globalTypeInferenceResults);
 
     if (options.readCodegenUri != null) {
       CodegenResults codegenResults =
@@ -283,7 +273,9 @@
     } else {
       reporter.log('Compiling methods');
       CodegenResults codegenResults = new OnDemandCodegenResults(
-          globalTypeInferenceResults, codegenInputs, backend.functionCompiler);
+          globalTypeInferenceResults,
+          codegenInputs,
+          backendStrategy.functionCompiler);
       if (options.writeCodegenUri != null) {
         serializationTask.serializeCodegen(backendStrategy, codegenResults);
       } else {
@@ -320,7 +312,7 @@
       resolutionEnqueuer = enqueuer.resolution;
     } else {
       resolutionEnqueuer = enqueuer.createResolutionEnqueuer();
-      backend.onResolutionStart();
+      frontendStrategy.onResolutionStart();
     }
     return resolutionEnqueuer;
   }
@@ -344,7 +336,9 @@
     // something to the resolution queue.  So we cannot wait with
     // this until after the resolution queue is processed.
     deferredLoadTask.beforeResolution(rootLibraryUri, libraries);
-    impactStrategy = backend.createImpactStrategy(
+
+    impactStrategy = new JavaScriptImpactStrategy(
+        impactCacheDeleter, dumpInfoTask,
         supportDeferredLoad: deferredLoadTask.isProgramSplit,
         supportDumpInfo: options.dumpInfo);
 
@@ -355,7 +349,7 @@
     processQueue(
         frontendStrategy.elementEnvironment, resolutionEnqueuer, mainFunction,
         onProgress: showResolutionProgress);
-    backend.onResolutionEnd();
+    frontendStrategy.onResolutionEnd();
     resolutionEnqueuer.logSummary(reporter.log);
 
     _reporter.reportSuppressedMessagesSummary();
@@ -402,7 +396,7 @@
       codegenWorldForTesting = codegenWorld;
     }
     reporter.log('Emitting JavaScript');
-    int programSize = backend.assembleProgram(closedWorld,
+    int programSize = backendStrategy.assembleProgram(closedWorld,
         globalInferenceResults.inferredData, codegenInputs, codegenWorld);
 
     if (options.dumpInfo) {
@@ -410,7 +404,7 @@
       dumpInfoTask.dumpInfo(closedWorld, globalInferenceResults);
     }
 
-    backend.onCodegenEnd(codegenInputs);
+    backendStrategy.onCodegenEnd(codegenInputs);
 
     checkQueue(codegenEnqueuer);
   }
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index 454d157..83f3790 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -12,6 +12,7 @@
 import 'package:dart2js_info/binary_serialization.dart' as dump_info;
 
 import '../compiler_new.dart';
+import 'backend_strategy.dart';
 import 'common/names.dart';
 import 'common/tasks.dart' show CompilerTask;
 import 'common.dart';
@@ -24,7 +25,6 @@
 import 'inferrer/types.dart'
     show GlobalTypeInferenceMemberResult, GlobalTypeInferenceResults;
 import 'js/js.dart' as jsAst;
-import 'js_backend/js_backend.dart' show JavaScriptBackend;
 import 'js_backend/field_analysis.dart';
 import 'universe/codegen_world_builder.dart';
 import 'universe/world_impact.dart'
@@ -204,7 +204,7 @@
 
     classInfo.size = size;
 
-    if (!compiler.backend.emitterTask.neededClasses.contains(clazz) &&
+    if (!compiler.backendStrategy.emitterTask.neededClasses.contains(clazz) &&
         classInfo.fields.isEmpty &&
         classInfo.functions.isEmpty) {
       return null;
@@ -344,13 +344,13 @@
     return _outputToInfo.putIfAbsent(outputUnit, () {
       // Dump-info currently only works with the full emitter. If another
       // emitter is used it will fail here.
-      JavaScriptBackend backend = compiler.backend;
+      BackendStrategy backendStrategy = compiler.backendStrategy;
       assert(outputUnit.name != null || outputUnit.isMainOutput);
       var filename = outputUnit.isMainOutput
           ? compiler.options.outputUri.pathSegments.last
           : deferredPartFileName(compiler.options, outputUnit.name);
       OutputUnitInfo info = new OutputUnitInfo(filename, outputUnit.name,
-          backend.emitterTask.emitter.generatedSize(outputUnit));
+          backendStrategy.emitterTask.emitter.generatedSize(outputUnit));
       info.imports
           .addAll(closedWorld.outputUnitData.getImportNames(outputUnit));
       result.outputUnits.add(info);
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index 81ca07d..9529615 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -61,7 +61,7 @@
   }
 
   ResolutionEnqueuer createResolutionEnqueuer() {
-    return _resolution ??= compiler.backend
+    return _resolution ??= compiler.frontendStrategy
         .createResolutionEnqueuer(this, compiler)
           ..onEmptyForTesting = compiler.onResolutionQueueEmptyForTesting;
   }
@@ -71,7 +71,7 @@
       GlobalTypeInferenceResults globalInferenceResults,
       CodegenInputs codegenInputs,
       CodegenResults codegenResults) {
-    Enqueuer enqueuer = compiler.backend.createCodegenEnqueuer(this, compiler,
+    Enqueuer enqueuer = compiler.backendStrategy.createCodegenEnqueuer(this,
         closedWorld, globalInferenceResults, codegenInputs, codegenResults)
       ..onEmptyForTesting = compiler.onCodegenQueueEmptyForTesting;
     if (retainDataForTesting) {
diff --git a/pkg/compiler/lib/src/frontend_strategy.dart b/pkg/compiler/lib/src/frontend_strategy.dart
index 4d0e320..5ae38ec 100644
--- a/pkg/compiler/lib/src/frontend_strategy.dart
+++ b/pkg/compiler/lib/src/frontend_strategy.dart
@@ -4,27 +4,16 @@
 
 library dart2js.frontend_strategy;
 
-import 'common/backend_api.dart';
 import 'common.dart';
+import 'common/tasks.dart';
 import 'common_elements.dart';
 import 'compiler.dart' show Compiler;
 import 'deferred_load.dart' show DeferredLoadTask;
 import 'elements/entities.dart';
-import 'elements/types.dart';
 import 'enqueue.dart';
-import 'js_backend/annotations.dart';
-import 'js_backend/field_analysis.dart' show KFieldAnalysis;
-import 'js_backend/backend_usage.dart';
-import 'js_backend/interceptor_data.dart';
 import 'js_backend/native_data.dart';
 import 'js_backend/no_such_method_registry.dart';
-import 'js_backend/runtime_types.dart';
 import 'kernel/loader.dart';
-import 'native/enqueue.dart' show NativeResolutionEnqueuer;
-import 'native/resolver.dart';
-import 'universe/class_hierarchy.dart';
-import 'universe/resolution_world_builder.dart';
-import 'universe/world_builder.dart';
 import 'universe/world_impact.dart';
 
 /// Strategy pattern that defines the connection between the input format and
@@ -41,63 +30,27 @@
   /// strategy.
   CommonElements get commonElements;
 
-  /// Returns the [DartTypes] for the element model used in this strategy.
-  DartTypes get dartTypes;
-
-  /// Returns the [AnnotationProcessor] for this strategy.
-  AnnotationProcessor get annotationProcessor;
-
   NativeBasicData get nativeBasicData;
 
   /// Creates a [DeferredLoadTask] for the element model used in this strategy.
   DeferredLoadTask createDeferredLoadTask(Compiler compiler);
 
-  /// Creates the [NativeClassFinder] for this strategy.
-  NativeClassFinder createNativeClassFinder(NativeBasicData nativeBasicData);
+  /// Support for classifying `noSuchMethod` implementations.
+  NoSuchMethodRegistry get noSuchMethodRegistry;
 
-  /// Creates the [NoSuchMethodResolver] corresponding the resolved model of
-  /// this strategy.
-  NoSuchMethodResolver createNoSuchMethodResolver();
+  /// Called before processing of the resolution queue is started.
+  void onResolutionStart();
 
-  /// Returns the [RuntimeTypesNeedBuilder] used by this frontend strategy.
-  RuntimeTypesNeedBuilder get runtimeTypesNeedBuilderForTesting;
+  ResolutionEnqueuer createResolutionEnqueuer(
+      CompilerTask task, Compiler compiler);
 
-  /// Creates the [ResolutionWorldBuilder] corresponding to the element model
-  /// used in this strategy.
-  ResolutionWorldBuilder createResolutionWorldBuilder(
-      NativeBasicData nativeBasicData,
-      NativeDataBuilder nativeDataBuilder,
-      InterceptorDataBuilder interceptorDataBuilder,
-      BackendUsageBuilder backendUsageBuilder,
-      RuntimeTypesNeedBuilder rtiNeedBuilder,
-      KFieldAnalysis allocatorAnalysis,
-      NativeResolutionEnqueuer nativeResolutionEnqueuer,
-      NoSuchMethodRegistry noSuchMethodRegistry,
-      AnnotationsDataBuilder annotationsDataBuilder,
-      SelectorConstraintsStrategy selectorConstraintsStrategy,
-      ClassHierarchyBuilder classHierarchyBuilder,
-      ClassQueries classQueries);
-
-  /// Creates the [WorkItemBuilder] corresponding to how a resolved model for
-  /// a single member is obtained in this strategy.
-  WorkItemBuilder createResolutionWorkItemBuilder(
-      NativeBasicData nativeBasicData,
-      NativeDataBuilder nativeDataBuilder,
-      AnnotationsDataBuilder annotationsDataBuilder,
-      ImpactTransformer impactTransformer,
-      Map<Entity, WorldImpact> impactCache,
-      KFieldAnalysis fieldAnalysis);
+  /// Called when the resolution queue has been closed.
+  void onResolutionEnd();
 
   /// Computes the main function from [mainLibrary] adding additional world
   /// impact to [impactBuilder].
   FunctionEntity computeMain(WorldImpactBuilder impactBuilder);
 
-  /// Creates the [RuntimeTypesNeedBuilder] for this strategy.
-  RuntimeTypesNeedBuilder createRuntimeTypesNeedBuilder();
-
-  /// Creates the [ClassQueries] for this strategy.
-  ClassQueries createClassQueries();
-
   /// Creates a [SourceSpan] from [spannable] in context of [currentElement].
   SourceSpan spanFromSpannable(Spannable spannable, Entity currentElement);
 }
@@ -112,24 +65,6 @@
       NativeBasicData nativeBasicData, NativeDataBuilder nativeDataBuilder);
 }
 
-abstract class FrontendStrategyBase implements FrontendStrategy {
-  final NativeBasicDataBuilderImpl nativeBasicDataBuilder =
-      new NativeBasicDataBuilderImpl();
-  NativeBasicData _nativeBasicData;
-
-  @override
-  NativeBasicData get nativeBasicData {
-    if (_nativeBasicData == null) {
-      _nativeBasicData = nativeBasicDataBuilder.close(elementEnvironment);
-      assert(
-          _nativeBasicData != null,
-          failedAt(NO_LOCATION_SPANNABLE,
-              "NativeBasicData has not been computed yet."));
-    }
-    return _nativeBasicData;
-  }
-}
-
 /// Class that deletes the contents of an [WorldImpact] cache.
 // TODO(redemption): this can be deleted when we sunset the old front end.
 abstract class ImpactCacheDeleter {
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index 585c560..d34c1d0 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -17,7 +17,6 @@
 import '../ir/constants.dart';
 import '../ir/static_type_provider.dart';
 import '../ir/util.dart';
-import '../js_backend/backend.dart';
 import '../js_backend/field_analysis.dart';
 import '../js_model/element_map.dart';
 import '../js_model/locals.dart' show JumpVisitor;
@@ -1244,22 +1243,22 @@
       AbstractValue mask) {
     String name = function.name;
     handleStaticInvoke(node, selector, mask, function, arguments);
-    if (name == JavaScriptBackend.JS) {
+    if (name == Identifiers.JS) {
       NativeBehavior nativeBehavior =
           _elementMap.getNativeBehaviorForJsCall(node);
       _sideEffectsBuilder.add(nativeBehavior.sideEffects);
       return _inferrer.typeOfNativeBehavior(nativeBehavior);
-    } else if (name == JavaScriptBackend.JS_EMBEDDED_GLOBAL) {
+    } else if (name == Identifiers.JS_EMBEDDED_GLOBAL) {
       NativeBehavior nativeBehavior =
           _elementMap.getNativeBehaviorForJsEmbeddedGlobalCall(node);
       _sideEffectsBuilder.add(nativeBehavior.sideEffects);
       return _inferrer.typeOfNativeBehavior(nativeBehavior);
-    } else if (name == JavaScriptBackend.JS_BUILTIN) {
+    } else if (name == Identifiers.JS_BUILTIN) {
       NativeBehavior nativeBehavior =
           _elementMap.getNativeBehaviorForJsBuiltinCall(node);
       _sideEffectsBuilder.add(nativeBehavior.sideEffects);
       return _inferrer.typeOfNativeBehavior(nativeBehavior);
-    } else if (name == JavaScriptBackend.JS_STRING_CONCAT) {
+    } else if (name == Identifiers.JS_STRING_CONCAT) {
       return _types.stringType;
     } else {
       _sideEffectsBuilder.setAllSideEffects();
diff --git a/pkg/compiler/lib/src/inferrer/closure_tracer.dart b/pkg/compiler/lib/src/inferrer/closure_tracer.dart
index 7558fcc..3ee6a53 100644
--- a/pkg/compiler/lib/src/inferrer/closure_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/closure_tracer.dart
@@ -4,9 +4,8 @@
 
 library compiler.src.inferrer.closure_tracer;
 
-import '../common/names.dart' show Names;
+import '../common/names.dart' show Identifiers, Names;
 import '../elements/entities.dart';
-import '../js_backend/backend.dart' show JavaScriptBackend;
 import '../universe/selector.dart' show Selector;
 import 'abstract_value_domain.dart';
 import 'debug.dart' as debug;
@@ -85,7 +84,7 @@
     MemberEntity called = info.calledElement;
     if (inferrer.closedWorld.commonElements.isForeign(called)) {
       String name = called.name;
-      if (name == JavaScriptBackend.JS || name == 'DART_CLOSURE_TO_JS') {
+      if (name == Identifiers.JS || name == Identifiers.DART_CLOSURE_TO_JS) {
         bailout('Used in JS ${info.debugName}');
       }
     }
diff --git a/pkg/compiler/lib/src/inferrer/list_tracer.dart b/pkg/compiler/lib/src/inferrer/list_tracer.dart
index 0f7aa07..aaa69e4 100644
--- a/pkg/compiler/lib/src/inferrer/list_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/list_tracer.dart
@@ -4,8 +4,8 @@
 
 library compiler.src.inferrer.list_tracer;
 
+import '../common/names.dart';
 import '../elements/entities.dart';
-import '../js_backend/backend.dart' show JavaScriptBackend;
 import '../universe/selector.dart' show Selector;
 import '../util/util.dart' show Setlet;
 import 'node_tracer.dart';
@@ -164,7 +164,7 @@
     super.visitStaticCallSiteTypeInformation(info);
     MemberEntity called = info.calledElement;
     if (inferrer.closedWorld.commonElements.isForeign(called) &&
-        called.name == JavaScriptBackend.JS) {
+        called.name == Identifiers.JS) {
       bailout('Used in JS ${info.debugName}');
     }
   }
diff --git a/pkg/compiler/lib/src/inferrer/map_tracer.dart b/pkg/compiler/lib/src/inferrer/map_tracer.dart
index 4925dfc..f21fd15 100644
--- a/pkg/compiler/lib/src/inferrer/map_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/map_tracer.dart
@@ -4,8 +4,8 @@
 
 library compiler.src.inferrer.map_tracer;
 
+import '../common/names.dart';
 import '../elements/entities.dart';
-import '../js_backend/backend.dart' show JavaScriptBackend;
 import '../universe/selector.dart' show Selector;
 import 'node_tracer.dart';
 import 'type_graph_nodes.dart';
@@ -68,7 +68,7 @@
     super.visitStaticCallSiteTypeInformation(info);
     MemberEntity called = info.calledElement;
     if (inferrer.closedWorld.commonElements.isForeign(called) &&
-        called.name == JavaScriptBackend.JS) {
+        called.name == Identifiers.JS) {
       bailout('Used in JS ${info.debugName}');
     }
   }
diff --git a/pkg/compiler/lib/src/inferrer/set_tracer.dart b/pkg/compiler/lib/src/inferrer/set_tracer.dart
index 6c809ad..72cf043 100644
--- a/pkg/compiler/lib/src/inferrer/set_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/set_tracer.dart
@@ -4,8 +4,8 @@
 
 library compiler.src.inferrer.set_tracer;
 
+import '../common/names.dart';
 import '../elements/entities.dart';
-import '../js_backend/backend.dart' show JavaScriptBackend;
 import '../universe/selector.dart' show Selector;
 import 'node_tracer.dart';
 import 'type_graph_nodes.dart';
@@ -93,7 +93,7 @@
     super.visitStaticCallSiteTypeInformation(info);
     MemberEntity called = info.calledElement;
     if (inferrer.closedWorld.commonElements.isForeign(called) &&
-        called.name == JavaScriptBackend.JS) {
+        called.name == Identifiers.JS) {
       bailout('Used in JS ${info.debugName}');
     }
   }
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
index d1b919c..3a41951 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
@@ -76,7 +76,7 @@
         _compiler.reporter,
         _compiler.outputProvider,
         closedWorld,
-        _compiler.backend.noSuchMethodRegistry,
+        _compiler.frontendStrategy.noSuchMethodRegistry,
         main,
         _inferredDataBuilder);
   }
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index d187523..5e22b23 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -5,50 +5,20 @@
 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 '../enqueue.dart' show 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 {
@@ -292,466 +262,6 @@
   }
 }
 
-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,
-      CodegenResults codegenResults) {
-    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, codegenResults),
-        new CodegenEnqueuerListener(
-            elementEnvironment,
-            commonElements,
-            impacts,
-            closedWorld.backendUsage,
-            closedWorld.rtiNeed,
-            customElementsCodegenAnalysis,
-            nativeCodegenEnqueuer));
-  }
-
-  Map<MemberEntity, WorldImpact> codegenImpactsForTesting;
-
-  WorldImpact generateCode(
-      WorkItem work,
-      JClosedWorld closedWorld,
-      CodegenResults codegenResults,
-      EntityLookup entityLookup,
-      ComponentLookup componentLookup) {
-    MemberEntity member = work.element;
-    CodegenResult result = codegenResults.getCodegenResults(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 codegenInputs, CodegenWorld codegenWorld) {
-    int programSize = emitterTask.assembleProgram(
-        _namer, closedWorld, inferredData, codegenInputs, 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;
diff --git a/pkg/compiler/lib/src/js_backend/field_analysis.dart b/pkg/compiler/lib/src/js_backend/field_analysis.dart
index 7349b4d..77aa43e 100644
--- a/pkg/compiler/lib/src/js_backend/field_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/field_analysis.dart
@@ -41,7 +41,7 @@
   final Map<KClass, ClassData> _classData = {};
   final Map<KField, StaticFieldData> _staticFieldData = {};
 
-  KFieldAnalysis(KernelFrontEndStrategy kernelStrategy)
+  KFieldAnalysis(KernelFrontendStrategy kernelStrategy)
       : _elementMap = kernelStrategy.elementMap;
 
   // Register class during resolution. Use simple syntactic analysis to find
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
index 3871204..c9b0ec1 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -11,9 +11,10 @@
 import '../deferred_load.dart' show OutputUnit;
 import '../elements/entities.dart';
 import '../js/js.dart' as jsAst;
-import '../js_backend/backend.dart' show CodegenInputs, JavaScriptBackend;
+import '../js_backend/backend.dart' show CodegenInputs;
 import '../js_backend/inferred_data.dart';
 import '../js_backend/namer.dart' show Namer;
+import '../js_model/js_strategy.dart';
 import '../universe/codegen_world_builder.dart';
 import '../world.dart' show JClosedWorld;
 import 'program_builder/program_builder.dart';
@@ -36,7 +37,7 @@
   final Compiler _compiler;
   final bool _generateSourceMap;
 
-  JavaScriptBackend get _backend => _compiler.backend;
+  JsBackendStrategy get _backendStrategy => _compiler.backendStrategy;
 
   @deprecated
   // This field should be removed. It's currently only needed for dump-info and
@@ -69,18 +70,18 @@
     // Compute the required type checks to know which classes need a
     // 'is$' method.
     typeTestRegistry.computeRequiredTypeChecks(
-        _backend.rtiChecksBuilder, codegenWorld);
+        _backendStrategy.rtiChecksBuilder, codegenWorld);
     // Compute the classes needed by RTI.
     typeTestRegistry.computeRtiNeededClasses(
-        codegen.rtiSubstitutions, _backend.generatedCode.keys);
+        codegen.rtiSubstitutions, _backendStrategy.generatedCode.keys);
   }
 
   /// Creates the [Emitter] for this task.
   void createEmitter(
       Namer namer, CodegenInputs codegen, JClosedWorld closedWorld) {
     measure(() {
-      _nativeEmitter =
-          new NativeEmitter(this, closedWorld, _backend.nativeCodegenEnqueuer);
+      _nativeEmitter = new NativeEmitter(
+          this, closedWorld, _backendStrategy.nativeCodegenEnqueuer);
       _emitter = new startup_js_emitter.EmitterImpl(
           _compiler.options,
           _compiler.reporter,
@@ -89,7 +90,7 @@
           namer,
           closedWorld,
           codegen.rtiEncoder,
-          _backend.sourceInformationStrategy,
+          _backendStrategy.sourceInformationStrategy,
           this,
           _generateSourceMap);
       metadataCollector = new MetadataCollector(
@@ -120,7 +121,7 @@
           closedWorld.commonElements,
           closedWorld.outputUnitData,
           codegenWorld,
-          _backend.nativeCodegenEnqueuer,
+          _backendStrategy.nativeCodegenEnqueuer,
           closedWorld.backendUsage,
           closedWorld.nativeData,
           closedWorld.rtiNeed,
@@ -128,14 +129,14 @@
           typeTestRegistry.rtiChecks,
           codegenInputs.rtiEncoder,
           codegenWorld.oneShotInterceptorData,
-          _backend.customElementsCodegenAnalysis,
-          _backend.generatedCode,
+          _backendStrategy.customElementsCodegenAnalysis,
+          _backendStrategy.generatedCode,
           namer,
           this,
           closedWorld,
           closedWorld.fieldAnalysis,
           inferredData,
-          _backend.sourceInformationStrategy,
+          _backendStrategy.sourceInformationStrategy,
           closedWorld.sorter,
           typeTestRegistry.rtiNeededClasses,
           closedWorld.elementEnvironment.mainFunction);
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index 2a64023..136fe7f 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -8,9 +8,10 @@
 
 import '../backend_strategy.dart';
 import '../common.dart';
-import '../common/codegen.dart' show CodegenRegistry, CodegenResults;
+import '../common/codegen.dart';
 import '../common/tasks.dart';
 import '../common/work.dart';
+import '../common_elements.dart' show CommonElements, ElementEnvironment;
 import '../compiler.dart';
 import '../deferred_load.dart' hide WorkItem;
 import '../dump_info.dart';
@@ -24,22 +25,30 @@
 import '../inferrer/types.dart';
 import '../js/js_source_mapping.dart';
 import '../js_backend/backend.dart';
+import '../js_backend/backend_impact.dart';
+import '../js_backend/codegen_listener.dart';
+import '../js_backend/custom_elements_analysis.dart';
+import '../js_backend/enqueuer.dart';
+import '../js_backend/impact_transformer.dart';
 import '../js_backend/inferred_data.dart';
 import '../js_backend/interceptor_data.dart';
-import '../js_backend/native_data.dart';
-import '../js_backend/namer.dart' show ModularNamer;
+import '../js_backend/namer.dart';
+import '../js_backend/runtime_types.dart';
 import '../js_emitter/code_emitter_task.dart' show ModularEmitter;
+import '../js_emitter/js_emitter.dart' show CodeEmitterTask;
+import '../js/js.dart' as js;
 import '../kernel/kernel_strategy.dart';
 import '../native/behavior.dart';
+import '../native/enqueue.dart';
 import '../options.dart';
 import '../serialization/serialization.dart';
 import '../ssa/builder_kernel.dart';
 import '../ssa/nodes.dart';
 import '../ssa/ssa.dart';
 import '../ssa/types.dart';
+import '../tracer.dart';
 import '../universe/codegen_world_builder.dart';
 import '../universe/selector.dart';
-import '../universe/world_builder.dart';
 import '../universe/world_impact.dart';
 import '../world.dart';
 import 'closure.dart';
@@ -53,7 +62,69 @@
   final Compiler _compiler;
   JsKernelToElementMap _elementMap;
 
-  JsBackendStrategy(this._compiler);
+  /// Codegen support for generating table of interceptors and
+  /// constructors for custom elements.
+  CustomElementsCodegenAnalysis _customElementsCodegenAnalysis;
+
+  NativeCodegenEnqueuer _nativeCodegenEnqueuer;
+
+  Namer _namer;
+
+  CodegenImpactTransformer _codegenImpactTransformer;
+
+  CodeEmitterTask _emitterTask;
+
+  RuntimeTypesChecksBuilder _rtiChecksBuilder;
+
+  FunctionCompiler _functionCompiler;
+
+  SourceInformationStrategy sourceInformationStrategy;
+
+  /// The generated code as a js AST for compiled methods.
+  final Map<MemberEntity, js.Expression> generatedCode =
+      <MemberEntity, js.Expression>{};
+
+  JsBackendStrategy(this._compiler) {
+    bool generateSourceMap = _compiler.options.generateSourceMap;
+    if (!generateSourceMap) {
+      sourceInformationStrategy = const JavaScriptSourceInformationStrategy();
+    } else {
+      sourceInformationStrategy = new KernelSourceInformationStrategy(this);
+    }
+    _emitterTask = new CodeEmitterTask(_compiler, generateSourceMap);
+    _functionCompiler = new SsaFunctionCompiler(
+        _compiler.options,
+        _compiler.reporter,
+        this,
+        _compiler.measurer,
+        sourceInformationStrategy);
+  }
+
+  @override
+  List<CompilerTask> get tasks {
+    List<CompilerTask> result = functionCompiler.tasks;
+    result.add(emitterTask);
+    return result;
+  }
+
+  @override
+  FunctionCompiler get functionCompiler => _functionCompiler;
+
+  @override
+  CodeEmitterTask get emitterTask => _emitterTask;
+
+  Namer get namerForTesting => _namer;
+
+  NativeEnqueuer get nativeCodegenEnqueuer => _nativeCodegenEnqueuer;
+
+  RuntimeTypesChecksBuilder get rtiChecksBuilderForTesting => _rtiChecksBuilder;
+
+  Map<MemberEntity, WorldImpact> codegenImpactsForTesting;
+
+  String getGeneratedCodeForTesting(MemberEntity element) {
+    return js.prettyPrint(generatedCode[element],
+        enableMinification: _compiler.options.enableMinification);
+  }
 
   @deprecated
   JsToElementMap get elementMap {
@@ -62,10 +133,32 @@
     return _elementMap;
   }
 
+  /// 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;
+  }
+
   @override
   JClosedWorld createJClosedWorld(
       KClosedWorld closedWorld, OutputUnitData outputUnitData) {
-    KernelFrontEndStrategy strategy = _compiler.frontendStrategy;
+    KernelFrontendStrategy strategy = _compiler.frontendStrategy;
     _elementMap = new JsKernelToElementMap(
         _compiler.reporter,
         _compiler.environment,
@@ -94,11 +187,178 @@
   }
 
   @override
-  SourceInformationStrategy get sourceInformationStrategy {
-    if (!_compiler.options.generateSourceMap) {
-      return const JavaScriptSourceInformationStrategy();
+  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;
     }
-    return new KernelSourceInformationStrategy(this);
+
+    CodegenInputs codegen = new CodegenInputsImpl(
+        rtiSubstitutions, rtiEncoder, tracer, rtiTags, fixedNames);
+
+    functionCompiler.initialize(globalTypeInferenceResults, codegen);
+    return codegen;
+  }
+
+  @override
+  CodegenEnqueuer createCodegenEnqueuer(
+      CompilerTask task,
+      JClosedWorld closedWorld,
+      GlobalTypeInferenceResults globalInferenceResults,
+      CodegenInputs codegen,
+      CodegenResults codegenResults) {
+    assert(_elementMap != null,
+        "JsBackendStrategy.elementMap has not been created yet.");
+    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,
+        new CodegenWorldBuilderImpl(
+            closedWorld,
+            _compiler.abstractValueStrategy.createSelectorStrategy(),
+            oneShotInterceptorData),
+        new KernelCodegenWorkItemBuilder(
+            this,
+            closedWorld,
+            codegenResults,
+            new ClosedEntityLookup(_elementMap),
+            // TODO(johnniwinther): Avoid the need for a [ComponentLookup]. This
+            // is caused by some type masks holding a kernel node for using in
+            // tracing.
+            new ComponentLookup(_elementMap.programEnv.mainComponent)),
+        new CodegenEnqueuerListener(
+            elementEnvironment,
+            commonElements,
+            impacts,
+            closedWorld.backendUsage,
+            closedWorld.rtiNeed,
+            customElementsCodegenAnalysis,
+            nativeCodegenEnqueuer));
+  }
+
+  /// 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);
+  }
+
+  WorldImpact generateCode(
+      WorkItem work,
+      JClosedWorld closedWorld,
+      CodegenResults codegenResults,
+      EntityLookup entityLookup,
+      ComponentLookup componentLookup) {
+    MemberEntity member = work.element;
+    CodegenResult result = codegenResults.getCodegenResults(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;
+  }
+
+  @override
+  void onCodegenEnd(CodegenInputs codegen) {
+    sourceInformationStrategy.onComplete();
+    codegen.tracer.close();
+  }
+
+  @override
+  int assembleProgram(JClosedWorld closedWorld, InferredData inferredData,
+      CodegenInputs codegenInputs, CodegenWorld codegenWorld) {
+    int programSize = emitterTask.assembleProgram(
+        _namer, closedWorld, inferredData, codegenInputs, codegenWorld);
+    closedWorld.noSuchMethodData.emitDiagnostic(_compiler.reporter);
+    return programSize;
   }
 
   @override
@@ -115,32 +375,6 @@
   }
 
   @override
-  WorkItemBuilder createCodegenWorkItemBuilder(
-      JClosedWorld closedWorld, CodegenResults codegenResults) {
-    assert(_elementMap != null,
-        "JsBackendStrategy.elementMap has not been created yet.");
-    return new KernelCodegenWorkItemBuilder(
-        _compiler.backend,
-        closedWorld,
-        codegenResults,
-        new ClosedEntityLookup(_elementMap),
-        // TODO(johnniwinther): Avoid the need for a [ComponentLookup]. This
-        // is caused by some type masks holding a kernel node for using in
-        // tracing.
-        new ComponentLookup(_elementMap.programEnv.mainComponent));
-  }
-
-  @override
-  CodegenWorldBuilder createCodegenWorldBuilder(
-      NativeBasicData nativeBasicData,
-      JClosedWorld closedWorld,
-      SelectorConstraintsStrategy selectorConstraintsStrategy,
-      OneShotInterceptorData oneShotInterceptorData) {
-    return new CodegenWorldBuilderImpl(
-        closedWorld, selectorConstraintsStrategy, oneShotInterceptorData);
-  }
-
-  @override
   SourceSpan spanFromSpannable(Spannable spannable, Entity currentElement) {
     return _elementMap.getSourceSpan(spannable, currentElement);
   }
@@ -176,25 +410,25 @@
 }
 
 class KernelCodegenWorkItemBuilder implements WorkItemBuilder {
-  final JavaScriptBackend _backend;
+  final JsBackendStrategy _backendStrategy;
   final JClosedWorld _closedWorld;
   final CodegenResults _codegenResults;
   final EntityLookup _entityLookup;
   final ComponentLookup _componentLookup;
 
-  KernelCodegenWorkItemBuilder(this._backend, this._closedWorld,
+  KernelCodegenWorkItemBuilder(this._backendStrategy, this._closedWorld,
       this._codegenResults, this._entityLookup, this._componentLookup);
 
   @override
   WorkItem createWorkItem(MemberEntity entity) {
     if (entity.isAbstract) return null;
-    return new KernelCodegenWorkItem(_backend, _closedWorld, _codegenResults,
-        _entityLookup, _componentLookup, entity);
+    return new KernelCodegenWorkItem(_backendStrategy, _closedWorld,
+        _codegenResults, _entityLookup, _componentLookup, entity);
   }
 }
 
 class KernelCodegenWorkItem extends WorkItem {
-  final JavaScriptBackend _backend;
+  final JsBackendStrategy _backendStrategy;
   final JClosedWorld _closedWorld;
   final CodegenResults _codegenResults;
   final EntityLookup _entityLookup;
@@ -202,12 +436,17 @@
   @override
   final MemberEntity element;
 
-  KernelCodegenWorkItem(this._backend, this._closedWorld, this._codegenResults,
-      this._entityLookup, this._componentLookup, this.element);
+  KernelCodegenWorkItem(
+      this._backendStrategy,
+      this._closedWorld,
+      this._codegenResults,
+      this._entityLookup,
+      this._componentLookup,
+      this.element);
 
   @override
   WorldImpact run() {
-    return _backend.generateCode(
+    return _backendStrategy.generateCode(
         this, _closedWorld, _codegenResults, _entityLookup, _componentLookup);
   }
 }
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index ac8b66d..ce5aed9 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -41,7 +41,6 @@
 import '../ir/util.dart';
 import '../js/js.dart' as js;
 import '../js_backend/annotations.dart';
-import '../js_backend/backend.dart' show JavaScriptBackend;
 import '../js_backend/namer.dart';
 import '../js_backend/native_data.dart';
 import '../js_backend/no_such_method_registry.dart';
@@ -1486,13 +1485,13 @@
   ForeignKind getForeignKind(ir.StaticInvocation node) {
     if (commonElements.isForeignHelper(getMember(node.target))) {
       switch (node.target.name.name) {
-        case JavaScriptBackend.JS:
+        case Identifiers.JS:
           return ForeignKind.JS;
-        case JavaScriptBackend.JS_BUILTIN:
+        case Identifiers.JS_BUILTIN:
           return ForeignKind.JS_BUILTIN;
-        case JavaScriptBackend.JS_EMBEDDED_GLOBAL:
+        case Identifiers.JS_EMBEDDED_GLOBAL:
           return ForeignKind.JS_EMBEDDED_GLOBAL;
-        case JavaScriptBackend.JS_INTERCEPTOR_CONSTANT:
+        case Identifiers.JS_INTERCEPTOR_CONSTANT:
           return ForeignKind.JS_INTERCEPTOR_CONSTANT;
       }
     }
diff --git a/pkg/compiler/lib/src/kernel/kernel_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
index c93e50f..c5663d9 100644
--- a/pkg/compiler/lib/src/kernel/kernel_strategy.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
@@ -8,6 +8,7 @@
 
 import '../common.dart';
 import '../common/backend_api.dart';
+import '../common/names.dart' show Uris;
 import '../common/resolution.dart';
 import '../common/tasks.dart';
 import '../common/work.dart';
@@ -15,7 +16,6 @@
 import '../compiler.dart';
 import '../deferred_load.dart' show DeferredLoadTask;
 import '../elements/entities.dart';
-import '../elements/types.dart';
 import '../enqueue.dart';
 import '../environment.dart' as env;
 import '../frontend_strategy.dart';
@@ -25,12 +25,17 @@
 import '../ir/modular.dart';
 import '../ir/scope.dart' show ScopeModel;
 import '../js_backend/annotations.dart';
-import '../js_backend/field_analysis.dart' show KFieldAnalysis;
+import '../js_backend/backend_impact.dart';
 import '../js_backend/backend_usage.dart';
+import '../js_backend/custom_elements_analysis.dart';
+import '../js_backend/field_analysis.dart' show KFieldAnalysis;
+import '../js_backend/impact_transformer.dart';
 import '../js_backend/interceptor_data.dart';
 import '../js_backend/native_data.dart';
 import '../js_backend/no_such_method_registry.dart';
+import '../js_backend/resolution_listener.dart';
 import '../js_backend/runtime_types.dart';
+import '../kernel/dart2js_target.dart';
 import '../native/enqueue.dart' show NativeResolutionEnqueuer;
 import '../native/resolver.dart';
 import '../options.dart';
@@ -46,7 +51,10 @@
 
 /// Front end strategy that loads '.dill' files and builds a resolved element
 /// model from kernel IR nodes.
-class KernelFrontEndStrategy extends FrontendStrategyBase {
+class KernelFrontendStrategy extends FrontendStrategy {
+  final NativeBasicDataBuilderImpl nativeBasicDataBuilder =
+      new NativeBasicDataBuilderImpl();
+  NativeBasicData _nativeBasicData;
   CompilerOptions _options;
   CompilerTask _compilerTask;
   KernelToElementMapImpl _elementMap;
@@ -59,12 +67,179 @@
   ModularStrategy _modularStrategy;
   IrAnnotationData _irAnnotationData;
 
-  KernelFrontEndStrategy(this._compilerTask, this._options,
+  NativeDataBuilderImpl _nativeDataBuilder;
+  NativeDataBuilder get nativeDataBuilder => _nativeDataBuilder;
+
+  BackendUsageBuilder _backendUsageBuilder;
+
+  NativeResolutionEnqueuer _nativeResolutionEnqueuer;
+
+  /// Resolution support for generating table of interceptors and
+  /// constructors for custom elements.
+  CustomElementsResolutionAnalysis _customElementsResolutionAnalysis;
+
+  KFieldAnalysis _fieldAnalysis;
+
+  /// Backend transformation methods for the world impacts.
+  ImpactTransformer impactTransformer;
+
+  @override
+  NoSuchMethodRegistry noSuchMethodRegistry;
+
+  KernelFrontendStrategy(this._compilerTask, this._options,
       DiagnosticReporter reporter, env.Environment environment) {
     assert(_compilerTask != null);
     _elementMap =
         new KernelToElementMapImpl(reporter, environment, this, _options);
     _modularStrategy = new KernelModularStrategy(_compilerTask, _elementMap);
+    _backendUsageBuilder = new BackendUsageBuilderImpl(this);
+    noSuchMethodRegistry = new NoSuchMethodRegistryImpl(
+        commonElements, new KernelNoSuchMethodResolver(_elementMap));
+  }
+
+  NativeResolutionEnqueuer get nativeResolutionEnqueuerForTesting =>
+      _nativeResolutionEnqueuer;
+
+  KFieldAnalysis get fieldAnalysisForTesting => _fieldAnalysis;
+
+  @override
+  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.
+    elementEnvironment.getThisType(commonElements.jsArrayClass);
+    elementEnvironment.getThisType(commonElements.jsExtendableArrayClass);
+
+    _validateInterceptorImplementsAllObjectMethods(
+        commonElements.jsInterceptorClass);
+    // The null-interceptor must also implement *all* methods.
+    _validateInterceptorImplementsAllObjectMethods(commonElements.jsNullClass);
+  }
+
+  void _validateInterceptorImplementsAllObjectMethods(
+      ClassEntity interceptorClass) {
+    if (interceptorClass == null) return;
+    ClassEntity objectClass = commonElements.objectClass;
+    elementEnvironment.forEachClassMember(objectClass,
+        (_, MemberEntity member) {
+      MemberEntity interceptorMember = 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}."));
+    });
+  }
+
+  @override
+  ResolutionEnqueuer createResolutionEnqueuer(
+      CompilerTask task, Compiler compiler) {
+    RuntimeTypesNeedBuilder rtiNeedBuilder = _createRuntimeTypesNeedBuilder();
+    BackendImpacts impacts = new BackendImpacts(commonElements);
+    _nativeResolutionEnqueuer = new NativeResolutionEnqueuer(
+        compiler.options,
+        elementEnvironment,
+        commonElements,
+        _elementMap.types,
+        new BaseNativeClassFinder(elementEnvironment, nativeBasicData));
+    _nativeDataBuilder = new NativeDataBuilderImpl(nativeBasicData);
+    _customElementsResolutionAnalysis = new CustomElementsResolutionAnalysis(
+        elementEnvironment,
+        commonElements,
+        nativeBasicData,
+        _backendUsageBuilder);
+    _fieldAnalysis = new KFieldAnalysis(this);
+    ClassQueries classQueries = new KernelClassQueries(elementMap);
+    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),
+        new ResolutionWorldBuilderImpl(
+            _options,
+            elementMap,
+            elementEnvironment,
+            _elementMap.types,
+            commonElements,
+            nativeBasicData,
+            nativeDataBuilder,
+            interceptorDataBuilder,
+            _backendUsageBuilder,
+            rtiNeedBuilder,
+            _fieldAnalysis,
+            _nativeResolutionEnqueuer,
+            noSuchMethodRegistry,
+            annotationsDataBuilder,
+            const StrongModeWorldStrategy(),
+            classHierarchyBuilder,
+            classQueries),
+        new KernelWorkItemBuilder(
+            _compilerTask,
+            elementMap,
+            nativeBasicData,
+            nativeDataBuilder,
+            annotationsDataBuilder,
+            impactTransformer,
+            closureModels,
+            compiler.impactCache,
+            _fieldAnalysis,
+            _modularStrategy,
+            _irAnnotationData));
+  }
+
+  @override
+  void onResolutionEnd() {
+    assert(_annotationProcessor != null,
+        "AnnotationProcessor has not been created.");
+    _annotationProcessor.processJsInteropAnnotations(
+        nativeBasicData, nativeDataBuilder);
+  }
+
+  @override
+  NativeBasicData get nativeBasicData {
+    if (_nativeBasicData == null) {
+      _nativeBasicData = nativeBasicDataBuilder.close(elementEnvironment);
+      assert(
+          _nativeBasicData != null,
+          failedAt(NO_LOCATION_SPANNABLE,
+              "NativeBasicData has not been computed yet."));
+    }
+    return _nativeBasicData;
   }
 
   @override
@@ -76,6 +251,16 @@
     }
     _annotationProcessor = new KernelAnnotationProcessor(
         elementMap, nativeBasicDataBuilder, _irAnnotationData);
+    for (Uri uri in kernelResult.libraries) {
+      LibraryEntity library = elementEnvironment.lookupLibrary(uri);
+      if (maybeEnableNative(library.canonicalUri)) {
+        _annotationProcessor.extractNativeAnnotations(library);
+      }
+      _annotationProcessor.extractJsInteropAnnotations(library);
+      if (uri == Uris.dart_html) {
+        _backendUsageBuilder.registerHtmlIsLoaded();
+      }
+    }
   }
 
   IrAnnotationData get irAnnotationDataForTesting => _irAnnotationData;
@@ -88,112 +273,28 @@
   @override
   CommonElements get commonElements => _elementMap.commonElements;
 
-  @override
-  DartTypes get dartTypes => _elementMap.types;
-
   KernelToElementMap get elementMap => _elementMap;
 
   @override
-  AnnotationProcessor get annotationProcessor {
-    assert(_annotationProcessor != null,
-        "AnnotationProcessor has not been created.");
-    return _annotationProcessor;
-  }
-
-  @override
   DeferredLoadTask createDeferredLoadTask(Compiler compiler) =>
       new KernelDeferredLoadTask(compiler, _elementMap);
 
   @override
-  NativeClassFinder createNativeClassFinder(NativeBasicData nativeBasicData) {
-    return new BaseNativeClassFinder(
-        _elementMap.elementEnvironment, nativeBasicData);
-  }
-
-  @override
-  NoSuchMethodResolver createNoSuchMethodResolver() {
-    return new KernelNoSuchMethodResolver(elementMap);
-  }
-
-  @override
   FunctionEntity computeMain(WorldImpactBuilder impactBuilder) {
     return elementEnvironment.mainFunction;
   }
 
-  @override
-  RuntimeTypesNeedBuilder createRuntimeTypesNeedBuilder() {
+  RuntimeTypesNeedBuilder _createRuntimeTypesNeedBuilder() {
     return _runtimeTypesNeedBuilder ??= _options.disableRtiOptimization
         ? const TrivialRuntimeTypesNeedBuilder()
         : new RuntimeTypesNeedBuilderImpl(
             elementEnvironment, _elementMap.types);
   }
 
-  @override
   RuntimeTypesNeedBuilder get runtimeTypesNeedBuilderForTesting =>
       _runtimeTypesNeedBuilder;
 
   @override
-  ResolutionWorldBuilder createResolutionWorldBuilder(
-      NativeBasicData nativeBasicData,
-      NativeDataBuilder nativeDataBuilder,
-      InterceptorDataBuilder interceptorDataBuilder,
-      BackendUsageBuilder backendUsageBuilder,
-      RuntimeTypesNeedBuilder rtiNeedBuilder,
-      KFieldAnalysis allocatorAnalysis,
-      NativeResolutionEnqueuer nativeResolutionEnqueuer,
-      NoSuchMethodRegistry noSuchMethodRegistry,
-      AnnotationsDataBuilder annotationsDataBuilder,
-      SelectorConstraintsStrategy selectorConstraintsStrategy,
-      ClassHierarchyBuilder classHierarchyBuilder,
-      ClassQueries classQueries) {
-    return new ResolutionWorldBuilderImpl(
-        _options,
-        elementMap,
-        elementMap.elementEnvironment,
-        elementMap.types,
-        elementMap.commonElements,
-        nativeBasicData,
-        nativeDataBuilder,
-        interceptorDataBuilder,
-        backendUsageBuilder,
-        rtiNeedBuilder,
-        allocatorAnalysis,
-        nativeResolutionEnqueuer,
-        noSuchMethodRegistry,
-        annotationsDataBuilder,
-        selectorConstraintsStrategy,
-        classHierarchyBuilder,
-        classQueries);
-  }
-
-  @override
-  WorkItemBuilder createResolutionWorkItemBuilder(
-      NativeBasicData nativeBasicData,
-      NativeDataBuilder nativeDataBuilder,
-      AnnotationsDataBuilder annotationsDataBuilder,
-      ImpactTransformer impactTransformer,
-      Map<Entity, WorldImpact> impactCache,
-      KFieldAnalysis fieldAnalysis) {
-    return new KernelWorkItemBuilder(
-        _compilerTask,
-        elementMap,
-        nativeBasicData,
-        nativeDataBuilder,
-        annotationsDataBuilder,
-        impactTransformer,
-        closureModels,
-        impactCache,
-        fieldAnalysis,
-        _modularStrategy,
-        _irAnnotationData);
-  }
-
-  @override
-  ClassQueries createClassQueries() {
-    return new KernelClassQueries(elementMap);
-  }
-
-  @override
   SourceSpan spanFromSpannable(Spannable spannable, Entity currentElement) {
     return _elementMap.getSourceSpan(spannable, currentElement);
   }
diff --git a/tests/compiler/dart2js/codegen/is_function_test.dart b/tests/compiler/dart2js/codegen/is_function_test.dart
index 9965040..73b2d2f 100644
--- a/tests/compiler/dart2js/codegen/is_function_test.dart
+++ b/tests/compiler/dart2js/codegen/is_function_test.dart
@@ -9,6 +9,7 @@
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/js_emitter/model.dart';
+import 'package:compiler/src/js_model/js_strategy.dart';
 import 'package:expect/expect.dart';
 import '../helpers/memory_compiler.dart';
 
@@ -24,8 +25,10 @@
         memorySourceFiles: {'main.dart': SOURCE}, options: options);
     Expect.isTrue(result.isSuccess);
     Compiler compiler = result.compiler;
-    Program program = compiler.backend.emitterTask.emitter.programForTesting;
-    var name = compiler.backend.namerForTesting.operatorIs(
+    Program program =
+        compiler.backendStrategy.emitterTask.emitter.programForTesting;
+    JsBackendStrategy backendStrategy = compiler.backendStrategy;
+    var name = backendStrategy.namerForTesting.operatorIs(
         compiler.backendClosedWorldForTesting.commonElements.functionClass);
     for (Fragment fragment in program.fragments) {
       for (Library library in fragment.libraries) {
diff --git a/tests/compiler/dart2js/codegen/jsarray_indexof_test.dart b/tests/compiler/dart2js/codegen/jsarray_indexof_test.dart
index d5df20f..f24357b 100644
--- a/tests/compiler/dart2js/codegen/jsarray_indexof_test.dart
+++ b/tests/compiler/dart2js/codegen/jsarray_indexof_test.dart
@@ -12,6 +12,7 @@
 import 'package:compiler/src/elements/names.dart';
 import 'package:compiler/src/world.dart';
 import 'package:compiler/src/js_emitter/model.dart';
+import 'package:compiler/src/js_model/js_strategy.dart';
 import 'package:compiler/src/js/js.dart' as js;
 import 'package:compiler/src/universe/selector.dart';
 import 'package:expect/expect.dart';
@@ -44,14 +45,15 @@
       memorySourceFiles: {'main.dart': source}, options: options);
   Expect.isTrue(result.isSuccess);
   Compiler compiler = result.compiler;
+  JsBackendStrategy backendStrategy = compiler.backendStrategy;
   JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
   MemberEntity jsArrayIndexOf =
       findClassMember(closedWorld, 'JSArray', 'indexOf');
-  ProgramLookup programLookup = new ProgramLookup(result.compiler);
+  ProgramLookup programLookup = new ProgramLookup(backendStrategy);
 
   Selector getLengthSelector = new Selector.getter(const PublicName('length'));
   js.Name getLengthName =
-      compiler.backend.namerForTesting.invocationName(getLengthSelector);
+      backendStrategy.namerForTesting.invocationName(getLengthSelector);
 
   Method method = programLookup.getMethod(jsArrayIndexOf);
   int lengthCount = 0;
diff --git a/tests/compiler/dart2js/codegen/model_test.dart b/tests/compiler/dart2js/codegen/model_test.dart
index 47d0c5c..666ddff 100644
--- a/tests/compiler/dart2js/codegen/model_test.dart
+++ b/tests/compiler/dart2js/codegen/model_test.dart
@@ -84,7 +84,7 @@
       MemberEntity member,
       Compiler compiler,
       this._closureDataLookup)
-      : _programLookup = new ProgramLookup(compiler),
+      : _programLookup = new ProgramLookup(compiler.backendStrategy),
         super(reporter, actualMap);
 
   void registerCalls(Features features, String tag, js.Node node,
diff --git a/tests/compiler/dart2js/codegen/trust_type_annotations2_test.dart b/tests/compiler/dart2js/codegen/trust_type_annotations2_test.dart
index fc46ac1..6cd1e63 100644
--- a/tests/compiler/dart2js/codegen/trust_type_annotations2_test.dart
+++ b/tests/compiler/dart2js/codegen/trust_type_annotations2_test.dart
@@ -29,7 +29,7 @@
     var compiler = result.compiler;
     var element =
         compiler.backendClosedWorldForTesting.elementEnvironment.mainFunction;
-    var code = compiler.backend.getGeneratedCode(element);
+    var code = compiler.backendStrategy.getGeneratedCodeForTesting(element);
     Expect.isTrue(code.contains('+'), code);
   }
 
diff --git a/tests/compiler/dart2js/codegen/type_inference8_test.dart b/tests/compiler/dart2js/codegen/type_inference8_test.dart
index 7cb7040..9150a65 100644
--- a/tests/compiler/dart2js/codegen/type_inference8_test.dart
+++ b/tests/compiler/dart2js/codegen/type_inference8_test.dart
@@ -13,6 +13,7 @@
 import "package:compiler/src/inferrer/abstract_value_domain.dart";
 import "package:compiler/src/inferrer/types.dart";
 import 'package:compiler/src/inferrer/typemasks/masks.dart';
+import 'package:compiler/src/js_model/js_strategy.dart';
 import "package:compiler/src/world.dart";
 import "package:expect/expect.dart";
 import '../helpers/memory_compiler.dart';
@@ -43,6 +44,7 @@
       memorySourceFiles: {'main.dart': TEST1},
       options: [Flags.disableInlining]);
   Compiler compiler = result.compiler;
+  JsBackendStrategy backendStrategy = compiler.backendStrategy;
   GlobalTypeInferenceResults results =
       compiler.globalInference.resultsForTesting;
   JClosedWorld closedWorld = results.closedWorld;
@@ -63,7 +65,7 @@
     AbstractValue barArgMask = results.resultOfParameter(barArg);
     Expect.equals(falseType, barArgMask);
   });
-  String barCode = compiler.backend.getGeneratedCode(bar);
+  String barCode = backendStrategy.getGeneratedCodeForTesting(bar);
   Expect.isTrue(barCode.contains('"bbb"'));
   Expect.isFalse(barCode.contains('"aaa"'));
 }
@@ -93,6 +95,7 @@
       memorySourceFiles: {'main.dart': TEST2},
       options: [Flags.disableInlining]);
   Compiler compiler = result.compiler;
+  JsBackendStrategy backendStrategy = compiler.backendStrategy;
   GlobalTypeInferenceResults results =
       compiler.globalInference.resultsForTesting;
   JClosedWorld closedWorld = results.closedWorld;
@@ -111,7 +114,7 @@
     // The argument to bar should have the same type as the return type of foo
     Expect.identical(commonMasks.boolType, barArgMask);
   });
-  String barCode = compiler.backend.getGeneratedCode(bar);
+  String barCode = backendStrategy.getGeneratedCodeForTesting(bar);
   Expect.isTrue(barCode.contains('"bbb"'));
   // Still must output the print for "aaa"
   Expect.isTrue(barCode.contains('"aaa"'));
diff --git a/tests/compiler/dart2js/codegen/use_checks_test.dart b/tests/compiler/dart2js/codegen/use_checks_test.dart
index d22e26d..6f95ee9 100644
--- a/tests/compiler/dart2js/codegen/use_checks_test.dart
+++ b/tests/compiler/dart2js/codegen/use_checks_test.dart
@@ -31,7 +31,7 @@
     var compiler = result.compiler;
     var element =
         compiler.backendClosedWorldForTesting.elementEnvironment.mainFunction;
-    var code = compiler.backend.getGeneratedCode(element);
+    var code = compiler.backendStrategy.getGeneratedCodeForTesting(element);
     Expect.isTrue(code.contains('+'), code);
   }
 
diff --git a/tests/compiler/dart2js/codegen/value_range3_test.dart b/tests/compiler/dart2js/codegen/value_range3_test.dart
index 62286e7..73491c1 100644
--- a/tests/compiler/dart2js/codegen/value_range3_test.dart
+++ b/tests/compiler/dart2js/codegen/value_range3_test.dart
@@ -28,7 +28,7 @@
     var compiler = result.compiler;
     var element =
         compiler.backendClosedWorldForTesting.elementEnvironment.mainFunction;
-    var code = compiler.backend.getGeneratedCode(element);
+    var code = compiler.backendStrategy.getGeneratedCodeForTesting(element);
     Expect.isFalse(code.contains('ioore'));
   }
 
diff --git a/tests/compiler/dart2js/deferred/constant_emission_test_helper.dart b/tests/compiler/dart2js/deferred/constant_emission_test_helper.dart
index e8a0a7c..c5f20be 100644
--- a/tests/compiler/dart2js/deferred/constant_emission_test_helper.dart
+++ b/tests/compiler/dart2js/deferred/constant_emission_test_helper.dart
@@ -37,7 +37,7 @@
           ? ['${Flags.enableLanguageExperiments}=constant-update-2018']
           : ['${Flags.enableLanguageExperiments}=no-constant-update-2018']);
   Compiler compiler = result.compiler;
-  ProgramLookup lookup = new ProgramLookup(compiler);
+  ProgramLookup lookup = new ProgramLookup(compiler.backendStrategy);
   var closedWorld = compiler.backendClosedWorldForTesting;
   var elementEnvironment = closedWorld.elementEnvironment;
 
diff --git a/tests/compiler/dart2js/deferred/emit_type_checks_test.dart b/tests/compiler/dart2js/deferred/emit_type_checks_test.dart
index 2aea089..b26555b 100644
--- a/tests/compiler/dart2js/deferred/emit_type_checks_test.dart
+++ b/tests/compiler/dart2js/deferred/emit_type_checks_test.dart
@@ -8,7 +8,7 @@
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/compiler_new.dart';
 import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/js_backend/js_backend.dart' show JavaScriptBackend;
+import 'package:compiler/src/js_model/js_strategy.dart';
 import 'package:expect/expect.dart';
 import '../helpers/memory_compiler.dart';
 import '../helpers/output_collector.dart';
@@ -21,8 +21,9 @@
     Compiler compiler = result.compiler;
     String mainOutput = collector.getOutput('', OutputType.js);
     String deferredOutput = collector.getOutput('out_1', OutputType.jsPart);
-    JavaScriptBackend backend = compiler.backend;
-    String isPrefix = backend.namerForTesting.fixedNames.operatorIsPrefix;
+    JsBackendStrategy backendStrategy = compiler.backendStrategy;
+    String isPrefix =
+        backendStrategy.namerForTesting.fixedNames.operatorIsPrefix;
     Expect.isTrue(
         deferredOutput.contains('${isPrefix}A: 1'),
         "Deferred output doesn't contain '${isPrefix}A: 1':\n"
diff --git a/tests/compiler/dart2js/deferred/load_graph_segmentation_test.dart b/tests/compiler/dart2js/deferred/load_graph_segmentation_test.dart
index 45bd24b..4d0589c 100644
--- a/tests/compiler/dart2js/deferred/load_graph_segmentation_test.dart
+++ b/tests/compiler/dart2js/deferred/load_graph_segmentation_test.dart
@@ -28,8 +28,8 @@
     var outputUnitForClass = closedWorld.outputUnitData.outputUnitForClass;
 
     var mainOutputUnit = closedWorld.outputUnitData.mainOutputUnit;
-    var backend = compiler.backend;
-    var classes = backend.emitterTask.neededClasses;
+    var backendStrategy = compiler.backendStrategy;
+    var classes = backendStrategy.emitterTask.neededClasses;
     var inputElement = classes.where((e) => e.name == 'InputElement').single;
     dynamic lib1 = lookupLibrary("memory:lib1.dart");
     var foo1 = env.lookupLibraryMember(lib1, "foo1");
diff --git a/tests/compiler/dart2js/end_to_end/exit_code_test.dart b/tests/compiler/dart2js/end_to_end/exit_code_test.dart
index 3397753..969a3fe 100644
--- a/tests/compiler/dart2js/end_to_end/exit_code_test.dart
+++ b/tests/compiler/dart2js/end_to_end/exit_code_test.dart
@@ -10,6 +10,7 @@
 import 'package:expect/expect.dart';
 
 import 'package:compiler/compiler_new.dart' as api;
+import 'package:compiler/src/backend_strategy.dart';
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/common/codegen.dart';
 import 'package:compiler/src/common/work.dart';
@@ -19,9 +20,9 @@
 import 'package:compiler/src/diagnostics/invariant.dart';
 import 'package:compiler/src/diagnostics/messages.dart';
 import 'package:compiler/src/diagnostics/spannable.dart';
-import 'package:compiler/src/apiimpl.dart' as apiimpl;
+import 'package:compiler/src/apiimpl.dart';
 import 'package:compiler/src/elements/entities.dart';
-import 'package:compiler/src/js_backend/js_backend.dart';
+import 'package:compiler/src/js_model/js_strategy.dart';
 import 'package:compiler/src/null_compiler_output.dart';
 import 'package:compiler/src/serialization/serialization.dart';
 import 'package:compiler/src/options.dart' show CompilerOptions;
@@ -29,7 +30,7 @@
 import 'package:compiler/src/world.dart';
 import 'diagnostic_reporter_helper.dart';
 
-class TestCompiler extends apiimpl.CompilerImpl {
+class TestCompiler extends CompilerImpl {
   final String testMarker;
   final String testType;
   final Function onTest;
@@ -52,8 +53,8 @@
   }
 
   @override
-  JavaScriptBackend createBackend() {
-    return new TestBackend(this);
+  BackendStrategy createBackendStrategy() {
+    return new TestBackendStrategy(this);
   }
 
   @override
@@ -100,15 +101,12 @@
   }
 }
 
-class TestBackend extends JavaScriptBackend {
-  @override
+class TestBackendStrategy extends JsBackendStrategy {
   final TestCompiler compiler;
-  TestBackend(TestCompiler compiler)
+
+  TestBackendStrategy(TestCompiler compiler)
       : this.compiler = compiler,
-        super(compiler,
-            generateSourceMap: compiler.options.generateSourceMap,
-            useMultiSourceInfo: compiler.options.useMultiSourceInfo,
-            useNewSourceInfo: compiler.options.useNewSourceInfo);
+        super(compiler);
 
   @override
   WorldImpact generateCode(
diff --git a/tests/compiler/dart2js/end_to_end/generate_code_with_compile_time_errors_test.dart b/tests/compiler/dart2js/end_to_end/generate_code_with_compile_time_errors_test.dart
index 6ae5ab8..8521dd5 100644
--- a/tests/compiler/dart2js/end_to_end/generate_code_with_compile_time_errors_test.dart
+++ b/tests/compiler/dart2js/end_to_end/generate_code_with_compile_time_errors_test.dart
@@ -10,7 +10,7 @@
 import 'package:expect/expect.dart';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/js_backend/js_backend.dart';
+import 'package:compiler/src/js_model/js_strategy.dart';
 import '../helpers/memory_compiler.dart';
 import '../helpers/output_collector.dart';
 
@@ -45,8 +45,8 @@
   Expect.equals(expectHint, collector.hints.isNotEmpty,
       "Unexpected hints: ${collector.warnings}");
 
-  JavaScriptBackend backend = compiler.backend;
-  bool isCodeGenerated = backend.generatedCode.isNotEmpty;
+  JsBackendStrategy backendStrategy = compiler.backendStrategy;
+  bool isCodeGenerated = backendStrategy.generatedCode.isNotEmpty;
   Expect.equals(
       expectedCodeGenerated,
       isCodeGenerated,
diff --git a/tests/compiler/dart2js/field_analysis/kfield_analysis_test.dart b/tests/compiler/dart2js/field_analysis/kfield_analysis_test.dart
index 72b427c..9fe7c7d 100644
--- a/tests/compiler/dart2js/field_analysis/kfield_analysis_test.dart
+++ b/tests/compiler/dart2js/field_analysis/kfield_analysis_test.dart
@@ -35,9 +35,9 @@
       Map<Id, ActualData<Features>> actualMap,
       {bool verbose: false}) {
     if (member.isField) {
-      KernelFrontEndStrategy frontendStrategy = compiler.frontendStrategy;
+      KernelFrontendStrategy frontendStrategy = compiler.frontendStrategy;
       KFieldAnalysis allocatorAnalysis =
-          compiler.backend.fieldAnalysisForTesting;
+          frontendStrategy.fieldAnalysisForTesting;
       ir.Member node = frontendStrategy.elementMap.getMemberNode(member);
       Features features = new Features();
       if (member.isInstanceMember) {
diff --git a/tests/compiler/dart2js/generic_methods/generic_method_test.dart b/tests/compiler/dart2js/generic_methods/generic_method_test.dart
index 65b2146..76ef8a7 100644
--- a/tests/compiler/dart2js/generic_methods/generic_method_test.dart
+++ b/tests/compiler/dart2js/generic_methods/generic_method_test.dart
@@ -8,6 +8,7 @@
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/js/js.dart' as js;
+import 'package:compiler/src/js_model/js_strategy.dart';
 import 'package:compiler/src/world.dart';
 import 'package:expect/expect.dart';
 import '../helpers/d8_helper.dart';
@@ -178,6 +179,7 @@
       Flags.disableRtiOptimization,
     ], expectedOutput: OUTPUT, printJs: args.contains('-v'));
     Compiler compiler = result.compilationResult.compiler;
+    JsBackendStrategy backendStrategy = compiler.backendStrategy;
     JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
 
@@ -195,7 +197,7 @@
             elementEnvironment.mainLibrary, methodName);
         Expect.isNotNull(method, "Method '$methodName' not found.");
       }
-      js.Fun fun = compiler.backend.generatedCode[method];
+      js.Fun fun = backendStrategy.generatedCode[method];
       Expect.equals(expectedParameterCount, fun.params.length,
           "Unexpected parameter count for $method:\n${js.nodeToString(fun)}");
     }
diff --git a/tests/compiler/dart2js/generic_methods/instantiation_stub_test.dart b/tests/compiler/dart2js/generic_methods/instantiation_stub_test.dart
index 850e1ff..f8c3281 100644
--- a/tests/compiler/dart2js/generic_methods/instantiation_stub_test.dart
+++ b/tests/compiler/dart2js/generic_methods/instantiation_stub_test.dart
@@ -68,7 +68,7 @@
     Expect.isTrue(result.isSuccess);
     Compiler compiler = result.compiler;
     JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
-    ProgramLookup programLookup = new ProgramLookup(compiler);
+    ProgramLookup programLookup = new ProgramLookup(compiler.backendStrategy);
 
     void checkStubs(ClassEntity element, List<String> expectedStubs) {
       Class cls = programLookup.getClass(element);
diff --git a/tests/compiler/dart2js/helpers/compiler_helper.dart b/tests/compiler/dart2js/helpers/compiler_helper.dart
index 9fab31d..a6c1deb 100644
--- a/tests/compiler/dart2js/helpers/compiler_helper.dart
+++ b/tests/compiler/dart2js/helpers/compiler_helper.dart
@@ -6,12 +6,12 @@
 
 import 'dart:async';
 import 'package:compiler/compiler_new.dart';
-import 'package:compiler/src/common_elements.dart';
-import 'package:compiler/src/elements/entities.dart';
-import 'package:compiler/src/js_backend/js_backend.dart' as js;
 import 'package:compiler/src/commandline_options.dart';
-import 'package:compiler/src/world.dart';
+import 'package:compiler/src/common_elements.dart';
 import 'package:compiler/src/compiler.dart' show Compiler;
+import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/js_model/js_strategy.dart';
+import 'package:compiler/src/world.dart';
 import 'package:expect/expect.dart';
 import 'package:front_end/src/fasta/util/link.dart' show Link;
 import 'memory_compiler.dart';
@@ -85,8 +85,8 @@
   LibraryEntity mainLibrary = elementEnvironment.mainLibrary;
   FunctionEntity element =
       elementEnvironment.lookupLibraryMember(mainLibrary, methodName);
-  js.JavaScriptBackend backend = compiler.backend;
-  String generated = backend.getGeneratedCode(element);
+  JsBackendStrategy backendStrategy = compiler.backendStrategy;
+  String generated = backendStrategy.getGeneratedCodeForTesting(element);
   if (check != null) {
     check(generated);
   }
diff --git a/tests/compiler/dart2js/helpers/program_lookup.dart b/tests/compiler/dart2js/helpers/program_lookup.dart
index 4f4d052..54124aa 100644
--- a/tests/compiler/dart2js/helpers/program_lookup.dart
+++ b/tests/compiler/dart2js/helpers/program_lookup.dart
@@ -4,11 +4,11 @@
 
 import 'package:expect/expect.dart';
 import 'package:compiler/src/common_elements.dart';
-import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/deferred_load.dart';
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/js_backend/namer.dart';
 import 'package:compiler/src/js_emitter/model.dart';
+import 'package:compiler/src/js_model/js_strategy.dart';
 import 'package:compiler/src/js/js.dart' as js;
 
 ClassEntity lookupClass(JElementEnvironment elementEnvironment, String name) {
@@ -42,9 +42,9 @@
   final Program program;
   final Namer namer;
 
-  ProgramLookup(Compiler compiler)
-      : this.program = compiler.backend.emitterTask.emitter.programForTesting,
-        this.namer = compiler.backend.namerForTesting;
+  ProgramLookup(JsBackendStrategy backendStrategy)
+      : this.program = backendStrategy.emitterTask.emitter.programForTesting,
+        this.namer = backendStrategy.namerForTesting;
 
   Fragment getFragment(OutputUnit outputUnit) {
     for (Fragment fragment in program.fragments) {
diff --git a/tests/compiler/dart2js/helpers/type_test_helper.dart b/tests/compiler/dart2js/helpers/type_test_helper.dart
index f95e6bb..3e38e24 100644
--- a/tests/compiler/dart2js/helpers/type_test_helper.dart
+++ b/tests/compiler/dart2js/helpers/type_test_helper.dart
@@ -75,7 +75,7 @@
     if (testBackendWorld) {
       return compiler.backendClosedWorldForTesting.dartTypes;
     } else {
-      KernelFrontEndStrategy frontendStrategy = compiler.frontendStrategy;
+      KernelFrontendStrategy frontendStrategy = compiler.frontendStrategy;
       return frontendStrategy.elementMap.types;
     }
   }
diff --git a/tests/compiler/dart2js/impact/impact_test.dart b/tests/compiler/dart2js/impact/impact_test.dart
index 38bfe17..ec60875 100644
--- a/tests/compiler/dart2js/impact/impact_test.dart
+++ b/tests/compiler/dart2js/impact/impact_test.dart
@@ -54,7 +54,7 @@
   void computeMemberData(Compiler compiler, MemberEntity member,
       Map<Id, ActualData<Features>> actualMap,
       {bool verbose: false}) {
-    KernelFrontEndStrategy frontendStrategy = compiler.frontendStrategy;
+    KernelFrontendStrategy frontendStrategy = compiler.frontendStrategy;
     WorldImpact impact = compiler.impactCache[member];
     ir.Member node = frontendStrategy.elementMap.getMemberNode(member);
     Features features = new Features();
diff --git a/tests/compiler/dart2js/inlining/inlining_test.dart b/tests/compiler/dart2js/inlining/inlining_test.dart
index 8e73762..bb4dcd2 100644
--- a/tests/compiler/dart2js/inlining/inlining_test.dart
+++ b/tests/compiler/dart2js/inlining/inlining_test.dart
@@ -9,8 +9,8 @@
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
 import 'package:compiler/src/elements/entities.dart';
-import 'package:compiler/src/js_backend/backend.dart';
 import 'package:compiler/src/js_model/element_map.dart';
+import 'package:compiler/src/js_model/js_strategy.dart';
 import 'package:compiler/src/js_model/js_world.dart';
 import 'package:compiler/src/ssa/builder_kernel.dart';
 import 'package:compiler/src/universe/world_impact.dart';
@@ -40,7 +40,7 @@
     JsToElementMap elementMap = closedWorld.elementMap;
     MemberDefinition definition = elementMap.getMemberDefinition(member);
     new InliningIrComputer(compiler.reporter, actualMap, elementMap, member,
-            compiler.backend, closedWorld.closureDataLookup)
+            compiler.backendStrategy, closedWorld.closureDataLookup)
         .run(definition.node);
   }
 
@@ -50,7 +50,7 @@
 
 /// AST visitor for computing inference data for a member.
 class InliningIrComputer extends IrDataExtractor<String> {
-  final JavaScriptBackend backend;
+  final JsBackendStrategy _backendStrategy;
   final JsToElementMap _elementMap;
   final ClosureData _closureDataLookup;
   final InlineDataCache _inlineDataCache;
@@ -60,7 +60,7 @@
       Map<Id, ActualData<String>> actualMap,
       this._elementMap,
       MemberEntity member,
-      this.backend,
+      this._backendStrategy,
       this._closureDataLookup)
       : this._inlineDataCache = new InlineDataCache(enableUserAssertions: true),
         super(reporter, actualMap);
@@ -72,7 +72,7 @@
         constructorBody = getConstructorBody(member);
       }
       List<String> inlinedIn = <String>[];
-      backend.codegenImpactsForTesting
+      _backendStrategy.codegenImpactsForTesting
           .forEach((MemberEntity user, WorldImpact impact) {
         for (StaticUse use in impact.staticUses) {
           if (use.kind == StaticUseKind.INLINING) {
diff --git a/tests/compiler/dart2js/js/js_constant_test.dart b/tests/compiler/dart2js/js/js_constant_test.dart
index 0bc4b44..6d0613e 100644
--- a/tests/compiler/dart2js/js/js_constant_test.dart
+++ b/tests/compiler/dart2js/js/js_constant_test.dart
@@ -32,8 +32,8 @@
       var elementEnvironment = closedWorld.elementEnvironment;
 
       MemberEntity element = elementEnvironment.mainFunction;
-      var backend = compiler.backend;
-      String generated = backend.getGeneratedCode(element);
+      String generated =
+          compiler.backendStrategy.getGeneratedCodeForTesting(element);
       checkerForAbsentPresent(test)(generated);
     }
 
diff --git a/tests/compiler/dart2js/js/js_spec_optimization_test.dart b/tests/compiler/dart2js/js/js_spec_optimization_test.dart
index 3ea2c61..004030c 100644
--- a/tests/compiler/dart2js/js/js_spec_optimization_test.dart
+++ b/tests/compiler/dart2js/js/js_spec_optimization_test.dart
@@ -99,8 +99,8 @@
       var elementEnvironment = closedWorld.elementEnvironment;
 
       MemberEntity element = elementEnvironment.mainFunction;
-      var backend = compiler.backend;
-      String generated = backend.getGeneratedCode(element);
+      String generated =
+          compiler.backendStrategy.getGeneratedCodeForTesting(element);
       checker(generated);
     }
 
diff --git a/tests/compiler/dart2js/member_usage/member_usage_test.dart b/tests/compiler/dart2js/member_usage/member_usage_test.dart
index 4e5a2c0..1a5dd51 100644
--- a/tests/compiler/dart2js/member_usage/member_usage_test.dart
+++ b/tests/compiler/dart2js/member_usage/member_usage_test.dart
@@ -79,7 +79,7 @@
   void computeMemberData(Compiler compiler, MemberEntity member,
       Map<Id, ActualData<Features>> actualMap,
       {bool verbose: false}) {
-    KernelFrontEndStrategy frontendStrategy = compiler.frontendStrategy;
+    KernelFrontendStrategy frontendStrategy = compiler.frontendStrategy;
     ResolutionWorldBuilderImpl resolutionWorldBuilder =
         compiler.resolutionWorldBuilder;
     ir.Member node = frontendStrategy.elementMap.getMemberNode(member);
diff --git a/tests/compiler/dart2js/model/cfe_annotations_test.dart b/tests/compiler/dart2js/model/cfe_annotations_test.dart
index d5b0e0f..e01dba6 100644
--- a/tests/compiler/dart2js/model/cfe_annotations_test.dart
+++ b/tests/compiler/dart2js/model/cfe_annotations_test.dart
@@ -197,7 +197,7 @@
             ..addAll(options));
       Expect.isTrue(result.isSuccess);
       Compiler compiler = result.compiler;
-      KernelFrontEndStrategy frontendStrategy = compiler.frontendStrategy;
+      KernelFrontendStrategy frontendStrategy = compiler.frontendStrategy;
       KernelToElementMapImpl elementMap = frontendStrategy.elementMap;
       ir.Component component = elementMap.env.mainComponent;
       IrAnnotationData annotationData =
diff --git a/tests/compiler/dart2js/model/cfe_constant_evaluation_test.dart b/tests/compiler/dart2js/model/cfe_constant_evaluation_test.dart
index e75c916..1ed2501 100644
--- a/tests/compiler/dart2js/model/cfe_constant_evaluation_test.dart
+++ b/tests/compiler/dart2js/model/cfe_constant_evaluation_test.dart
@@ -536,7 +536,7 @@
       '${Flags.enableLanguageExperiments}=constant-update-2018',
     ]);
     Compiler compiler = result.compiler;
-    KernelFrontEndStrategy frontEndStrategy = compiler.frontendStrategy;
+    KernelFrontendStrategy frontEndStrategy = compiler.frontendStrategy;
     KernelToElementMapImpl elementMap = frontEndStrategy.elementMap;
     KElementEnvironment elementEnvironment =
         compiler.frontendStrategy.elementEnvironment;
diff --git a/tests/compiler/dart2js/model/no_such_method_enabled_test.dart b/tests/compiler/dart2js/model/no_such_method_enabled_test.dart
index 58d85b9..08a9bf9 100644
--- a/tests/compiler/dart2js/model/no_such_method_enabled_test.dart
+++ b/tests/compiler/dart2js/model/no_such_method_enabled_test.dart
@@ -261,7 +261,8 @@
 checkTest(Compiler compiler, NoSuchMethodTest test) {
   ElementEnvironment frontendEnvironment =
       compiler.frontendStrategy.elementEnvironment;
-  NoSuchMethodRegistryImpl registry = compiler.backend.noSuchMethodRegistry;
+  NoSuchMethodRegistryImpl registry =
+      compiler.frontendStrategy.noSuchMethodRegistry;
   NoSuchMethodResolver resolver = registry.internalResolverForTesting;
   FunctionEntity ObjectNSM = frontendEnvironment.lookupClassMember(
       compiler.frontendStrategy.commonElements.objectClass, 'noSuchMethod');
diff --git a/tests/compiler/dart2js/model/supermixin_test.dart b/tests/compiler/dart2js/model/supermixin_test.dart
index 3533fe7..fab668d 100644
--- a/tests/compiler/dart2js/model/supermixin_test.dart
+++ b/tests/compiler/dart2js/model/supermixin_test.dart
@@ -61,7 +61,7 @@
     MemberEntity method2 = lookupMember(elementEnvironment, 'Class.method2');
     Expect.equals(mixin, method2.enclosingClass);
 
-    ProgramLookup lookup = new ProgramLookup(result.compiler);
+    ProgramLookup lookup = new ProgramLookup(result.compiler.backendStrategy);
     ClassData data = lookup.getClassData(superClass);
     Expect.isNotNull(data.getMethod(method1));
     Expect.isNull(data.getMethod(method2));
diff --git a/tests/compiler/dart2js/optimization/optimization_test.dart b/tests/compiler/dart2js/optimization/optimization_test.dart
index 1f56a1a..a1bc198 100644
--- a/tests/compiler/dart2js/optimization/optimization_test.dart
+++ b/tests/compiler/dart2js/optimization/optimization_test.dart
@@ -10,8 +10,8 @@
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
 import 'package:compiler/src/elements/entities.dart';
-import 'package:compiler/src/js_backend/backend.dart';
 import 'package:compiler/src/js_model/element_map.dart';
+import 'package:compiler/src/js_model/js_strategy.dart';
 import 'package:compiler/src/js_model/js_world.dart';
 import 'package:compiler/src/ssa/logging.dart';
 import 'package:compiler/src/ssa/ssa.dart';
@@ -142,7 +142,7 @@
     JsToElementMap elementMap = closedWorld.elementMap;
     MemberDefinition definition = elementMap.getMemberDefinition(member);
     new OptimizationIrComputer(compiler.reporter, actualMap, elementMap, member,
-            compiler.backend, closedWorld.closureDataLookup)
+            compiler.backendStrategy, closedWorld.closureDataLookup)
         .run(definition.node);
   }
 
@@ -153,7 +153,7 @@
 
 /// AST visitor for computing inference data for a member.
 class OptimizationIrComputer extends IrDataExtractor<OptimizationTestLog> {
-  final JavaScriptBackend backend;
+  final JsBackendStrategy _backendStrategy;
   final JsToElementMap _elementMap;
   final ClosureData _closureDataLookup;
 
@@ -162,12 +162,12 @@
       Map<Id, ActualData<OptimizationTestLog>> actualMap,
       this._elementMap,
       MemberEntity member,
-      this.backend,
+      this._backendStrategy,
       this._closureDataLookup)
       : super(reporter, actualMap);
 
   OptimizationTestLog getLog(MemberEntity member) {
-    SsaFunctionCompiler functionCompiler = backend.functionCompiler;
+    SsaFunctionCompiler functionCompiler = _backendStrategy.functionCompiler;
     return functionCompiler.optimizer.loggersForTesting[member];
   }
 
diff --git a/tests/compiler/dart2js/rti/backend_type_helper_test.dart b/tests/compiler/dart2js/rti/backend_type_helper_test.dart
index 8cf6de4..95dc812 100644
--- a/tests/compiler/dart2js/rti/backend_type_helper_test.dart
+++ b/tests/compiler/dart2js/rti/backend_type_helper_test.dart
@@ -20,7 +20,7 @@
     Expect.isTrue(result.isSuccess);
     Compiler compiler = result.compiler;
     JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
-    ProgramLookup programLookup = new ProgramLookup(compiler);
+    ProgramLookup programLookup = new ProgramLookup(compiler.backendStrategy);
 
     List<ClassEntity> found = <ClassEntity>[];
     for (ClassEntity element
diff --git a/tests/compiler/dart2js/rti/disable_rti_test.dart b/tests/compiler/dart2js/rti/disable_rti_test.dart
index c4749ad..9e7b1aa 100644
--- a/tests/compiler/dart2js/rti/disable_rti_test.dart
+++ b/tests/compiler/dart2js/rti/disable_rti_test.dart
@@ -79,7 +79,7 @@
     JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     JElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
     RuntimeTypesNeed rtiNeed = closedWorld.rtiNeed;
-    ProgramLookup programLookup = new ProgramLookup(compiler);
+    ProgramLookup programLookup = new ProgramLookup(compiler.backendStrategy);
 
     List<ClassEntity> closures = <ClassEntity>[];
 
diff --git a/tests/compiler/dart2js/rti/factory_call_test.dart b/tests/compiler/dart2js/rti/factory_call_test.dart
index 392c989..f92fd7e 100644
--- a/tests/compiler/dart2js/rti/factory_call_test.dart
+++ b/tests/compiler/dart2js/rti/factory_call_test.dart
@@ -8,6 +8,7 @@
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/js_backend/runtime_types.dart';
 import 'package:compiler/src/js_emitter/model.dart';
+import 'package:compiler/src/js_model/js_strategy.dart';
 import 'package:compiler/src/js/js.dart' as js;
 import 'package:compiler/src/world.dart';
 import 'package:expect/expect.dart';
@@ -40,13 +41,14 @@
         await runCompiler(memorySourceFiles: {'main.dart': code});
     Expect.isTrue(result.isSuccess);
     Compiler compiler = result.compiler;
+    JsBackendStrategy backendStrategy = compiler.backendStrategy;
     JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     RuntimeTypesNeed rtiNeed = closedWorld.rtiNeed;
     ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
-    ProgramLookup programLookup = new ProgramLookup(compiler);
+    ProgramLookup programLookup = new ProgramLookup(backendStrategy);
 
     js.Name getName(String name) {
-      return compiler.backend.namerForTesting
+      return backendStrategy.namerForTesting
           .globalPropertyNameForMember(lookupMember(elementEnvironment, name));
     }
 
diff --git a/tests/compiler/dart2js/rti/instance_call_test.dart b/tests/compiler/dart2js/rti/instance_call_test.dart
index cdbbf3e..41c88ea 100644
--- a/tests/compiler/dart2js/rti/instance_call_test.dart
+++ b/tests/compiler/dart2js/rti/instance_call_test.dart
@@ -10,6 +10,7 @@
 import 'package:compiler/src/elements/names.dart';
 import 'package:compiler/src/js_backend/runtime_types.dart';
 import 'package:compiler/src/js_emitter/model.dart';
+import 'package:compiler/src/js_model/js_strategy.dart';
 import 'package:compiler/src/js/js.dart' as js;
 import 'package:compiler/src/world.dart';
 import 'package:compiler/src/universe/call_structure.dart';
@@ -101,13 +102,14 @@
         options: [Flags.omitImplicitChecks]);
     Expect.isTrue(result.isSuccess);
     Compiler compiler = result.compiler;
+    JsBackendStrategy backendStrategy = compiler.backendStrategy;
     JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     RuntimeTypesNeed rtiNeed = closedWorld.rtiNeed;
     ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
-    ProgramLookup programLookup = new ProgramLookup(compiler);
+    ProgramLookup programLookup = new ProgramLookup(backendStrategy);
 
     js.Name getName(String name, int typeArguments) {
-      return compiler.backend.namerForTesting.invocationName(new Selector.call(
+      return backendStrategy.namerForTesting.invocationName(new Selector.call(
           new PublicName(name),
           new CallStructure(1, const <String>[], typeArguments)));
     }
diff --git a/tests/compiler/dart2js/rti/rti_emission_test.dart b/tests/compiler/dart2js/rti/rti_emission_test.dart
index 0e580ca..fd96ed8 100644
--- a/tests/compiler/dart2js/rti/rti_emission_test.dart
+++ b/tests/compiler/dart2js/rti/rti_emission_test.dart
@@ -13,6 +13,7 @@
 import 'package:compiler/src/js_backend/runtime_types.dart';
 import 'package:compiler/src/js_emitter/model.dart';
 import 'package:compiler/src/js_model/element_map.dart';
+import 'package:compiler/src/js_model/js_strategy.dart';
 import 'package:compiler/src/js_model/js_world.dart';
 import 'package:compiler/src/util/features.dart';
 import 'package:kernel/ast.dart' as ir;
@@ -43,11 +44,13 @@
   Compiler get compiler;
   ProgramLookup lookup;
 
+  JsBackendStrategy get backendStrategy => compiler.backendStrategy;
+
   RuntimeTypesImpl get checksBuilder =>
-      compiler.backend.rtiChecksBuilderForTesting;
+      backendStrategy.rtiChecksBuilderForTesting;
 
   String getClassValue(ClassEntity element) {
-    lookup ??= new ProgramLookup(compiler);
+    lookup ??= new ProgramLookup(backendStrategy);
     Class cls = lookup.getClass(element);
     Features features = new Features();
     if (cls != null) {
diff --git a/tests/compiler/dart2js/rti/rti_need_test_helper.dart b/tests/compiler/dart2js/rti/rti_need_test_helper.dart
index 4c54942..d5c4e49 100644
--- a/tests/compiler/dart2js/rti/rti_need_test_helper.dart
+++ b/tests/compiler/dart2js/rti/rti_need_test_helper.dart
@@ -57,10 +57,11 @@
 abstract class ComputeValueMixin {
   Compiler get compiler;
 
+  KernelFrontendStrategy get frontendStrategy => compiler.frontendStrategy;
   ResolutionWorldBuilder get resolutionWorldBuilder =>
       compiler.resolutionWorldBuilder;
   RuntimeTypesNeedBuilderImpl get rtiNeedBuilder =>
-      compiler.frontendStrategy.runtimeTypesNeedBuilderForTesting;
+      frontendStrategy.runtimeTypesNeedBuilderForTesting;
   RuntimeTypesNeedImpl get rtiNeed =>
       compiler.backendClosedWorldForTesting.rtiNeed;
   ClassEntity getFrontendClass(ClassEntity cls);
@@ -308,7 +309,7 @@
     JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     ir.Node node = closedWorld.elementMap.getMemberDefinition(member).node;
     if (node is ir.FunctionDeclaration || node is ir.FunctionExpression) {
-      KernelFrontEndStrategy frontendStrategy = compiler.frontendStrategy;
+      KernelFrontendStrategy frontendStrategy = compiler.frontendStrategy;
       KernelToElementMap frontendElementMap = frontendStrategy.elementMap;
       return frontendElementMap.getLocalFunction(node);
     }
diff --git a/tests/compiler/dart2js/rti/type_representation_test.dart b/tests/compiler/dart2js/rti/type_representation_test.dart
index 0729ef9..e1c2e07 100644
--- a/tests/compiler/dart2js/rti/type_representation_test.dart
+++ b/tests/compiler/dart2js/rti/type_representation_test.dart
@@ -12,9 +12,9 @@
 import 'package:compiler/src/elements/types.dart';
 import 'package:compiler/src/js/js.dart';
 import 'package:compiler/src/elements/entities.dart';
-import 'package:compiler/src/js_backend/backend.dart' show JavaScriptBackend;
 import 'package:compiler/src/js_backend/runtime_types.dart'
     show RuntimeTypeTags, TypeRepresentationGenerator;
+import 'package:compiler/src/js_model/js_strategy.dart';
 import 'package:compiler/src/world.dart';
 import 'package:expect/expect.dart';
 import '../helpers/element_lookup.dart';
@@ -65,7 +65,7 @@
       await runCompiler(memorySourceFiles: {'main.dart': source});
   Expect.isTrue(result.isSuccess);
   Compiler compiler = result.compiler;
-  JavaScriptBackend backend = compiler.backend;
+  JsBackendStrategy backendStrategy = compiler.backendStrategy;
 
   RuntimeTypeTags rtiTags = const RuntimeTypeTags();
   TypeRepresentationGenerator typeRepresentation =
@@ -86,7 +86,7 @@
       [String expectedTypedefRepresentation]) {
     bool encodeTypedefName = false;
     Expression expression = typeRepresentation.getTypeRepresentation(
-        backend.emitterTask.emitter,
+        backendStrategy.emitterTask.emitter,
         type,
         onVariable,
         (x) => encodeTypedefName);
@@ -94,7 +94,7 @@
 
     encodeTypedefName = true;
     expression = typeRepresentation.getTypeRepresentation(
-        backend.emitterTask.emitter,
+        backendStrategy.emitterTask.emitter,
         type,
         onVariable,
         (x) => encodeTypedefName);
@@ -106,7 +106,7 @@
 
   String getJsName(Entity cls) {
     Expression name = typeRepresentation.getJavaScriptClassName(
-        cls, backend.emitterTask.emitter);
+        cls, backendStrategy.emitterTask.emitter);
     return stringify(name);
   }
 
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
index 9e4273d..058750c 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
@@ -17,7 +17,7 @@
 import 'package:compiler/src/js/js.dart' as js;
 import 'package:compiler/src/js/js_debug.dart';
 import 'package:compiler/src/js/js_source_mapping.dart';
-import 'package:compiler/src/js_backend/js_backend.dart';
+import 'package:compiler/src/js_model/js_strategy.dart';
 import 'package:compiler/src/source_file_provider.dart';
 import '../../helpers/memory_compiler.dart';
 import '../../helpers/output_collector.dart';
@@ -342,29 +342,29 @@
         options: ['--out=$targetUri', '--source-map=$sourceMapFileUri']
           ..addAll(options),
         beforeRun: (compiler) {
-          JavaScriptBackend backend = compiler.backend;
+          JsBackendStrategy backendStrategy = compiler.backendStrategy;
           dynamic handler = compiler.handler;
           SourceFileProvider sourceFileProvider = handler.provider;
           sourceFileManager =
               new ProviderSourceFileManager(sourceFileProvider, outputProvider);
           RecordingSourceInformationStrategy strategy =
               new RecordingSourceInformationStrategy(
-                  backend.sourceInformationStrategy);
-          backend.sourceInformationStrategy = strategy;
+                  backendStrategy.sourceInformationStrategy);
+          backendStrategy.sourceInformationStrategy = strategy;
         });
     if (!result.isSuccess) {
       throw "Compilation failed.";
     }
 
     api.CompilerImpl compiler = result.compiler;
-    JavaScriptBackend backend = compiler.backend;
+    JsBackendStrategy backendStrategy = compiler.backendStrategy;
     RecordingSourceInformationStrategy strategy =
-        backend.sourceInformationStrategy;
+        backendStrategy.sourceInformationStrategy;
     SourceMapInfo mainSourceMapInfo;
     Map<MemberEntity, SourceMapInfo> elementSourceMapInfos =
         <MemberEntity, SourceMapInfo>{};
     if (perElement) {
-      backend.generatedCode.forEach((_element, js.Expression node) {
+      backendStrategy.generatedCode.forEach((_element, js.Expression node) {
         MemberEntity element = _element;
         RecordedSourceInformationProcess subProcess =
             strategy.subProcessForNode(node);
diff --git a/tests/compiler/dart2js/static_type/static_type_test.dart b/tests/compiler/dart2js/static_type/static_type_test.dart
index 369d14c..e530f19 100644
--- a/tests/compiler/dart2js/static_type/static_type_test.dart
+++ b/tests/compiler/dart2js/static_type/static_type_test.dart
@@ -48,7 +48,7 @@
   void computeMemberData(Compiler compiler, MemberEntity member,
       Map<Id, ActualData<String>> actualMap,
       {bool verbose: false}) {
-    KernelFrontEndStrategy frontendStrategy = compiler.frontendStrategy;
+    KernelFrontendStrategy frontendStrategy = compiler.frontendStrategy;
     KernelToElementMapImpl elementMap = frontendStrategy.elementMap;
     StaticTypeCache staticTypeCache = elementMap.getCachedStaticTypes(member);
     ir.Member node = elementMap.getMemberNode(member);
diff --git a/tests/compiler/dart2js/static_type/type_promotion_test.dart b/tests/compiler/dart2js/static_type/type_promotion_test.dart
index ca9dfd4..1367dd3 100644
--- a/tests/compiler/dart2js/static_type/type_promotion_test.dart
+++ b/tests/compiler/dart2js/static_type/type_promotion_test.dart
@@ -46,7 +46,7 @@
   void computeMemberData(Compiler compiler, MemberEntity member,
       Map<Id, ActualData<String>> actualMap,
       {bool verbose: false}) {
-    KernelFrontEndStrategy frontendStrategy = compiler.frontendStrategy;
+    KernelFrontendStrategy frontendStrategy = compiler.frontendStrategy;
     KernelToElementMapImpl elementMap = frontendStrategy.elementMap;
     Map<ir.Expression, TypeMap> typeMaps =
         elementMap.getTypeMapsForTesting(member);