Version 1.20.0-dev.9.0

Merge commit '0f0bd64ca42c2eab15c4a07a8aaffde130646fff' into dev
diff --git a/pkg/compiler/lib/src/common/backend_api.dart b/pkg/compiler/lib/src/common/backend_api.dart
index 258a38f..b93ddee 100644
--- a/pkg/compiler/lib/src/common/backend_api.dart
+++ b/pkg/compiler/lib/src/common/backend_api.dart
@@ -64,6 +64,9 @@
     return const SourceInformationStrategy();
   }
 
+  /// Common classes used by the backend.
+  BackendClasses get backendClasses;
+
   /// Interface for serialization of backend specific data.
   BackendSerialization get serialization => const BackendSerialization();
 
@@ -182,34 +185,6 @@
 
   void registerConstSymbol(String name) {}
 
-  bool isNullImplementation(ClassElement cls) {
-    return cls == compiler.coreClasses.nullClass;
-  }
-
-  ClassElement get intImplementation => compiler.coreClasses.intClass;
-  ClassElement get doubleImplementation => compiler.coreClasses.doubleClass;
-  ClassElement get numImplementation => compiler.coreClasses.numClass;
-  ClassElement get stringImplementation => compiler.coreClasses.stringClass;
-  ClassElement get listImplementation => compiler.coreClasses.listClass;
-  ClassElement get growableListImplementation => compiler.coreClasses.listClass;
-  ClassElement get fixedListImplementation => compiler.coreClasses.listClass;
-  ClassElement get constListImplementation => compiler.coreClasses.listClass;
-  ClassElement get mapImplementation => compiler.coreClasses.mapClass;
-  ClassElement get constMapImplementation => compiler.coreClasses.mapClass;
-  ClassElement get functionImplementation => compiler.coreClasses.functionClass;
-  ClassElement get typeImplementation => compiler.coreClasses.typeClass;
-  ClassElement get boolImplementation => compiler.coreClasses.boolClass;
-  ClassElement get nullImplementation => compiler.coreClasses.nullClass;
-  ClassElement get uint32Implementation => compiler.coreClasses.intClass;
-  ClassElement get uint31Implementation => compiler.coreClasses.intClass;
-  ClassElement get positiveIntImplementation => compiler.coreClasses.intClass;
-  ClassElement get syncStarIterableImplementation =>
-      compiler.coreClasses.iterableClass;
-  ClassElement get asyncFutureImplementation =>
-      compiler.coreClasses.futureClass;
-  ClassElement get asyncStarStreamImplementation =>
-      compiler.coreClasses.streamClass;
-
   ClassElement defaultSuperclass(ClassElement element) {
     return compiler.coreClasses.objectClass;
   }
@@ -411,3 +386,27 @@
   SerializerPlugin get serializer => const SerializerPlugin();
   DeserializerPlugin get deserializer => const DeserializerPlugin();
 }
+
+/// Interface providing access to core classes used by the backend.
+abstract class BackendClasses {
+  ClassElement get intImplementation;
+  ClassElement get doubleImplementation;
+  ClassElement get numImplementation;
+  ClassElement get stringImplementation;
+  ClassElement get listImplementation;
+  ClassElement get growableListImplementation;
+  ClassElement get fixedListImplementation;
+  ClassElement get constListImplementation;
+  ClassElement get mapImplementation;
+  ClassElement get constMapImplementation;
+  ClassElement get functionImplementation;
+  ClassElement get typeImplementation;
+  ClassElement get boolImplementation;
+  ClassElement get nullImplementation;
+  ClassElement get uint32Implementation;
+  ClassElement get uint31Implementation;
+  ClassElement get positiveIntImplementation;
+  ClassElement get syncStarIterableImplementation;
+  ClassElement get asyncFutureImplementation;
+  ClassElement get asyncStarStreamImplementation;
+}
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 5667a4e..789cbe4 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -850,12 +850,16 @@
           mainMethod.computeType(resolution);
           if (mainMethod.functionSignature.parameterCount != 0) {
             // The first argument could be a list of strings.
-            backend.listImplementation.ensureResolved(resolution);
+            backend.backendClasses.listImplementation
+                .ensureResolved(resolution);
             backend.registerInstantiatedType(
-                backend.listImplementation.rawType, world, globalDependencies);
-            backend.stringImplementation.ensureResolved(resolution);
+                backend.backendClasses.listImplementation.rawType,
+                world,
+                globalDependencies);
+            backend.backendClasses.stringImplementation
+                .ensureResolved(resolution);
             backend.registerInstantiatedType(
-                backend.stringImplementation.rawType,
+                backend.backendClasses.stringImplementation.rawType,
                 world,
                 globalDependencies);
 
diff --git a/pkg/compiler/lib/src/constant_system_dart.dart b/pkg/compiler/lib/src/constant_system_dart.dart
index c42ca74..0f9a0d6 100644
--- a/pkg/compiler/lib/src/constant_system_dart.dart
+++ b/pkg/compiler/lib/src/constant_system_dart.dart
@@ -446,8 +446,10 @@
     // TODO(johnniwinther): Change the `Type` type to
     // `compiler.coreTypes.typeType` and check the backend specific value in
     // [checkConstMapKeysDontOverrideEquals] in 'members.dart'.
-    return new TypeConstantValue(type,
-        compiler.backend.typeImplementation.computeType(compiler.resolution));
+    return new TypeConstantValue(
+        type,
+        compiler.backend.backendClasses.typeImplementation
+            .computeType(compiler.resolution));
   }
 
   @override
diff --git a/pkg/compiler/lib/src/inferrer/node_tracer.dart b/pkg/compiler/lib/src/inferrer/node_tracer.dart
index cc890bf..058d36d 100644
--- a/pkg/compiler/lib/src/inferrer/node_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/node_tracer.dart
@@ -333,7 +333,8 @@
    */
   bool isParameterOfListAddingMethod(Element element) {
     if (!element.isRegularParameter) return false;
-    if (element.enclosingClass != compiler.backend.listImplementation) {
+    if (element.enclosingClass !=
+        compiler.backend.backendClasses.listImplementation) {
       return false;
     }
     Element method = element.enclosingElement;
@@ -349,7 +350,8 @@
    */
   bool isParameterOfMapAddingMethod(Element element) {
     if (!element.isRegularParameter) return false;
-    if (element.enclosingClass != compiler.backend.mapImplementation) {
+    if (element.enclosingClass !=
+        compiler.backend.backendClasses.mapImplementation) {
       return false;
     }
     Element method = element.enclosingElement;
diff --git a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
index effe4fb..85e5dbd 100644
--- a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
@@ -1352,7 +1352,7 @@
     // In erroneous code the number of arguments in the selector might not
     // match the function element.
     // TODO(polux): return nonNullEmpty and check it doesn't break anything
-    if (!selector.applies(target, compiler.backend) ||
+    if (!selector.applies(target) ||
         (mask != null &&
             !mask.canHit(target, selector, compiler.closedWorld))) {
       return types.dynamicType;
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index 98e12be..ddca262 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -24,7 +24,7 @@
         ValueTypeMask;
 import '../universe/selector.dart' show Selector;
 import '../util/util.dart' show ImmutableEmptySet, Setlet;
-import '../world.dart' show ClassWorld;
+import '../world.dart' show ClosedWorld;
 import 'debug.dart' as debug;
 import 'inferrer_visitor.dart' show ArgumentsTypes;
 import 'type_graph_inferrer.dart'
@@ -867,26 +867,27 @@
    */
   TypeInformation handleIntrisifiedSelector(
       Selector selector, TypeMask mask, TypeGraphInferrerEngine inferrer) {
-    ClassWorld classWorld = inferrer.closedWorld;
-    if (!classWorld.backend.intImplementation.isResolved) return null;
+    ClosedWorld closedWorld = inferrer.closedWorld;
+    if (!closedWorld.backendClasses.intImplementation.isResolved) return null;
     if (mask == null) return null;
-    if (!mask.containsOnlyInt(classWorld)) {
+    if (!mask.containsOnlyInt(closedWorld)) {
       return null;
     }
     if (!selector.isCall && !selector.isOperator) return null;
     if (!arguments.named.isEmpty) return null;
     if (arguments.positional.length > 1) return null;
 
-    ClassElement uint31Implementation = classWorld.backend.uint31Implementation;
-    bool isInt(info) => info.type.containsOnlyInt(classWorld);
+    ClassElement uint31Implementation =
+        closedWorld.backendClasses.uint31Implementation;
+    bool isInt(info) => info.type.containsOnlyInt(closedWorld);
     bool isEmpty(info) => info.type.isEmpty;
     bool isUInt31(info) {
-      return info.type.satisfies(uint31Implementation, classWorld);
+      return info.type.satisfies(uint31Implementation, closedWorld);
     }
 
     bool isPositiveInt(info) {
-      return info.type
-          .satisfies(classWorld.backend.positiveIntImplementation, classWorld);
+      return info.type.satisfies(
+          closedWorld.backendClasses.positiveIntImplementation, closedWorld);
     }
 
     TypeInformation tryLater() => inferrer.types.nonNullEmptyType;
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index acc0edc1..0899d1b 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -11,7 +11,12 @@
 import '../closure.dart';
 import '../common.dart';
 import '../common/backend_api.dart'
-    show Backend, ImpactTransformer, ForeignResolver, NativeRegistry;
+    show
+        Backend,
+        BackendClasses,
+        ImpactTransformer,
+        ForeignResolver,
+        NativeRegistry;
 import '../common/codegen.dart' show CodegenImpact, CodegenWorkItem;
 import '../common/names.dart' show Identifiers, Selectors, Uris;
 import '../common/registry.dart' show Registry;
@@ -591,6 +596,7 @@
 
   final BackendHelpers helpers;
   final BackendImpacts impacts;
+  BackendClasses backendClasses;
 
   final JSFrontendAccess frontend;
 
@@ -630,6 +636,7 @@
     functionCompiler =
         new SsaFunctionCompiler(this, sourceInformationStrategy, useKernel);
     serialization = new JavaScriptBackendSerialization(this);
+    backendClasses = new JavaScriptBackendClasses(helpers);
   }
 
   ConstantSystem get constantSystem => constants.constantSystem;
@@ -925,7 +932,7 @@
     if (elements == null) return false;
     if (elements.isEmpty) return false;
     return elements.any((element) {
-      return selector.applies(element, this) &&
+      return selector.applies(element) &&
           (mask == null ||
               mask.canHit(element, selector, compiler.closedWorld));
     });
@@ -1121,7 +1128,7 @@
         registerBackendUse(helpers.createRuntimeType);
       }
       impactBuilder.registerTypeUse(
-          new TypeUse.instantiation(typeImplementation.rawType));
+          new TypeUse.instantiation(backendClasses.typeImplementation.rawType));
     }
     lookupMapAnalysis.registerConstantKey(constant);
   }
@@ -1139,7 +1146,7 @@
             helpers.setRuntimeTypeInfo,
             null));
       }
-      if (type.element == typeImplementation) {
+      if (type.element == backendClasses.typeImplementation) {
         // If we use a type literal in a constant, the compile time
         // constant emitter will generate a call to the createRuntimeType
         // helper so we register a use of that.
@@ -1897,30 +1904,6 @@
     return compiler.closedWorld.hasOnlySubclasses(classElement);
   }
 
-  bool isNullImplementation(ClassElement cls) {
-    return cls == helpers.jsNullClass;
-  }
-
-  ClassElement get intImplementation => helpers.jsIntClass;
-  ClassElement get uint32Implementation => helpers.jsUInt32Class;
-  ClassElement get uint31Implementation => helpers.jsUInt31Class;
-  ClassElement get positiveIntImplementation => helpers.jsPositiveIntClass;
-  ClassElement get doubleImplementation => helpers.jsDoubleClass;
-  ClassElement get numImplementation => helpers.jsNumberClass;
-  ClassElement get stringImplementation => helpers.jsStringClass;
-  ClassElement get listImplementation => helpers.jsArrayClass;
-  ClassElement get constListImplementation => helpers.jsUnmodifiableArrayClass;
-  ClassElement get fixedListImplementation => helpers.jsFixedArrayClass;
-  ClassElement get growableListImplementation => helpers.jsExtendableArrayClass;
-  ClassElement get mapImplementation => helpers.mapLiteralClass;
-  ClassElement get constMapImplementation => helpers.constMapLiteralClass;
-  ClassElement get typeImplementation => helpers.typeLiteralClass;
-  ClassElement get boolImplementation => helpers.jsBoolClass;
-  ClassElement get nullImplementation => helpers.jsNullClass;
-  ClassElement get syncStarIterableImplementation => helpers.syncStarIterable;
-  ClassElement get asyncFutureImplementation => helpers.futureImplementation;
-  ClassElement get asyncStarStreamImplementation => helpers.controllerStream;
-
   void registerStaticUse(Element element, Enqueuer enqueuer) {
     if (element == helpers.disableTreeShakingMarker) {
       isTreeShakingDisabled = true;
@@ -3257,3 +3240,30 @@
     }
   }
 }
+
+class JavaScriptBackendClasses implements BackendClasses {
+  final BackendHelpers helpers;
+
+  JavaScriptBackendClasses(this.helpers);
+
+  ClassElement get intImplementation => helpers.jsIntClass;
+  ClassElement get uint32Implementation => helpers.jsUInt32Class;
+  ClassElement get uint31Implementation => helpers.jsUInt31Class;
+  ClassElement get positiveIntImplementation => helpers.jsPositiveIntClass;
+  ClassElement get doubleImplementation => helpers.jsDoubleClass;
+  ClassElement get numImplementation => helpers.jsNumberClass;
+  ClassElement get stringImplementation => helpers.jsStringClass;
+  ClassElement get listImplementation => helpers.jsArrayClass;
+  ClassElement get constListImplementation => helpers.jsUnmodifiableArrayClass;
+  ClassElement get fixedListImplementation => helpers.jsFixedArrayClass;
+  ClassElement get growableListImplementation => helpers.jsExtendableArrayClass;
+  ClassElement get mapImplementation => helpers.mapLiteralClass;
+  ClassElement get constMapImplementation => helpers.constMapLiteralClass;
+  ClassElement get typeImplementation => helpers.typeLiteralClass;
+  ClassElement get boolImplementation => helpers.jsBoolClass;
+  ClassElement get nullImplementation => helpers.jsNullClass;
+  ClassElement get syncStarIterableImplementation => helpers.syncStarIterable;
+  ClassElement get asyncFutureImplementation => helpers.futureImplementation;
+  ClassElement get asyncStarStreamImplementation => helpers.controllerStream;
+  ClassElement get functionImplementation => helpers.coreClasses.functionClass;
+}
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index e933ae5..7726ed0 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -446,7 +446,7 @@
   BackendImpact get typeLiteral {
     if (_typeLiteral == null) {
       _typeLiteral = new BackendImpact(
-          instantiatedClasses: [backend.typeImplementation],
+          instantiatedClasses: [backend.backendClasses.typeImplementation],
           staticUses: [helpers.createRuntimeType]);
     }
     return _typeLiteral;
diff --git a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
index e717466..7f86482 100644
--- a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
@@ -265,8 +265,10 @@
 
   @override
   ConstantValue createType(Compiler compiler, DartType type) {
-    return new TypeConstantValue(type,
-        compiler.backend.typeImplementation.computeType(compiler.resolution));
+    return new TypeConstantValue(
+        type,
+        compiler.backend.backendClasses.typeImplementation
+            .computeType(compiler.resolution));
   }
 
   // Integer checks report true for -0.0, INFINITY, and -INFINITY.  At
diff --git a/pkg/compiler/lib/src/js_backend/enqueuer.dart b/pkg/compiler/lib/src/js_backend/enqueuer.dart
index 8ceca0b..e4b3027 100644
--- a/pkg/compiler/lib/src/js_backend/enqueuer.dart
+++ b/pkg/compiler/lib/src/js_backend/enqueuer.dart
@@ -88,7 +88,7 @@
 
   Registry get mirrorDependencies => _compiler.mirrorDependencies;
 
-  ClassWorld get _world => _compiler.closedWorld;
+  ClosedWorld get _world => _compiler.closedWorld;
 
   bool get queueIsEmpty => queue.isEmpty;
 
diff --git a/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart b/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
index 2045c6c..d729e56 100644
--- a/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
@@ -277,7 +277,7 @@
         // type_lookup_map/generic_type_test
         // TODO(sigmund): can we get rid of this?
         backend.computeImpactForInstantiatedConstantType(
-            backend.typeImplementation.rawType, impactBuilder);
+            backend.backendClasses.typeImplementation.rawType, impactBuilder);
         _addGenerics(arg);
       }
     }
diff --git a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
index 1e0b6a3..96d991a 100644
--- a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
@@ -92,7 +92,7 @@
     Set<Selector> generatedSelectors = new Set<Selector>();
     for (Selector selector in selectors.keys) {
       if (generatedSelectors.contains(selector)) continue;
-      if (!selector.appliesUnnamed(member, backend)) continue;
+      if (!selector.appliesUnnamed(member)) continue;
       if (selectors[selector].applies(member, selector, compiler.closedWorld)) {
         generatedSelectors.add(selector);
 
diff --git a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
index 621d781..c63527d 100644
--- a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
@@ -248,7 +248,7 @@
           new Selector.call(member.memberName, selector.callStructure);
       renamedCallSelectors.add(renamedSelector);
 
-      if (!renamedSelector.appliesUnnamed(member, compiler.backend)) {
+      if (!renamedSelector.appliesUnnamed(member)) {
         continue;
       }
 
@@ -266,7 +266,7 @@
     // call-selectors (and they are in the renamedCallSelectors set.
     for (Selector selector in selectors.keys) {
       if (renamedCallSelectors.contains(selector)) continue;
-      if (!selector.appliesUnnamed(member, backend)) continue;
+      if (!selector.appliesUnnamed(member)) continue;
       if (!selectors[selector]
           .applies(member, selector, compiler.closedWorld)) {
         continue;
diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart
index 1ab06fe..8e2d48b 100644
--- a/pkg/compiler/lib/src/native/enqueue.dart
+++ b/pkg/compiler/lib/src/native/enqueue.dart
@@ -483,8 +483,8 @@
           backend.registerInstantiatedType(type, world, registry);
         } else if (type == coreTypes.boolType) {
           backend.registerInstantiatedType(type, world, registry);
-        } else if (compiler.types
-            .isSubtype(type, backend.listImplementation.rawType)) {
+        } else if (compiler.types.isSubtype(
+            type, backend.backendClasses.listImplementation.rawType)) {
           backend.registerInstantiatedType(type, world, registry);
         }
         // TODO(johnniwinther): Improve spec string precision to handle type
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index 5cca521..a39f87c 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -332,7 +332,7 @@
    */
   List<HInstruction> completeDynamicSendArgumentsList(Selector selector,
       FunctionElement function, List<HInstruction> providedArguments) {
-    assert(selector.applies(function, backend));
+    assert(selector.applies(function));
     FunctionSignature signature = function.functionSignature;
     List<HInstruction> compiledArguments = new List<HInstruction>(
         signature.parameterCount + 1); // Plus one for receiver.
@@ -426,7 +426,7 @@
               element.isGenerativeConstructorBody,
           message: "Missing selector for inlining of $element."));
       if (selector != null) {
-        if (!selector.applies(function, backend)) return false;
+        if (!selector.applies(function)) return false;
         if (mask != null &&
             !mask.canHit(function, selector, compiler.closedWorld)) {
           return false;
@@ -3201,7 +3201,7 @@
     // TODO(5347): Try to avoid the need for calling [implementation] before
     // calling [makeStaticArgumentList].
     Selector selector = elements.getSelector(node);
-    assert(invariant(node, selector.applies(function.implementation, backend),
+    assert(invariant(node, selector.applies(function.implementation),
         message: "$selector does not apply to ${function.implementation}"));
     List<HInstruction> inputs = makeStaticArgumentList(
         selector.callStructure, node.arguments, function.implementation);
@@ -4453,8 +4453,7 @@
     List<HInstruction> setterInputs = <HInstruction>[];
     void generateSuperSendSet() {
       Selector setterSelector = elements.getSelector(node);
-      if (Elements.isUnresolved(element) ||
-          !setterSelector.applies(element, compiler.backend)) {
+      if (Elements.isUnresolved(element) || !setterSelector.applies(element)) {
         generateSuperNoSuchMethodSend(node, setterSelector, setterInputs);
         pop();
       } else {
diff --git a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
index eafe01b..1716c7f 100644
--- a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
+++ b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
@@ -11,7 +11,7 @@
 import '../js_backend/js_backend.dart';
 import '../types/types.dart';
 import '../universe/selector.dart' show Selector;
-import '../world.dart' show ClassWorld;
+import '../world.dart' show ClosedWorld;
 import 'nodes.dart';
 import 'optimize.dart';
 
@@ -49,7 +49,7 @@
 
   BackendHelpers get helpers => backend.helpers;
 
-  ClassWorld get classWorld => compiler.closedWorld;
+  ClosedWorld get closedWorld => compiler.closedWorld;
 
   void visitGraph(HGraph graph) {
     this.graph = graph;
@@ -109,8 +109,8 @@
 
     // All intercepted classes extend `Interceptor`, so if the receiver can't be
     // a class extending `Interceptor` then it can be called directly.
-    return new TypeMask.nonNullSubclass(helpers.jsInterceptorClass, classWorld)
-        .isDisjoint(receiver.instructionType, classWorld);
+    return new TypeMask.nonNullSubclass(helpers.jsInterceptorClass, closedWorld)
+        .isDisjoint(receiver.instructionType, closedWorld);
   }
 
   HInstruction tryComputeConstantInterceptor(
@@ -145,17 +145,17 @@
       if (type.isNull) {
         return helpers.jsNullClass;
       }
-    } else if (type.containsOnlyInt(classWorld)) {
+    } else if (type.containsOnlyInt(closedWorld)) {
       return helpers.jsIntClass;
-    } else if (type.containsOnlyDouble(classWorld)) {
+    } else if (type.containsOnlyDouble(closedWorld)) {
       return helpers.jsDoubleClass;
-    } else if (type.containsOnlyBool(classWorld)) {
+    } else if (type.containsOnlyBool(closedWorld)) {
       return helpers.jsBoolClass;
-    } else if (type.containsOnlyString(classWorld)) {
+    } else if (type.containsOnlyString(closedWorld)) {
       return helpers.jsStringClass;
-    } else if (type.satisfies(helpers.jsArrayClass, classWorld)) {
+    } else if (type.satisfies(helpers.jsArrayClass, closedWorld)) {
       return helpers.jsArrayClass;
-    } else if (type.containsOnlyNum(classWorld) &&
+    } else if (type.containsOnlyNum(closedWorld) &&
         !interceptedClasses.contains(helpers.jsIntClass) &&
         !interceptedClasses.contains(helpers.jsDoubleClass)) {
       // If the method being intercepted is not defined in [int] or [double] we
@@ -174,7 +174,7 @@
       // for a subclass or call methods defined on a subclass.  Provided the
       // code is completely insensitive to the specific instance subclasses, we
       // can use the non-leaf class directly.
-      ClassElement element = type.singleClass(classWorld);
+      ClassElement element = type.singleClass(closedWorld);
       if (element != null && backend.isNative(element)) {
         return element;
       }
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 627e7195..9aa2d98 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -378,7 +378,7 @@
     ClosedWorld world = compiler.closedWorld;
 
     bool applies(Element element) {
-      return selector.applies(element, backend) &&
+      return selector.applies(element) &&
           (mask == null || mask.canHit(element, selector, world));
     }
 
@@ -427,7 +427,7 @@
         return result;
       }
     } else if (selector.isGetter) {
-      if (selector.applies(helpers.jsIndexableLength, backend)) {
+      if (selector.applies(helpers.jsIndexableLength)) {
         HInstruction optimized = tryOptimizeLengthInterceptedGetter(node);
         if (optimized != null) return optimized;
       }
diff --git a/pkg/compiler/lib/src/ssa/types.dart b/pkg/compiler/lib/src/ssa/types.dart
index edffc3a..18ed76c 100644
--- a/pkg/compiler/lib/src/ssa/types.dart
+++ b/pkg/compiler/lib/src/ssa/types.dart
@@ -9,7 +9,7 @@
 import '../tree/tree.dart' as ast;
 import '../types/types.dart';
 import '../universe/selector.dart' show Selector;
-import '../world.dart' show ClassWorld;
+import '../world.dart' show ClosedWorld;
 
 class TypeMaskFactory {
   static TypeMask inferredReturnTypeForElement(
@@ -34,7 +34,7 @@
     var typesReturned = nativeBehavior.typesReturned;
     if (typesReturned.isEmpty) return compiler.commonMasks.dynamicType;
 
-    ClassWorld world = compiler.closedWorld;
+    ClosedWorld world = compiler.closedWorld;
     CommonMasks commonMasks = compiler.commonMasks;
     CoreClasses coreClasses = compiler.coreClasses;
 
diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart
index e9b4c98..46beb9e 100644
--- a/pkg/compiler/lib/src/ssa/types_propagation.dart
+++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
@@ -7,7 +7,7 @@
 import '../js_backend/js_backend.dart';
 import '../types/types.dart';
 import '../universe/selector.dart' show Selector;
-import '../world.dart' show ClassWorld;
+import '../world.dart' show ClosedWorld;
 import 'nodes.dart';
 import 'optimize.dart';
 
@@ -18,13 +18,13 @@
       new Map<HInstruction, Function>();
 
   final Compiler compiler;
-  final ClassWorld classWorld;
+  final ClosedWorld closedWorld;
   JavaScriptBackend get backend => compiler.backend;
   String get name => 'type propagator';
 
   SsaTypePropagator(Compiler compiler)
       : this.compiler = compiler,
-        this.classWorld = compiler.closedWorld;
+        this.closedWorld = compiler.closedWorld;
 
   TypeMask computeType(HInstruction instruction) {
     return instruction.accept(this);
@@ -160,7 +160,7 @@
     TypeMask candidateType = backend.emptyType;
     for (int i = 0, length = phi.inputs.length; i < length; i++) {
       TypeMask inputType = phi.inputs[i].instructionType;
-      candidateType = candidateType.union(inputType, classWorld);
+      candidateType = candidateType.union(inputType, closedWorld);
     }
     return candidateType;
   }
@@ -173,25 +173,25 @@
       // We must make sure a type conversion for receiver or argument check
       // does not try to do an int check, because an int check is not enough.
       // We only do an int check if the input is integer or null.
-      if (checkedType.containsOnlyNum(classWorld) &&
-          !checkedType.containsOnlyDouble(classWorld) &&
+      if (checkedType.containsOnlyNum(closedWorld) &&
+          !checkedType.containsOnlyDouble(closedWorld) &&
           input.isIntegerOrNull(compiler)) {
         instruction.checkedType = backend.intType;
-      } else if (checkedType.containsOnlyInt(classWorld) &&
+      } else if (checkedType.containsOnlyInt(closedWorld) &&
           !input.isIntegerOrNull(compiler)) {
         instruction.checkedType = backend.numType;
       }
     }
 
-    TypeMask outputType = checkedType.intersection(inputType, classWorld);
+    TypeMask outputType = checkedType.intersection(inputType, closedWorld);
     if (outputType.isEmpty) {
       // Intersection of double and integer conflicts (is empty), but JS numbers
       // can be both int and double at the same time.  For example, the input
       // can be a literal double '8.0' that is marked as an integer (because 'is
       // int' will return 'true').  What we really need to do is make the
       // overlap between int and double values explicit in the TypeMask system.
-      if (inputType.containsOnlyInt(classWorld) &&
-          checkedType.containsOnlyDouble(classWorld)) {
+      if (inputType.containsOnlyInt(closedWorld) &&
+          checkedType.containsOnlyDouble(closedWorld)) {
         if (inputType.isNullable && checkedType.isNullable) {
           outputType = backend.doubleType.nullable();
         } else {
@@ -221,7 +221,7 @@
     HInstruction input = instruction.checkedInput;
     TypeMask inputType = input.instructionType;
     TypeMask outputType =
-        instruction.knownType.intersection(inputType, classWorld);
+        instruction.knownType.intersection(inputType, closedWorld);
     if (inputType != outputType) {
       input.replaceAllUsersDominatedBy(instruction.next, instruction);
     }
@@ -244,7 +244,7 @@
     // In some cases, we want the receiver to be an integer,
     // but that does not mean we will get a NoSuchMethodError
     // if it's not: the receiver could be a double.
-    if (type.containsOnlyInt(classWorld)) {
+    if (type.containsOnlyInt(closedWorld)) {
       // If the instruction's type is integer or null, the codegen
       // will emit a null check, which is enough to know if it will
       // hit a noSuchMethod.
@@ -274,12 +274,12 @@
         Element target = targets.first;
         ClassElement cls = target.enclosingClass;
         TypeMask type =
-            new TypeMask.nonNullSubclass(cls.declaration, classWorld);
+            new TypeMask.nonNullSubclass(cls.declaration, closedWorld);
         // TODO(ngeoffray): We currently only optimize on primitive
         // types.
-        if (!type.satisfies(backend.helpers.jsIndexableClass, classWorld) &&
-            !type.containsOnlyNum(classWorld) &&
-            !type.containsOnlyBool(classWorld)) {
+        if (!type.satisfies(backend.helpers.jsIndexableClass, closedWorld) &&
+            !type.containsOnlyNum(closedWorld) &&
+            !type.containsOnlyBool(closedWorld)) {
           return false;
         }
         if (!isCheckEnoughForNsmOrAe(receiver, type)) return false;
@@ -373,7 +373,7 @@
       TypeMask computeNewType() {
         newType = compiler.closedWorld.allFunctions
             .receiverType(instruction.selector, instruction.mask);
-        newType = newType.intersection(receiverType, classWorld);
+        newType = newType.intersection(receiverType, closedWorld);
         return newType;
       }
 
diff --git a/pkg/compiler/lib/src/types/container_type_mask.dart b/pkg/compiler/lib/src/types/container_type_mask.dart
index acde3b2..908996b 100644
--- a/pkg/compiler/lib/src/types/container_type_mask.dart
+++ b/pkg/compiler/lib/src/types/container_type_mask.dart
@@ -50,13 +50,13 @@
         length == other.length;
   }
 
-  TypeMask intersection(TypeMask other, ClassWorld classWorld) {
-    TypeMask forwardIntersection = forwardTo.intersection(other, classWorld);
+  TypeMask intersection(TypeMask other, ClosedWorld closedWorld) {
+    TypeMask forwardIntersection = forwardTo.intersection(other, closedWorld);
     if (forwardIntersection.isEmptyOrNull) return forwardIntersection;
     return forwardIntersection.isNullable ? nullable() : nonNullable();
   }
 
-  TypeMask union(other, ClassWorld classWorld) {
+  TypeMask union(other, ClosedWorld closedWorld) {
     if (this == other) {
       return this;
     } else if (equalsDisregardNull(other)) {
@@ -67,9 +67,9 @@
         elementType != null &&
         other.elementType != null) {
       TypeMask newElementType =
-          elementType.union(other.elementType, classWorld);
+          elementType.union(other.elementType, closedWorld);
       int newLength = (length == other.length) ? length : null;
-      TypeMask newForwardTo = forwardTo.union(other.forwardTo, classWorld);
+      TypeMask newForwardTo = forwardTo.union(other.forwardTo, closedWorld);
       return new ContainerTypeMask(
           newForwardTo,
           allocationNode == other.allocationNode ? allocationNode : null,
@@ -79,7 +79,7 @@
           newElementType,
           newLength);
     } else {
-      return forwardTo.union(other, classWorld);
+      return forwardTo.union(other, closedWorld);
     }
   }
 
diff --git a/pkg/compiler/lib/src/types/dictionary_type_mask.dart b/pkg/compiler/lib/src/types/dictionary_type_mask.dart
index c308041..fc7a8a5 100644
--- a/pkg/compiler/lib/src/types/dictionary_type_mask.dart
+++ b/pkg/compiler/lib/src/types/dictionary_type_mask.dart
@@ -47,13 +47,13 @@
             (k) => typeMap.containsKey(k) && typeMap[k] == other.typeMap[k]);
   }
 
-  TypeMask intersection(TypeMask other, ClassWorld classWorld) {
-    TypeMask forwardIntersection = forwardTo.intersection(other, classWorld);
+  TypeMask intersection(TypeMask other, ClosedWorld closedWorld) {
+    TypeMask forwardIntersection = forwardTo.intersection(other, closedWorld);
     if (forwardIntersection.isEmptyOrNull) return forwardIntersection;
     return forwardIntersection.isNullable ? nullable() : nonNullable();
   }
 
-  TypeMask union(other, ClassWorld classWorld) {
+  TypeMask union(other, ClosedWorld closedWorld) {
     if (this == other) {
       return this;
     } else if (equalsDisregardNull(other)) {
@@ -61,9 +61,9 @@
     } else if (other.isEmptyOrNull) {
       return other.isNullable ? this.nullable() : this;
     } else if (other.isDictionary) {
-      TypeMask newForwardTo = forwardTo.union(other.forwardTo, classWorld);
-      TypeMask newKeyType = keyType.union(other.keyType, classWorld);
-      TypeMask newValueType = valueType.union(other.valueType, classWorld);
+      TypeMask newForwardTo = forwardTo.union(other.forwardTo, closedWorld);
+      TypeMask newKeyType = keyType.union(other.keyType, closedWorld);
+      TypeMask newValueType = valueType.union(other.valueType, closedWorld);
       Map<String, TypeMask> mappings = <String, TypeMask>{};
       typeMap.forEach((k, v) {
         if (!other.typeMap.containsKey(k)) {
@@ -72,7 +72,7 @@
       });
       other.typeMap.forEach((k, v) {
         if (typeMap.containsKey(k)) {
-          mappings[k] = v.union(typeMap[k], classWorld);
+          mappings[k] = v.union(typeMap[k], closedWorld);
         } else {
           mappings[k] = v.nullable();
         }
@@ -82,13 +82,13 @@
     } else if (other.isMap &&
         (other.keyType != null) &&
         (other.valueType != null)) {
-      TypeMask newForwardTo = forwardTo.union(other.forwardTo, classWorld);
-      TypeMask newKeyType = keyType.union(other.keyType, classWorld);
-      TypeMask newValueType = valueType.union(other.valueType, classWorld);
+      TypeMask newForwardTo = forwardTo.union(other.forwardTo, closedWorld);
+      TypeMask newKeyType = keyType.union(other.keyType, closedWorld);
+      TypeMask newValueType = valueType.union(other.valueType, closedWorld);
       return new MapTypeMask(
           newForwardTo, null, null, newKeyType, newValueType);
     } else {
-      return forwardTo.union(other, classWorld);
+      return forwardTo.union(other, closedWorld);
     }
   }
 
diff --git a/pkg/compiler/lib/src/types/flat_type_mask.dart b/pkg/compiler/lib/src/types/flat_type_mask.dart
index 1055af2..5a3ef8e 100644
--- a/pkg/compiler/lib/src/types/flat_type_mask.dart
+++ b/pkg/compiler/lib/src/types/flat_type_mask.dart
@@ -120,25 +120,25 @@
     // The general optimization is to realize there is only one class that
     // implements [base] and [base] is not instantiated. We however do
     // not track correctly the list of truly instantiated classes.
-    Backend backend = closedWorld.backend;
+    BackendClasses backendClasses = closedWorld.backendClasses;
     if (containsOnlyString(closedWorld)) {
       return cls == closedWorld.coreClasses.stringClass ||
-          cls == backend.stringImplementation;
+          cls == backendClasses.stringImplementation;
     }
     if (containsOnlyBool(closedWorld)) {
       return cls == closedWorld.coreClasses.boolClass ||
-          cls == backend.boolImplementation;
+          cls == backendClasses.boolImplementation;
     }
     if (containsOnlyInt(closedWorld)) {
       return cls == closedWorld.coreClasses.intClass ||
-          cls == backend.intImplementation ||
-          cls == backend.positiveIntImplementation ||
-          cls == backend.uint32Implementation ||
-          cls == backend.uint31Implementation;
+          cls == backendClasses.intImplementation ||
+          cls == backendClasses.positiveIntImplementation ||
+          cls == backendClasses.uint32Implementation ||
+          cls == backendClasses.uint31Implementation;
     }
     if (containsOnlyDouble(closedWorld)) {
       return cls == closedWorld.coreClasses.doubleClass ||
-          cls == backend.doubleImplementation;
+          cls == backendClasses.doubleImplementation;
     }
     return false;
   }
@@ -180,38 +180,38 @@
   }
 
   bool containsOnlyInt(ClosedWorld closedWorld) {
-    Backend backend = closedWorld.backend;
+    BackendClasses backendClasses = closedWorld.backendClasses;
     return base == closedWorld.coreClasses.intClass ||
-        base == backend.intImplementation ||
-        base == backend.positiveIntImplementation ||
-        base == backend.uint31Implementation ||
-        base == backend.uint32Implementation;
+        base == backendClasses.intImplementation ||
+        base == backendClasses.positiveIntImplementation ||
+        base == backendClasses.uint31Implementation ||
+        base == backendClasses.uint32Implementation;
   }
 
   bool containsOnlyDouble(ClosedWorld closedWorld) {
-    Backend backend = closedWorld.backend;
+    BackendClasses backendClasses = closedWorld.backendClasses;
     return base == closedWorld.coreClasses.doubleClass ||
-        base == backend.doubleImplementation;
+        base == backendClasses.doubleImplementation;
   }
 
   bool containsOnlyNum(ClosedWorld closedWorld) {
-    Backend backend = closedWorld.backend;
+    BackendClasses backendClasses = closedWorld.backendClasses;
     return containsOnlyInt(closedWorld) ||
         containsOnlyDouble(closedWorld) ||
         base == closedWorld.coreClasses.numClass ||
-        base == backend.numImplementation;
+        base == backendClasses.numImplementation;
   }
 
   bool containsOnlyBool(ClosedWorld closedWorld) {
-    Backend backend = closedWorld.backend;
+    BackendClasses backendClasses = closedWorld.backendClasses;
     return base == closedWorld.coreClasses.boolClass ||
-        base == backend.boolImplementation;
+        base == backendClasses.boolImplementation;
   }
 
   bool containsOnlyString(ClosedWorld closedWorld) {
-    Backend backend = closedWorld.backend;
+    BackendClasses backendClasses = closedWorld.backendClasses;
     return base == closedWorld.coreClasses.stringClass ||
-        base == backend.stringImplementation;
+        base == backendClasses.stringImplementation;
   }
 
   bool containsOnly(ClassElement cls) {
@@ -543,11 +543,11 @@
    * privacy is taken into account.
    */
   bool canHit(Element element, Selector selector, ClosedWorld closedWorld) {
-    Backend backend = closedWorld.backend;
+    BackendClasses backendClasses = closedWorld.backendClasses;
     assert(element.name == selector.name);
     if (isEmpty) return false;
     if (isNull) {
-      return hasElementIn(backend.nullImplementation, selector, element);
+      return hasElementIn(backendClasses.nullImplementation, selector, element);
     }
 
     // TODO(kasperl): Can't we just avoid creating typed selectors
@@ -560,18 +560,16 @@
     }
 
     ClassElement other = element.enclosingClass;
-    if (other == backend.nullImplementation) {
+    if (other == backendClasses.nullImplementation) {
       return isNullable;
     } else if (isExact) {
       return hasElementIn(self, selector, element);
     } else if (isSubclass) {
-      assert(closedWorld.isClosed);
       return hasElementIn(self, selector, element) ||
           other.isSubclassOf(self) ||
           closedWorld.hasAnySubclassThatMixes(self, other);
     } else {
       assert(isSubtype);
-      assert(closedWorld.isClosed);
       bool result = hasElementIn(self, selector, element) ||
           other.implementsInterface(self) ||
           closedWorld.hasAnySubclassThatImplements(other, base) ||
@@ -602,7 +600,7 @@
       ClassElement enclosingClass = element.enclosingClass;
       return hasConcreteMatch(enclosingClass.superclass, selector, world);
     }
-    return selector.appliesUntyped(element, world.backend);
+    return selector.appliesUntyped(element);
   }
 
   bool needsNoSuchMethodHandling(Selector selector, ClosedWorld closedWorld) {
diff --git a/pkg/compiler/lib/src/types/forwarding_type_mask.dart b/pkg/compiler/lib/src/types/forwarding_type_mask.dart
index d886e99..cdf4f16 100644
--- a/pkg/compiler/lib/src/types/forwarding_type_mask.dart
+++ b/pkg/compiler/lib/src/types/forwarding_type_mask.dart
@@ -26,55 +26,55 @@
   bool get isValue => false;
   bool get isForwarding => true;
 
-  bool isInMask(TypeMask other, ClassWorld classWorld) {
-    return forwardTo.isInMask(other, classWorld);
+  bool isInMask(TypeMask other, ClosedWorld closedWorld) {
+    return forwardTo.isInMask(other, closedWorld);
   }
 
-  bool containsMask(TypeMask other, ClassWorld classWorld) {
-    return forwardTo.containsMask(other, classWorld);
+  bool containsMask(TypeMask other, ClosedWorld closedWorld) {
+    return forwardTo.containsMask(other, closedWorld);
   }
 
-  bool containsOnlyInt(ClassWorld classWorld) {
-    return forwardTo.containsOnlyInt(classWorld);
+  bool containsOnlyInt(ClosedWorld closedWorld) {
+    return forwardTo.containsOnlyInt(closedWorld);
   }
 
-  bool containsOnlyDouble(ClassWorld classWorld) {
-    return forwardTo.containsOnlyDouble(classWorld);
+  bool containsOnlyDouble(ClosedWorld closedWorld) {
+    return forwardTo.containsOnlyDouble(closedWorld);
   }
 
-  bool containsOnlyNum(ClassWorld classWorld) {
-    return forwardTo.containsOnlyNum(classWorld);
+  bool containsOnlyNum(ClosedWorld closedWorld) {
+    return forwardTo.containsOnlyNum(closedWorld);
   }
 
-  bool containsOnlyBool(ClassWorld classWorld) {
-    return forwardTo.containsOnlyBool(classWorld);
+  bool containsOnlyBool(ClosedWorld closedWorld) {
+    return forwardTo.containsOnlyBool(closedWorld);
   }
 
-  bool containsOnlyString(ClassWorld classWorld) {
-    return forwardTo.containsOnlyString(classWorld);
+  bool containsOnlyString(ClosedWorld closedWorld) {
+    return forwardTo.containsOnlyString(closedWorld);
   }
 
   bool containsOnly(ClassElement element) {
     return forwardTo.containsOnly(element);
   }
 
-  bool satisfies(ClassElement cls, ClassWorld classWorld) {
-    return forwardTo.satisfies(cls, classWorld);
+  bool satisfies(ClassElement cls, ClosedWorld closedWorld) {
+    return forwardTo.satisfies(cls, closedWorld);
   }
 
-  bool contains(ClassElement type, ClassWorld classWorld) {
-    return forwardTo.contains(type, classWorld);
+  bool contains(ClassElement type, ClosedWorld closedWorld) {
+    return forwardTo.contains(type, closedWorld);
   }
 
-  bool containsAll(ClassWorld classWorld) {
-    return forwardTo.containsAll(classWorld);
+  bool containsAll(ClosedWorld closedWorld) {
+    return forwardTo.containsAll(closedWorld);
   }
 
-  ClassElement singleClass(ClassWorld classWorld) {
-    return forwardTo.singleClass(classWorld);
+  ClassElement singleClass(ClosedWorld closedWorld) {
+    return forwardTo.singleClass(closedWorld);
   }
 
-  TypeMask union(other, ClassWorld classWorld) {
+  TypeMask union(other, ClosedWorld closedWorld) {
     if (this == other) {
       return this;
     } else if (equalsDisregardNull(other)) {
@@ -82,23 +82,23 @@
     } else if (other.isEmptyOrNull) {
       return other.isNullable ? this.nullable() : this;
     }
-    return forwardTo.union(other, classWorld);
+    return forwardTo.union(other, closedWorld);
   }
 
-  bool isDisjoint(TypeMask other, ClassWorld classWorld) {
-    return forwardTo.isDisjoint(other, classWorld);
+  bool isDisjoint(TypeMask other, ClosedWorld closedWorld) {
+    return forwardTo.isDisjoint(other, closedWorld);
   }
 
-  TypeMask intersection(TypeMask other, ClassWorld classWorld) {
-    return forwardTo.intersection(other, classWorld);
+  TypeMask intersection(TypeMask other, ClosedWorld closedWorld) {
+    return forwardTo.intersection(other, closedWorld);
   }
 
-  bool needsNoSuchMethodHandling(Selector selector, ClassWorld classWorld) {
-    return forwardTo.needsNoSuchMethodHandling(selector, classWorld);
+  bool needsNoSuchMethodHandling(Selector selector, ClosedWorld closedWorld) {
+    return forwardTo.needsNoSuchMethodHandling(selector, closedWorld);
   }
 
-  bool canHit(Element element, Selector selector, ClassWorld classWorld) {
-    return forwardTo.canHit(element, selector, classWorld);
+  bool canHit(Element element, Selector selector, ClosedWorld closedWorld) {
+    return forwardTo.canHit(element, selector, closedWorld);
   }
 
   Element locateSingleElement(Selector selector, Compiler compiler) {
diff --git a/pkg/compiler/lib/src/types/map_type_mask.dart b/pkg/compiler/lib/src/types/map_type_mask.dart
index 57f3c46..230db17 100644
--- a/pkg/compiler/lib/src/types/map_type_mask.dart
+++ b/pkg/compiler/lib/src/types/map_type_mask.dart
@@ -53,13 +53,13 @@
         valueType == other.valueType;
   }
 
-  TypeMask intersection(TypeMask other, ClassWorld classWorld) {
-    TypeMask forwardIntersection = forwardTo.intersection(other, classWorld);
+  TypeMask intersection(TypeMask other, ClosedWorld closedWorld) {
+    TypeMask forwardIntersection = forwardTo.intersection(other, closedWorld);
     if (forwardIntersection.isEmptyOrNull) return forwardIntersection;
     return forwardIntersection.isNullable ? nullable() : nonNullable();
   }
 
-  TypeMask union(other, ClassWorld classWorld) {
+  TypeMask union(other, ClosedWorld closedWorld) {
     if (this == other) {
       return this;
     } else if (equalsDisregardNull(other)) {
@@ -71,20 +71,21 @@
         other.keyType != null &&
         valueType != null &&
         other.valueType != null) {
-      TypeMask newKeyType = keyType.union(other.keyType, classWorld);
-      TypeMask newValueType = valueType.union(other.valueType, classWorld);
-      TypeMask newForwardTo = forwardTo.union(other.forwardTo, classWorld);
+      TypeMask newKeyType = keyType.union(other.keyType, closedWorld);
+      TypeMask newValueType = valueType.union(other.valueType, closedWorld);
+      TypeMask newForwardTo = forwardTo.union(other.forwardTo, closedWorld);
       return new MapTypeMask(
           newForwardTo, null, null, newKeyType, newValueType);
     } else if (other.isDictionary) {
       // TODO(johnniwinther): Find another way to check this invariant that
       // doesn't need the compiler.
-      assert(
-          other.keyType == classWorld.backend.compiler.commonMasks.stringType);
-      TypeMask newKeyType = keyType.union(other.keyType, classWorld);
+      assert(other.keyType ==
+          new TypeMask.nonNullExact(
+              closedWorld.backendClasses.stringImplementation, closedWorld));
+      TypeMask newKeyType = keyType.union(other.keyType, closedWorld);
       TypeMask newValueType =
-          other.typeMap.values.fold(keyType, (p, n) => p.union(n, classWorld));
-      TypeMask newForwardTo = forwardTo.union(other.forwardTo, classWorld);
+          other.typeMap.values.fold(keyType, (p, n) => p.union(n, closedWorld));
+      TypeMask newForwardTo = forwardTo.union(other.forwardTo, closedWorld);
       MapTypeMask newMapTypeMask = new MapTypeMask(
           newForwardTo,
           allocationNode == other.allocationNode ? allocationNode : null,
@@ -95,7 +96,7 @@
           newValueType);
       return newMapTypeMask;
     } else {
-      return forwardTo.union(other, classWorld);
+      return forwardTo.union(other, closedWorld);
     }
   }
 
diff --git a/pkg/compiler/lib/src/types/masks.dart b/pkg/compiler/lib/src/types/masks.dart
index b498b80..9f59ad5 100644
--- a/pkg/compiler/lib/src/types/masks.dart
+++ b/pkg/compiler/lib/src/types/masks.dart
@@ -5,7 +5,7 @@
 library masks;
 
 import '../common.dart';
-import '../common/backend_api.dart' show Backend;
+import '../common/backend_api.dart' show BackendClasses;
 import '../compiler.dart' show Compiler;
 import '../constants/values.dart' show PrimitiveConstantValue;
 import '../elements/elements.dart';
@@ -18,7 +18,7 @@
         UniverseSelectorConstraints,
         SelectorConstraintsStrategy;
 import '../util/util.dart';
-import '../world.dart' show ClassWorld, ClosedWorld;
+import '../world.dart' show ClosedWorld;
 import 'abstract_value_domain.dart' show AbstractValue;
 
 part 'container_type_mask.dart';
@@ -37,7 +37,9 @@
 
   CommonMasks(this.compiler);
 
-  ClassWorld get classWorld => compiler.closedWorld;
+  ClosedWorld get closedWorld => compiler.closedWorld;
+
+  BackendClasses get backendClasses => closedWorld.backendClasses;
 
   TypeMask _dynamicType;
   TypeMask _nonNullType;
@@ -63,72 +65,72 @@
   TypeMask _asyncStarStreamType;
 
   TypeMask get dynamicType => _dynamicType ??=
-      new TypeMask.subclass(classWorld.coreClasses.objectClass, classWorld);
+      new TypeMask.subclass(closedWorld.coreClasses.objectClass, closedWorld);
 
   TypeMask get nonNullType => _nonNullType ??= new TypeMask.nonNullSubclass(
-      classWorld.coreClasses.objectClass, classWorld);
+      closedWorld.coreClasses.objectClass, closedWorld);
 
   TypeMask get intType => _intType ??= new TypeMask.nonNullSubclass(
-      compiler.backend.intImplementation, classWorld);
+      backendClasses.intImplementation, closedWorld);
 
   TypeMask get uint32Type => _uint32Type ??= new TypeMask.nonNullSubclass(
-      compiler.backend.uint32Implementation, classWorld);
+      backendClasses.uint32Implementation, closedWorld);
 
   TypeMask get uint31Type => _uint31Type ??= new TypeMask.nonNullExact(
-      compiler.backend.uint31Implementation, classWorld);
+      backendClasses.uint31Implementation, closedWorld);
 
   TypeMask get positiveIntType =>
       _positiveIntType ??= new TypeMask.nonNullSubclass(
-          compiler.backend.positiveIntImplementation, classWorld);
+          backendClasses.positiveIntImplementation, closedWorld);
 
   TypeMask get doubleType => _doubleType ??= new TypeMask.nonNullExact(
-      compiler.backend.doubleImplementation, classWorld);
+      backendClasses.doubleImplementation, closedWorld);
 
   TypeMask get numType => _numType ??= new TypeMask.nonNullSubclass(
-      compiler.backend.numImplementation, classWorld);
+      backendClasses.numImplementation, closedWorld);
 
-  TypeMask get boolType => _boolType ??= new TypeMask.nonNullExact(
-      compiler.backend.boolImplementation, classWorld);
+  TypeMask get boolType => _boolType ??=
+      new TypeMask.nonNullExact(backendClasses.boolImplementation, closedWorld);
 
   TypeMask get functionType => _functionType ??= new TypeMask.nonNullSubtype(
-      compiler.backend.functionImplementation, classWorld);
+      backendClasses.functionImplementation, closedWorld);
 
-  TypeMask get listType => _listType ??= new TypeMask.nonNullExact(
-      compiler.backend.listImplementation, classWorld);
+  TypeMask get listType => _listType ??=
+      new TypeMask.nonNullExact(backendClasses.listImplementation, closedWorld);
 
   TypeMask get constListType => _constListType ??= new TypeMask.nonNullExact(
-      compiler.backend.constListImplementation, classWorld);
+      backendClasses.constListImplementation, closedWorld);
 
   TypeMask get fixedListType => _fixedListType ??= new TypeMask.nonNullExact(
-      compiler.backend.fixedListImplementation, classWorld);
+      backendClasses.fixedListImplementation, closedWorld);
 
   TypeMask get growableListType =>
       _growableListType ??= new TypeMask.nonNullExact(
-          compiler.backend.growableListImplementation, classWorld);
+          backendClasses.growableListImplementation, closedWorld);
 
   TypeMask get mapType => _mapType ??= new TypeMask.nonNullSubtype(
-      compiler.backend.mapImplementation, classWorld);
+      backendClasses.mapImplementation, closedWorld);
 
   TypeMask get constMapType => _constMapType ??= new TypeMask.nonNullSubtype(
-      compiler.backend.constMapImplementation, classWorld);
+      backendClasses.constMapImplementation, closedWorld);
 
   TypeMask get stringType => _stringType ??= new TypeMask.nonNullExact(
-      compiler.backend.stringImplementation, classWorld);
+      backendClasses.stringImplementation, closedWorld);
 
-  TypeMask get typeType => _typeType ??= new TypeMask.nonNullExact(
-      compiler.backend.typeImplementation, classWorld);
+  TypeMask get typeType => _typeType ??=
+      new TypeMask.nonNullExact(backendClasses.typeImplementation, closedWorld);
 
   TypeMask get syncStarIterableType =>
       _syncStarIterableType ??= new TypeMask.nonNullExact(
-          compiler.backend.syncStarIterableImplementation, classWorld);
+          backendClasses.syncStarIterableImplementation, closedWorld);
 
   TypeMask get asyncFutureType =>
       _asyncFutureType ??= new TypeMask.nonNullExact(
-          compiler.backend.asyncFutureImplementation, classWorld);
+          backendClasses.asyncFutureImplementation, closedWorld);
 
   TypeMask get asyncStarStreamType =>
       _asyncStarStreamType ??= new TypeMask.nonNullExact(
-          compiler.backend.asyncStarStreamImplementation, classWorld);
+          backendClasses.asyncStarStreamImplementation, closedWorld);
 
   // TODO(johnniwinther): Assert that the null type has been resolved.
   TypeMask get nullType => _nullType ??= const TypeMask.empty();
diff --git a/pkg/compiler/lib/src/types/value_type_mask.dart b/pkg/compiler/lib/src/types/value_type_mask.dart
index 1ca437b..ba99b06 100644
--- a/pkg/compiler/lib/src/types/value_type_mask.dart
+++ b/pkg/compiler/lib/src/types/value_type_mask.dart
@@ -27,8 +27,8 @@
     return super.equalsDisregardNull(other) && value == other.value;
   }
 
-  TypeMask intersection(TypeMask other, ClassWorld classWorld) {
-    TypeMask forwardIntersection = forwardTo.intersection(other, classWorld);
+  TypeMask intersection(TypeMask other, ClosedWorld closedWorld) {
+    TypeMask forwardIntersection = forwardTo.intersection(other, closedWorld);
     if (forwardIntersection.isEmptyOrNull) return forwardIntersection;
     return forwardIntersection.isNullable ? nullable() : nonNullable();
   }
diff --git a/pkg/compiler/lib/src/universe/class_set.dart b/pkg/compiler/lib/src/universe/class_set.dart
index be69cc2..2dd892e 100644
--- a/pkg/compiler/lib/src/universe/class_set.dart
+++ b/pkg/compiler/lib/src/universe/class_set.dart
@@ -19,7 +19,7 @@
 
 /// Node for [cls] in a tree forming the subclass relation of [ClassElement]s.
 ///
-/// This is used by the [ClassWorld] to perform queries on subclass and subtype
+/// This is used by the [ClosedWorld] to perform queries on subclass and subtype
 /// relations.
 ///
 /// For this class hierarchy:
diff --git a/pkg/compiler/lib/src/universe/function_set.dart b/pkg/compiler/lib/src/universe/function_set.dart
index c34ae91..c05c7f9 100644
--- a/pkg/compiler/lib/src/universe/function_set.dart
+++ b/pkg/compiler/lib/src/universe/function_set.dart
@@ -125,7 +125,7 @@
   String get name => selector.name;
 
   bool applies(Element element, ClosedWorld closedWorld) {
-    if (!selector.appliesUnnamed(element, closedWorld.backend)) return false;
+    if (!selector.appliesUnnamed(element)) return false;
     return constraint.canHit(element, selector, closedWorld);
   }
 
@@ -287,7 +287,7 @@
           ClassElement cls = element.enclosingClass;
           return [cls]..addAll(closedWorld.mixinUsesOf(cls));
         }).map((cls) {
-          if (closedWorld.backend.isNullImplementation(cls)) {
+          if (closedWorld.backendClasses.nullImplementation == cls) {
             return const TypeMask.empty();
           } else if (closedWorld.isInstantiated(cls.declaration)) {
             return new TypeMask.nonNullSubclass(cls.declaration, closedWorld);
diff --git a/pkg/compiler/lib/src/universe/selector.dart b/pkg/compiler/lib/src/universe/selector.dart
index 14d8b3a..39937fb 100644
--- a/pkg/compiler/lib/src/universe/selector.dart
+++ b/pkg/compiler/lib/src/universe/selector.dart
@@ -217,12 +217,12 @@
     return kind;
   }
 
-  bool appliesUnnamed(Element element, Target target) {
+  bool appliesUnnamed(Element element) {
     assert(sameNameHack(element));
-    return appliesUntyped(element, target);
+    return appliesUntyped(element);
   }
 
-  bool appliesUntyped(Element element, Target target) {
+  bool appliesUntyped(Element element) {
     assert(sameNameHack(element));
     if (Elements.isUnresolved(element)) return false;
     if (memberName.isPrivate && memberName.library != element.library) {
@@ -230,7 +230,6 @@
       // `memberName != element.memberName`.
       return false;
     }
-    if (target.isForeign(element)) return true;
     if (element.isSetter) return isSetter;
     if (element.isGetter) return isGetter || isCall;
     if (element.isField) {
@@ -253,9 +252,9 @@
     return element.isConstructor || name == element.name;
   }
 
-  bool applies(Element element, Target target) {
+  bool applies(Element element) {
     if (!sameNameHack(element)) return false;
-    return appliesUnnamed(element, target);
+    return appliesUnnamed(element);
   }
 
   bool match(SelectorKind kind, Name memberName, CallStructure callStructure) {
diff --git a/pkg/compiler/lib/src/universe/universe.dart b/pkg/compiler/lib/src/universe/universe.dart
index 957b02b..03fc3c1 100644
--- a/pkg/compiler/lib/src/universe/universe.dart
+++ b/pkg/compiler/lib/src/universe/universe.dart
@@ -11,7 +11,7 @@
 import '../dart_types.dart';
 import '../elements/elements.dart';
 import '../util/util.dart';
-import '../world.dart' show ClassWorld, ClosedWorld, OpenWorld;
+import '../world.dart' show World, ClosedWorld, OpenWorld;
 import 'selector.dart' show Selector;
 import 'use.dart' show DynamicUse, DynamicUseKind, StaticUse, StaticUseKind;
 
@@ -29,11 +29,11 @@
   /// Returns whether [element] is a potential target when being
   /// invoked on a receiver with this constraint. [selector] is used to ensure
   /// library privacy is taken into account.
-  bool canHit(Element element, Selector selector, ClassWorld classWorld);
+  bool canHit(Element element, Selector selector, World world);
 
   /// Returns whether this [TypeMask] applied to [selector] can hit a
   /// [noSuchMethod].
-  bool needsNoSuchMethodHandling(Selector selector, ClassWorld classWorld);
+  bool needsNoSuchMethodHandling(Selector selector, World world);
 }
 
 /// The combined constraints on receivers all the dynamic call sites of the same
@@ -71,7 +71,7 @@
   ///
   /// Ideally the selector constraints for calls `foo` with two positional
   /// arguments apply to `A.foo` but `B.foo`.
-  bool applies(Element element, Selector selector, ClassWorld world);
+  bool applies(Element element, Selector selector, World world);
 
   /// Returns `true` if at least one of the receivers matching these constraints
   /// in the closed [world] have no implementation matching [selector].
@@ -84,7 +84,7 @@
   ///
   /// the potential receiver `new A()` has no implementation of `foo` and thus
   /// needs to handle the call through its `noSuchMethod` handler.
-  bool needsNoSuchMethodHandling(Selector selector, ClassWorld world);
+  bool needsNoSuchMethodHandling(Selector selector, World world);
 }
 
 /// A mutable [SelectorConstraints] used in [Universe].
@@ -103,7 +103,7 @@
 }
 
 /// The [Universe] is an auxiliary class used in the process of computing the
-/// [ClassWorld]. The concepts here and in [ClassWorld] are very similar -- in
+/// [ClosedWorld]. The concepts here and in [ClosedWorld] are very similar -- in
 /// the same way that the "universe expands" you can think of this as a mutable
 /// world that is expanding as we visit and discover parts of the program.
 // TODO(sigmund): rename to "growing/expanding/mutable world"?
@@ -129,7 +129,7 @@
   Iterable<DartType> get instantiatedTypes;
 
   /// Returns `true` if [member] is invoked as a setter.
-  bool hasInvokedSetter(Element member, ClassWorld world);
+  bool hasInvokedSetter(Element member, World world);
 }
 
 abstract class ResolutionUniverse implements Universe {
@@ -299,10 +299,10 @@
   }
 
   bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors,
-      Element member, ClassWorld world) {
+      Element member, OpenWorld world) {
     if (selectors == null) return false;
     for (Selector selector in selectors.keys) {
-      if (selector.appliesUnnamed(member, world.backend)) {
+      if (selector.appliesUnnamed(member)) {
         SelectorConstraints masks = selectors[selector];
         if (masks.applies(member, selector, world)) {
           return true;
@@ -542,7 +542,7 @@
       Element member, ClosedWorld world) {
     if (selectors == null) return false;
     for (Selector selector in selectors.keys) {
-      if (selector.appliesUnnamed(member, world.backend)) {
+      if (selector.appliesUnnamed(member)) {
         SelectorConstraints masks = selectors[selector];
         if (masks.applies(member, selector, world)) {
           return true;
diff --git a/pkg/compiler/lib/src/universe/use.dart b/pkg/compiler/lib/src/universe/use.dart
index a1756ed..543e2bd 100644
--- a/pkg/compiler/lib/src/universe/use.dart
+++ b/pkg/compiler/lib/src/universe/use.dart
@@ -21,7 +21,7 @@
 import '../dart_types.dart';
 import '../elements/elements.dart';
 import '../util/util.dart' show Hashing;
-import '../world.dart' show ClassWorld;
+import '../world.dart' show World;
 import 'call_structure.dart' show CallStructure;
 import 'selector.dart' show Selector;
 import 'universe.dart' show ReceiverConstraint;
@@ -37,8 +37,8 @@
 
   DynamicUse(this.selector, this.mask);
 
-  bool appliesUnnamed(Element element, ClassWorld world) {
-    return selector.appliesUnnamed(element, world.backend) &&
+  bool appliesUnnamed(Element element, World world) {
+    return selector.appliesUnnamed(element) &&
         (mask == null || mask.canHit(element, selector, world));
   }
 
diff --git a/pkg/compiler/lib/src/universe/world_impact.dart b/pkg/compiler/lib/src/universe/world_impact.dart
index 723a87a..9012057 100644
--- a/pkg/compiler/lib/src/universe/world_impact.dart
+++ b/pkg/compiler/lib/src/universe/world_impact.dart
@@ -17,7 +17,7 @@
 ///
 /// The impact object can be computed locally by inspecting just the resolution
 /// information of that element alone. The compiler uses [Universe] and
-/// [ClassWorld] to combine the information discovered in the impact objects of
+/// [World] to combine the information discovered in the impact objects of
 /// all elements reachable in an application.
 class WorldImpact {
   const WorldImpact();
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index c348c77..40e73a5 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -5,7 +5,7 @@
 library dart2js.world;
 
 import 'closure.dart' show SynthesizedCallMethodElementX;
-import 'common/backend_api.dart' show Backend;
+import 'common/backend_api.dart' show BackendClasses;
 import 'common.dart';
 import 'compiler.dart' show Compiler;
 import 'core_types.dart' show CoreClasses;
@@ -27,7 +27,10 @@
 import 'universe/side_effects.dart' show SideEffects;
 import 'util/util.dart' show Link;
 
-/// The [ClassWorld] represents the information known about a program when
+/// Common superinterface for [OpenWorld] and [ClosedWorld].
+abstract class World {}
+
+/// The [ClosedWorld] represents the information known about a program when
 /// compiling with closed-world semantics.
 ///
 /// Given the entrypoint of an application, we can track what's reachable from
@@ -35,49 +38,13 @@
 /// JavaScript types are touched, what language features are used, and so on.
 /// This precise knowledge about what's live in the program is later used in
 /// optimizations and other compiler decisions during code generation.
-abstract class ClassWorld {
-  // TODO(johnniwinther): Refine this into a `BackendClasses` interface.
-  Backend get backend;
+abstract class ClosedWorld implements World {
+  /// Access to core classes used by the backend.
+  BackendClasses get backendClasses;
 
+  /// Access to core classes used in the Dart language.
   CoreClasses get coreClasses;
 
-  /// Returns `true` if the class world is closed.
-  bool get isClosed;
-
-  /// Returns `true` if closed-world assumptions can be made, that is,
-  /// incremental compilation isn't enabled.
-  bool get hasClosedWorldAssumption;
-
-  /// Returns a string representation of the closed world.
-  ///
-  /// If [cls] is provided, the dump will contain only classes related to [cls].
-  String dump([ClassElement cls]);
-
-  /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies
-  /// of known classes.
-  ///
-  /// This method is only provided for testing. For queries on classes, use the
-  /// methods defined in [ClassWorld].
-  ClassHierarchyNode getClassHierarchyNode(ClassElement cls);
-
-  /// Returns [ClassSet] for [cls] used to model the extends and implements
-  /// relations of known classes.
-  ///
-  /// This method is only provided for testing. For queries on classes, use the
-  /// methods defined in [ClassWorld].
-  ClassSet getClassSet(ClassElement cls);
-
-  // TODO(johnniwinther): Find a better strategy for caching these.
-  @deprecated
-  List<Map<ClassElement, TypeMask>> get canonicalizedTypeMasks;
-}
-
-/// The [ClosedWorld] represents the information known about a program when
-/// compiling with closed-world semantics.
-///
-/// This expands [ClassWorld] with information about live functions,
-/// side effects, and selectors with known single targets.
-abstract class ClosedWorld extends ClassWorld {
   /// Returns `true` if [cls] is either directly or indirectly instantiated.
   bool isInstantiated(ClassElement cls);
 
@@ -189,6 +156,24 @@
   /// Returns `true` if any subclass of [superclass] implements [type].
   bool hasAnySubclassThatImplements(ClassElement superclass, ClassElement type);
 
+  /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies
+  /// of known classes.
+  ///
+  /// This method is only provided for testing. For queries on classes, use the
+  /// methods defined in [ClosedWorld].
+  ClassHierarchyNode getClassHierarchyNode(ClassElement cls);
+
+  /// Returns [ClassSet] for [cls] used to model the extends and implements
+  /// relations of known classes.
+  ///
+  /// This method is only provided for testing. For queries on classes, use the
+  /// methods defined in [ClosedWorld].
+  ClassSet getClassSet(ClassElement cls);
+
+  // TODO(johnniwinther): Find a better strategy for caching these.
+  @deprecated
+  List<Map<ClassElement, TypeMask>> get canonicalizedTypeMasks;
+
   /// Returns the [FunctionSet] containing all live functions in the closed
   /// world.
   FunctionSet get allFunctions;
@@ -230,6 +215,11 @@
   // TODO(johnniwinther): Is this 'passed invocation target` or
   // `passed as argument`?
   bool getMightBePassedToApply(Element element);
+
+  /// Returns a string representation of the closed world.
+  ///
+  /// If [cls] is provided, the dump will contain only classes related to [cls].
+  String dump([ClassElement cls]);
 }
 
 /// Interface for computing side effects and uses of elements. This is used
@@ -265,7 +255,7 @@
   void registerClosureClass(ClassElement cls);
 }
 
-abstract class OpenWorld implements ClassWorld {
+abstract class OpenWorld implements World {
   /// Called to add [cls] to the set of known classes.
   ///
   /// This ensures that class hierarchy queries can be performed on [cls] and
@@ -512,8 +502,8 @@
   @override
   ClassElement getLubOfInstantiatedSubclasses(ClassElement cls) {
     assert(isClosed);
-    if (backend.isJsInterop(cls)) {
-      return backend.helpers.jsJavaScriptObjectClass;
+    if (_backend.isJsInterop(cls)) {
+      return _backend.helpers.jsJavaScriptObjectClass;
     }
     ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration];
     return hierarchy != null
@@ -524,8 +514,8 @@
   @override
   ClassElement getLubOfInstantiatedSubtypes(ClassElement cls) {
     assert(isClosed);
-    if (backend.isJsInterop(cls)) {
-      return backend.helpers.jsJavaScriptObjectClass;
+    if (_backend.isJsInterop(cls)) {
+      return _backend.helpers.jsJavaScriptObjectClass;
     }
     ClassSet classSet = _classSets[cls.declaration];
     return classSet != null ? classSet.getLubOfInstantiatedSubtypes() : null;
@@ -669,7 +659,8 @@
   }
 
   final Compiler _compiler;
-  JavaScriptBackend get backend => _compiler.backend;
+  BackendClasses get backendClasses => _backend.backendClasses;
+  JavaScriptBackend get _backend => _compiler.backend;
   CommonMasks get commonMasks => _compiler.commonMasks;
   final FunctionSet allFunctions;
   final Set<Element> functionsCalledInLoop = new Set<Element>();
@@ -704,11 +695,6 @@
 
   bool get isClosed => _closed;
 
-  // Used by selectors.
-  bool isForeign(Element element) {
-    return backend.isForeign(element);
-  }
-
   Set<ClassElement> typesImplementedBySubclassesOf(ClassElement cls) {
     return _typesImplementedBySubclasses[cls.declaration];
   }
@@ -749,7 +735,7 @@
   /// of known classes.
   ///
   /// This method is only provided for testing. For queries on classes, use the
-  /// methods defined in [ClassWorld].
+  /// methods defined in [ClosedWorld].
   ClassHierarchyNode getClassHierarchyNode(ClassElement cls) {
     return _classHierarchyNodes[cls.declaration];
   }
@@ -769,7 +755,7 @@
   /// relations of known classes.
   ///
   /// This method is only provided for testing. For queries on classes, use the
-  /// methods defined in [ClassWorld].
+  /// methods defined in [ClosedWorld].
   ClassSet getClassSet(ClassElement cls) {
     return _classSets[cls.declaration];
   }
@@ -924,7 +910,7 @@
 
   bool fieldNeverChanges(Element element) {
     if (!element.isField) return false;
-    if (backend.isNative(element)) {
+    if (_backend.isNative(element)) {
       // Some native fields are views of data that may be changed by operations.
       // E.g. node.firstChild depends on parentNode.removeBefore(n1, n2).
       // TODO(sra): Refine the effect classification so that native effects are
@@ -1024,6 +1010,4 @@
   bool getCurrentlyKnownMightBePassedToApply(Element element) {
     return getMightBePassedToApply(element);
   }
-
-  bool get hasClosedWorldAssumption => !_compiler.options.hasIncrementalSupport;
 }
diff --git a/runtime/observatory/.gitignore b/runtime/observatory/.gitignore
index 06adbfb..c73eaff 100644
--- a/runtime/observatory/.gitignore
+++ b/runtime/observatory/.gitignore
@@ -3,4 +3,3 @@
 build
 .pub
 .idea
-.packages
\ No newline at end of file
diff --git a/runtime/observatory/pubspec.lock b/runtime/observatory/pubspec.lock
new file mode 100644
index 0000000..1f8a109
--- /dev/null
+++ b/runtime/observatory/pubspec.lock
@@ -0,0 +1,251 @@
+# Generated by pub
+# See http://pub.dartlang.org/doc/glossary.html#lockfile
+packages:
+  analyzer:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/analyzer"
+      relative: true
+    source: path
+    version: "0.26.1+14"
+  args:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/args"
+      relative: true
+    source: path
+    version: "0.13.2"
+  async:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/async"
+      relative: true
+    source: path
+    version: "1.4.0"
+  barback:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/barback"
+      relative: true
+    source: path
+    version: "0.15.2+7"
+  browser:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/browser"
+      relative: true
+    source: path
+    version: "0.10.0+2"
+  charcode:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/charcode"
+      relative: true
+    source: path
+    version: "1.1.0"
+  charted:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/charted"
+      relative: true
+    source: path
+    version: "0.4.0+1"
+  cli_util:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/cli_util"
+      relative: true
+    source: path
+    version: "0.0.1+2"
+  code_transformers:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/code_transformers"
+      relative: true
+    source: path
+    version: "0.2.11"
+  collection:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/collection"
+      relative: true
+    source: path
+    version: "1.2.0"
+  csslib:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/csslib"
+      relative: true
+    source: path
+    version: "0.12.2"
+  dart_style:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/dart_style"
+      relative: true
+    source: path
+    version: "0.2.1"
+  dart_to_js_script_rewriter:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/dart_to_js_script_rewriter"
+      relative: true
+    source: path
+    version: "1.0.1"
+  glob:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/glob"
+      relative: true
+    source: path
+    version: "1.0.5"
+  html:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/html"
+      relative: true
+    source: path
+    version: "0.12.2"
+  initialize:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/initialize"
+      relative: true
+    source: path
+    version: "0.6.1+2"
+  intl:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/intl"
+      relative: true
+    source: path
+    version: "0.12.4+3"
+  logging:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/logging"
+      relative: true
+    source: path
+    version: "0.11.2"
+  matcher:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/matcher"
+      relative: true
+    source: path
+    version: "0.12.0+1"
+  observe:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/observe"
+      relative: true
+    source: path
+    version: "0.13.1+3"
+  package_config:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/package_config"
+      relative: true
+    source: path
+    version: "0.1.3"
+  path:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/path"
+      relative: true
+    source: path
+    version: "1.3.9"
+  petitparser:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/petitparser"
+      relative: true
+    source: path
+    version: "1.5.0"
+  plugin:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/plugin"
+      relative: true
+    source: path
+    version: "0.1.0"
+  pool:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/pool"
+      relative: true
+    source: path
+    version: "1.2.1"
+  quiver:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/quiver"
+      relative: true
+    source: path
+    version: "0.21.4"
+  quiver_iterables:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/quiver_iterables"
+      relative: true
+    source: path
+    version: "1.0.0"
+  smoke:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/smoke"
+      relative: true
+    source: path
+    version: "0.3.6"
+  source_maps:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/source_maps"
+      relative: true
+    source: path
+    version: "0.10.1"
+  source_span:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/source_span"
+      relative: true
+    source: path
+    version: "1.2.1"
+  stack_trace:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/stack_trace"
+      relative: true
+    source: path
+    version: "1.5.0"
+  string_scanner:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/string_scanner"
+      relative: true
+    source: path
+    version: "0.1.4"
+  template_binding:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/template_binding"
+      relative: true
+    source: path
+    version: "0.14.0+2"
+  unittest:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/unittest"
+      relative: true
+    source: path
+    version: "0.11.6+1"
+  usage:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/usage"
+      relative: true
+    source: path
+    version: "1.0.1"
+  utf:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/utf"
+      relative: true
+    source: path
+    version: "0.9.0+2"
+  watcher:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/watcher"
+      relative: true
+    source: path
+    version: "0.9.7"
+  web_components:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/web_components"
+      relative: true
+    source: path
+    version: "0.12.3"
+  when:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/when"
+      relative: true
+    source: path
+    version: "0.2.0"
+  which:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/which"
+      relative: true
+    source: path
+    version: "0.1.3"
+  yaml:
+    description:
+      path: "../../third_party/observatory_pub_packages/packages/yaml"
+      relative: true
+    source: path
+    version: "2.1.7"
+sdks:
+  dart: any
diff --git a/tests/compiler/dart2js/map_tracer_test.dart b/tests/compiler/dart2js/map_tracer_test.dart
index 6c4af67..4399798 100644
--- a/tests/compiler/dart2js/map_tracer_test.dart
+++ b/tests/compiler/dart2js/map_tracer_test.dart
@@ -211,7 +211,7 @@
   Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(generateTest(allocation), uri,
       expectedErrors: 0, expectedWarnings: 1);
-  var classWorld = compiler.openWorld.closeWorld();
+  var closedWorld = compiler.openWorld.closeWorld();
   asyncTest(() => compiler.run(uri).then((_) {
         var keyType, valueType;
         var commonMasks = compiler.commonMasks;
@@ -238,9 +238,9 @@
         }
 
         K(TypeMask other) =>
-            simplify(keyType.union(other, classWorld), compiler);
+            simplify(keyType.union(other, closedWorld), compiler);
         V(TypeMask other) =>
-            simplify(valueType.union(other, classWorld), compiler).nullable();
+            simplify(valueType.union(other, closedWorld), compiler).nullable();
 
         checkType('mapInField', K(aKeyType), V(commonMasks.numType));
         checkType('mapPassedToMethod', K(aKeyType), V(commonMasks.numType));
diff --git a/tests/compiler/dart2js/patch_test.dart b/tests/compiler/dart2js/patch_test.dart
index 3990949..f12c2b2 100644
--- a/tests/compiler/dart2js/patch_test.dart
+++ b/tests/compiler/dart2js/patch_test.dart
@@ -942,7 +942,7 @@
   TypeMask typeMask = new TypeMask.exact(cls, world);
   FunctionElement method = cls.implementation.lookupLocalMember('method');
   method.computeType(compiler.resolution);
-  Expect.isTrue(selector.applies(method, world.backend));
+  Expect.isTrue(selector.applies(method));
   Expect.isTrue(typeMask.canHit(method, selector, world));
 
   // Check that the declaration method in the declaration class is a target
@@ -952,7 +952,7 @@
   typeMask = new TypeMask.exact(cls, world);
   method = cls.lookupLocalMember('clear');
   method.computeType(compiler.resolution);
-  Expect.isTrue(selector.applies(method, world.backend));
+  Expect.isTrue(selector.applies(method));
   Expect.isTrue(typeMask.canHit(method, selector, world));
 
   // Check that the declaration method in the declaration class is a target
@@ -960,7 +960,7 @@
   cls = ensure(compiler, "B", compiler.commonElements.coreLibrary.find);
   cls.ensureResolved(compiler.resolution);
   typeMask = new TypeMask.exact(cls, world);
-  Expect.isTrue(selector.applies(method, world.backend));
+  Expect.isTrue(selector.applies(method));
   Expect.isTrue(typeMask.canHit(method, selector, world));
 }
 
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart
index 0bb2985..cc429df 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart
@@ -37,9 +37,9 @@
               typesInferrer.getTypeOfElement(element).containsOnly(type));
         }
 
-        checkFieldTypeInClass(
-            'A', 'intField', compiler.backend.uint31Implementation);
-        checkFieldTypeInClass(
-            'A', 'stringField', compiler.backend.stringImplementation);
+        checkFieldTypeInClass('A', 'intField',
+            compiler.backend.backendClasses.uint31Implementation);
+        checkFieldTypeInClass('A', 'stringField',
+            compiler.backend.backendClasses.stringImplementation);
       }));
 }
diff --git a/tests/compiler/dart2js/type_mask_test.dart b/tests/compiler/dart2js/type_mask_test.dart
index 00508d1..fae28df 100644
--- a/tests/compiler/dart2js/type_mask_test.dart
+++ b/tests/compiler/dart2js/type_mask_test.dart
@@ -21,7 +21,7 @@
 main() {
   Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(CODE, uri);
-  var classWorld = compiler.openWorld.closeWorld();
+  var closedWorld = compiler.openWorld.closeWorld();
 
   asyncTest(() => compiler.run(uri).then((_) {
         var classA = findElement(compiler, 'A');
@@ -29,37 +29,37 @@
         var classC = findElement(compiler, 'C');
         var classD = findElement(compiler, 'D');
 
-        var exactA = new TypeMask.nonNullExact(classA, classWorld);
-        var exactB = new TypeMask.nonNullExact(classB, classWorld);
-        var exactC = new TypeMask.nonNullExact(classC, classWorld);
-        var exactD = new TypeMask.nonNullExact(classD, classWorld);
+        var exactA = new TypeMask.nonNullExact(classA, closedWorld);
+        var exactB = new TypeMask.nonNullExact(classB, closedWorld);
+        var exactC = new TypeMask.nonNullExact(classC, closedWorld);
+        var exactD = new TypeMask.nonNullExact(classD, closedWorld);
 
-        var subclassA = new TypeMask.nonNullSubclass(classA, classWorld);
-        var subtypeA = new TypeMask.nonNullSubtype(classA, classWorld);
+        var subclassA = new TypeMask.nonNullSubclass(classA, closedWorld);
+        var subtypeA = new TypeMask.nonNullSubtype(classA, closedWorld);
 
         var subclassObject = new TypeMask.nonNullSubclass(
-            compiler.coreClasses.objectClass, classWorld);
+            compiler.coreClasses.objectClass, closedWorld);
 
         var unionABC =
-            UnionTypeMask.unionOf([exactA, exactB, exactC], classWorld);
+            UnionTypeMask.unionOf([exactA, exactB, exactC], closedWorld);
         var unionABnC = UnionTypeMask
-            .unionOf([exactA, exactB.nullable(), exactC], classWorld);
-        var unionAB = UnionTypeMask.unionOf([exactA, exactB], classWorld);
+            .unionOf([exactA, exactB.nullable(), exactC], closedWorld);
+        var unionAB = UnionTypeMask.unionOf([exactA, exactB], closedWorld);
         var unionSubtypeAC =
-            UnionTypeMask.unionOf([subtypeA, exactC], classWorld);
+            UnionTypeMask.unionOf([subtypeA, exactC], closedWorld);
         var unionSubclassAC =
-            UnionTypeMask.unionOf([subclassA, exactC], classWorld);
+            UnionTypeMask.unionOf([subclassA, exactC], closedWorld);
         var unionBCD =
-            UnionTypeMask.unionOf([exactB, exactC, exactD], classWorld);
+            UnionTypeMask.unionOf([exactB, exactC, exactD], closedWorld);
         var unionBCDn = UnionTypeMask
-            .unionOf([exactB, exactC, exactD.nullable()], classWorld);
+            .unionOf([exactB, exactC, exactD.nullable()], closedWorld);
 
         Expect.isFalse(unionABC.isNullable);
         Expect.isTrue(unionABnC.isNullable);
         Expect.isFalse(unionBCD.isNullable);
         Expect.isTrue(unionBCDn.isNullable);
 
-        rule(a, b, c) => Expect.equals(c, a.isInMask(b, classWorld));
+        rule(a, b, c) => Expect.equals(c, a.isInMask(b, closedWorld));
 
         rule(exactA, exactA, true);
         rule(exactA, exactB, false);
diff --git a/tools/VERSION b/tools/VERSION
index 59e3311..07b5836 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 1
 MINOR 20
 PATCH 0
-PRERELEASE 8
+PRERELEASE 9
 PRERELEASE_PATCH 0