Version 1.22.0-dev.3.0

Merge commit '384d35240d34792e8f370dd3e566cebab53d0863' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e3c1bc8..d24dffa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,16 +1,35 @@
 ## 1.22.0
 
+### Language
+
+  * The `assert()` statement has been expanded to support an optional second
+    `message` argument (SDK issue [27342](https://github.com/dart-lang/sdk/issues/27342)).
+
+    The message is displayed if the assert fails. It can be any object, and it
+    is accessible as `AssertionError.message`. It can be used to provide more
+    user friendly exception outputs. As an example, the following assert:
+
+    ```dart
+    assert(configFile != null, "Tool config missing. Please see https://goo.gl/k8iAi for details.");
+    ```
+
+    would produce the following exception output:
+
+    ```
+    Unhandled exception:
+    'file:///Users/mit/tmp/tool/bin/main.dart': Failed assertion: line 9 pos 10: 
+    'configFile != null': Tool config missing. Please see https://goo.gl/k8iAi for details.
+    #0      _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:33)
+    #1      _AssertionError._throwNew (dart:core-patch/errors_patch.dart:29)
+    #2      main (file:///Users/mit/tmp/tool/bin/main.dart:9:10)
+    ```
+
 ### Tool changes
 
 * Dart2Js
 
   * Remove support for (long-time deprecated) mixin typedefs.
 
-* Dart Dev Compiler
-
-  * Support messages in `assert()` statements. (SDK issue
-    [27342](https://github.com/dart-lang/sdk/issues/27342))
-
 * Pub
 
   * Avoid using a barback asset server for executables unless they actually use
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index 44e846c..f2fee9d 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -1781,9 +1781,8 @@
 The scope of the \EXTENDS{} and \WITH{} clauses of a class $C$ is the type-parameter scope of $C$.
 
 \LMHash{}
-%It is a compile-time error if  the \EXTENDS{} clause of a class $C$ includes a type expression that does not denote a class available in the lexical scope of $C$.
-It is a compile-time error if  the \EXTENDS{} clause of a class $C$ specifies an enumerated type (\ref{enums}), a malformed  type or a deferred type (\ref{staticTypes}) as a superclass.
-% too strict? Do we e want extends List<Undeclared> to work as List<dynamic>?
+It is a compile-time error if the \EXTENDS{} clause of a class $C$ specifies a type variable (\ref{generics}), a type alias (\ref{typedef}), an enumerated type (\ref{enums}), a malformed type, or a deferred type (\ref{staticTypes}) as a superclass.
+It is a compile-time error if the \EXTENDS{} clause of a class $C$ specifies type \DYNAMIC{} as a superinterface.
 
 \commentary{ The type parameters of a generic class are available in the lexical scope of the superclass clause, potentially shadowing classes in the surrounding scope. The following code is therefore illegal and should cause a compile-time error:
 }
@@ -1917,7 +1916,9 @@
 The scope of the \IMPLEMENTS{} clause of a class $C$ is the type-parameter scope of $C$.
 
 \LMHash{}
-It is a compile-time error if  the \IMPLEMENTS{}  clause of a class $C$ specifies a type variable as a superinterface. It is a compile-time error if  the  \IMPLEMENTS{} clause of a class $C$ specifies an enumerated type (\ref{enums}),  a malformed type or deferred type (\ref{staticTypes}) as a superinterface.  It is a compile-time error if the \IMPLEMENTS{} clause of a class $C$ specifies type \DYNAMIC{} as a superinterface. It is a compile-time error if  the  \IMPLEMENTS{} clause of a class $C$ specifies  a type $T$ as a superinterface more than once.
+It is a compile-time error if the \IMPLEMENTS{} clause of a class $C$ specifies a type variable (\ref{generics}), a type alias (\ref{typedef}), an enumerated type (\ref{enums}), a malformed type, or a deferred type (\ref{staticTypes}) as a superinterface.
+It is a compile-time error if the \IMPLEMENTS{} clause of a class $C$ specifies type \DYNAMIC{} as a superinterface.
+It is a compile-time error if the \IMPLEMENTS{} clause of a class $C$ specifies a type $T$ as a superinterface more than once.
 It is a compile-time error if the superclass of a class $C$ is specified as a superinterface of $C$.
 
 \rationale{
@@ -2090,8 +2091,10 @@
 \LMLabel{mixinApplication}
 
 \LMHash{}
-A mixin may be applied to a superclass, yielding a new class. Mixin application occurs when a mixin is mixed into a class declaration via its \WITH{} clause.  The mixin application may be used to extend a class per section (\ref{classes}); alternately, a class may be defined as a mixin application as described in this section.   It is a compile-time error if the \WITH{} clause of a mixin application $C$ includes a deferred type expression.
-
+A mixin may be applied to a superclass, yielding a new class.
+Mixin application occurs when a mixin is mixed into a class declaration via its \WITH{} clause.
+The mixin application may be used to extend a class per section (\ref{classes}); alternately, a class may be defined as a mixin application as described in this section.
+It is a compile-time error if the \WITH{} clause of a mixin application $C$ includes a type variable (\ref{generics}), a type alias (\ref{typedef}), an enumerated type (\ref{enums}), a malformed type, or a deferred type (\ref{staticTypes}).
 
 \begin{grammar}
 {\bf  mixinApplicationClass:}
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 7751fb6..5ee2afd 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -678,6 +678,19 @@
   }
 
   /**
+   * Return the [nd.AnalysisDriver] for the "innermost" context whose associated
+   * folder is or contains the given path.  ("innermost" refers to the nesting
+   * of contexts, so if there is a context for path /foo and a context for
+   * path /foo/bar, then the innermost context containing /foo/bar/baz.dart is
+   * the context for /foo/bar.)
+   *
+   * If no context contains the given path, `null` is returned.
+   */
+  nd.AnalysisDriver getContainingDriver(String path) {
+    return contextManager.getDriverFor(path);
+  }
+
+  /**
    * Return the primary [ContextSourcePair] representing the given [path].
    *
    * The [AnalysisContext] of this pair will be the context that explicitly
diff --git a/pkg/analysis_server/lib/src/computer/new_notifications.dart b/pkg/analysis_server/lib/src/computer/new_notifications.dart
index 2d575a9..1ca3636 100644
--- a/pkg/analysis_server/lib/src/computer/new_notifications.dart
+++ b/pkg/analysis_server/lib/src/computer/new_notifications.dart
@@ -16,7 +16,7 @@
   var unit = result.unit;
   if (unit != null) {
     NavigationCollectorImpl collector = new NavigationCollectorImpl();
-    computeSimpleDartNavigation(collector, unit);
+    computeDartNavigation(collector, unit, null, null);
     collector.createRegions();
     var params = new protocol.AnalysisNavigationParams(
         result.path, collector.regions, collector.targets, collector.files);
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index 5066533..424815d 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -13,6 +13,7 @@
 import 'package:analysis_server/src/constants.dart';
 import 'package:analysis_server/src/context_manager.dart';
 import 'package:analysis_server/src/domains/analysis/navigation.dart';
+import 'package:analysis_server/src/domains/analysis/navigation_dart.dart';
 import 'package:analysis_server/src/operation/operation_analysis.dart'
     show NavigationOperation, OccurrencesOperation;
 import 'package:analysis_server/src/protocol/protocol_internal.dart';
@@ -147,26 +148,24 @@
     var params = new AnalysisGetNavigationParams.fromRequest(request);
     String file = params.file;
 
-    void send(CompilationUnit unit) {
-      if (unit == null) {
+    if (server.options.enableNewAnalysisDriver) {
+      AnalysisDriver driver = server.getContainingDriver(file);
+      if (driver == null) {
         server.sendResponse(new Response.getNavigationInvalidFile(request));
       } else {
-        CompilationUnitElement unitElement = unit.element;
-        NavigationCollectorImpl collector = computeNavigation(
-            server,
-            unitElement.context,
-            unitElement.source,
-            params.offset,
-            params.length);
-        server.sendResponse(new AnalysisGetNavigationResult(
-                collector.files, collector.targets, collector.regions)
-            .toResponse(request.id));
+        AnalysisResult result = await server.getAnalysisResult(file);
+        CompilationUnit unit = result?.unit;
+        if (unit == null || !result.exists) {
+          server.sendResponse(new Response.getNavigationInvalidFile(request));
+        } else {
+          NavigationCollectorImpl collector = new NavigationCollectorImpl();
+          computeDartNavigation(collector, unit, params.offset, params.length);
+          collector.createRegions();
+          server.sendResponse(new AnalysisGetNavigationResult(
+                  collector.files, collector.targets, collector.regions)
+              .toResponse(request.id));
+        }
       }
-    }
-
-    if (server.options.enableNewAnalysisDriver) {
-      AnalysisResult result = await server.getAnalysisResult(file);
-      send(result?.unit);
       return;
     }
 
@@ -179,7 +178,20 @@
       switch (reason) {
         case AnalysisDoneReason.COMPLETE:
           CompilationUnit unit = await server.getResolvedCompilationUnit(file);
-          send(unit);
+          if (unit == null) {
+            server.sendResponse(new Response.getNavigationInvalidFile(request));
+          } else {
+            CompilationUnitElement unitElement = unit.element;
+            NavigationCollectorImpl collector = computeNavigation(
+                server,
+                unitElement.context,
+                unitElement.source,
+                params.offset,
+                params.length);
+            server.sendResponse(new AnalysisGetNavigationResult(
+                    collector.files, collector.targets, collector.regions)
+                .toResponse(request.id));
+          }
           break;
         case AnalysisDoneReason.CONTEXT_REMOVED:
           // The active contexts have changed, so try again.
diff --git a/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart b/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
index 1ae3193..63f10df 100644
--- a/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
+++ b/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
@@ -15,16 +15,31 @@
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 
-NavigationCollector computeSimpleDartNavigation(
-    NavigationCollector collector, CompilationUnit unit) {
+NavigationCollector computeDartNavigation(NavigationCollector collector,
+    CompilationUnit unit, int offset, int length) {
   _DartNavigationCollector dartCollector =
       new _DartNavigationCollector(collector);
   _DartNavigationComputerVisitor visitor =
       new _DartNavigationComputerVisitor(dartCollector);
-  unit.accept(visitor);
+  if (offset == null || length == null) {
+    unit.accept(visitor);
+  } else {
+    AstNode node = _getNodeForRange(unit, offset, length);
+    node?.accept(visitor);
+  }
   return collector;
 }
 
+AstNode _getNodeForRange(CompilationUnit unit, int offset, int length) {
+  AstNode node = new NodeLocator(offset, offset + length).searchWithin(unit);
+  for (AstNode n = node; n != null; n = n.parent) {
+    if (n is Directive) {
+      return n;
+    }
+  }
+  return node;
+}
+
 /**
  * A computer for navigation regions in a Dart [CompilationUnit].
  */
@@ -37,30 +52,10 @@
       CompilationUnit unit =
           context.getResolvedCompilationUnit2(source, libraries.first);
       if (unit != null) {
-        _DartNavigationCollector dartCollector =
-            new _DartNavigationCollector(collector);
-        _DartNavigationComputerVisitor visitor =
-            new _DartNavigationComputerVisitor(dartCollector);
-        if (offset == null || length == null) {
-          unit.accept(visitor);
-        } else {
-          AstNode node = _getNodeForRange(unit, offset, length);
-          node?.accept(visitor);
-        }
+        computeDartNavigation(collector, unit, offset, length);
       }
     }
   }
-
-  static AstNode _getNodeForRange(
-      CompilationUnit unit, int offset, int length) {
-    AstNode node = new NodeLocator(offset, offset + length).searchWithin(unit);
-    for (AstNode n = node; n != null; n = n.parent) {
-      if (n is Directive) {
-        return n;
-      }
-    }
-    return node;
-  }
 }
 
 /**
diff --git a/pkg/analysis_server/test/analysis/get_navigation_test.dart b/pkg/analysis_server/test/analysis/get_navigation_test.dart
index 5e262a7..085659e 100644
--- a/pkg/analysis_server/test/analysis/get_navigation_test.dart
+++ b/pkg/analysis_server/test/analysis/get_navigation_test.dart
@@ -15,6 +15,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(GetNavigationTest);
+    defineReflectiveTests(GetNavigationTest_Driver);
   });
 }
 
@@ -248,3 +249,13 @@
     regions = result.regions;
   }
 }
+
+@reflectiveTest
+class GetNavigationTest_Driver extends GetNavigationTest {
+  @override
+  void setUp() {
+    enableNewAnalysisDriver = true;
+    generateSummaryFiles = true;
+    super.setUp();
+  }
+}
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index db3bf03..ded3532 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -2136,6 +2136,46 @@
     expect(lints[0].name, 'camel_case_types');
   }
 
+  test_analysis_options_include_package() async {
+    // Create files.
+    String libPath = newFolder([projPath, ContextManagerTest.LIB_NAME]);
+    newFile([libPath, 'main.dart']);
+    String sdkExtPath = newFolder([projPath, 'sdk_ext']);
+    newFile([sdkExtPath, 'entry.dart']);
+    String sdkExtSrcPath = newFolder([projPath, 'sdk_ext', 'src']);
+    newFile([sdkExtSrcPath, 'part.dart']);
+    // Setup package
+    String booLibPosixPath = '/my/pkg/boo/lib';
+    newFile(
+        [booLibPosixPath, 'other_options.yaml'],
+        r'''
+analyzer:
+  language:
+    enableStrictCallChecks: true
+  errors:
+    unused_local_variable: false
+linter:
+  rules:
+    - camel_case_types
+''');
+    // Setup analysis options file which includes another options file.
+    newFile([projPath, ContextManagerImpl.PACKAGE_SPEC_NAME],
+        'boo:$booLibPosixPath\n');
+    newFile(
+        [projPath, optionsFileName],
+        r'''
+include: package:boo/other_options.yaml
+''');
+    // Setup context.
+    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
+    await pumpEventQueue();
+    // Verify options were set.
+    expect(analysisOptions.enableStrictCallChecks, isTrue);
+    expect(errorProcessors, hasLength(1));
+    expect(lints, hasLength(1));
+    expect(lints[0].name, 'camel_case_types');
+  }
+
   test_analysis_options_parse_failure() async {
     // Create files.
     String libPath = newFolder([projPath, ContextManagerTest.LIB_NAME]);
diff --git a/pkg/analyzer/lib/src/command_line/arguments.dart b/pkg/analyzer/lib/src/command_line/arguments.dart
index f85a34e..5ea958e 100644
--- a/pkg/analyzer/lib/src/command_line/arguments.dart
+++ b/pkg/analyzer/lib/src/command_line/arguments.dart
@@ -103,25 +103,46 @@
  * Add the standard flags and options to the given [parser]. The standard flags
  * are those that are typically used to control the way in which the code is
  * analyzed.
+ *
+ * TODO(danrubel) Update DDC to support all the options defined in this method
+ * then remove the [ddc] named argument from this method.
  */
-void defineAnalysisArguments(ArgParser parser, {bool hide: true}) {
-  defineDDCAnalysisArguments(parser, hide: hide);
+void defineAnalysisArguments(ArgParser parser, {bool hide: true, ddc: false}) {
+  parser.addOption(defineVariableOption,
+      abbr: 'D',
+      allowMultiple: true,
+      help: 'Define environment variables. For example, "-Dfoo=bar" defines an '
+          'environment variable named "foo" whose value is "bar".');
+
+  parser.addOption(sdkPathOption, help: 'The path to the Dart SDK.');
+  parser.addOption(sdkSummaryPathOption,
+      help: 'The path to the Dart SDK summary file.', hide: hide);
 
   parser.addOption(analysisOptionsFileOption,
-      help: 'Path to an analysis options file.');
+      help: 'Path to an analysis options file.', hide: ddc);
+
+  parser.addOption(packageRootOption,
+      abbr: 'p',
+      help: 'The path to a package root directory (deprecated). '
+          'This option cannot be used with --packages.');
   parser.addOption(packagesOption,
       help: 'The path to the package resolution configuration file, which '
           'supplies a mapping of package names to paths. This option cannot be '
-          'used with --package-root.');
+          'used with --package-root.',
+      hide: ddc);
 
   parser.addFlag(strongModeFlag,
-      help: 'Enable strong static checks (https://goo.gl/DqcBsw)');
+      help: 'Enable strong static checks (https://goo.gl/DqcBsw)',
+      defaultsTo: ddc,
+      hide: ddc);
   parser.addFlag(noImplicitCastsFlag,
       negatable: false,
-      help: 'Disable implicit casts in strong mode (https://goo.gl/cTLz40)');
+      help: 'Disable implicit casts in strong mode (https://goo.gl/cTLz40)',
+      hide: ddc);
   parser.addFlag(noImplicitDynamicFlag,
       negatable: false,
-      help: 'Disable implicit dynamic (https://goo.gl/m0UgXD)');
+      help: 'Disable implicit dynamic (https://goo.gl/m0UgXD)',
+      hide: ddc);
   //
   // Hidden flags and options.
   //
@@ -129,51 +150,29 @@
 //      help: 'Enable support for null-aware operators (DEP 9).',
 //      defaultsTo: false,
 //      negatable: false,
-//      hide: hide);
+//      hide: hide || ddc);
   parser.addFlag(enableStrictCallChecksFlag,
       help: 'Fix issue 21938.',
       defaultsTo: false,
       negatable: false,
-      hide: hide);
+      hide: hide || ddc);
   parser.addFlag(enableInitializingFormalAccessFlag,
       help:
           'Enable support for allowing access to field formal parameters in a '
           'constructor\'s initializer list',
       defaultsTo: false,
       negatable: false,
-      hide: hide);
+      hide: hide || ddc);
   parser.addFlag(enableSuperInMixinFlag,
       help: 'Relax restrictions on mixins (DEP 34).',
       defaultsTo: false,
       negatable: false,
-      hide: hide);
+      hide: hide || ddc);
 //  parser.addFlag('enable_type_checks',
 //      help: 'Check types in constant evaluation.',
 //      defaultsTo: false,
 //      negatable: false,
-//      hide: hide);
-}
-
-/**
- * Add the DDC analysis flags and options to the given [parser].
- *
- * TODO(danrubel) Update DDC to support all the options defined in
- * the [defineAnalysisOptions] method above, then have DDC call that method
- * and remove this method.
- */
-void defineDDCAnalysisArguments(ArgParser parser, {bool hide: true}) {
-  parser.addOption(defineVariableOption,
-      abbr: 'D',
-      allowMultiple: true,
-      help: 'Define environment variables. For example, "-Dfoo=bar" defines an '
-          'environment variable named "foo" whose value is "bar".');
-  parser.addOption(sdkPathOption, help: 'The path to the Dart SDK.');
-  parser.addOption(sdkSummaryPathOption,
-      help: 'The path to the Dart SDK summary file.', hide: hide);
-  parser.addOption(packageRootOption,
-      abbr: 'p',
-      help: 'The path to a package root directory (deprecated). '
-          'This option cannot be used with --packages.');
+//      hide: hide || ddc);
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index a6bb7fa..ef28cb2 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -30,6 +30,7 @@
 import 'package:analyzer/src/summary/package_bundle_reader.dart';
 import 'package:analyzer/src/task/dart.dart' show COMPILATION_UNIT_ELEMENT;
 import 'package:analyzer/task/dart.dart' show LibrarySpecificUnit;
+import 'package:meta/meta.dart';
 
 /**
  * This class computes [AnalysisResult]s for Dart files.
@@ -219,6 +220,8 @@
    */
   Search _search;
 
+  AnalysisDriverTestView _testView;
+
   /**
    * Create a new instance of [AnalysisDriver].
    *
@@ -234,6 +237,7 @@
       SourceFactory sourceFactory,
       this._analysisOptions)
       : _sourceFactory = sourceFactory.clone() {
+    _testView = new AnalysisDriverTestView(this);
     _fillSalt();
     _sdkBundle = sourceFactory.dartSdk.getLinkedBundle();
     _fsState = new FileSystemState(
@@ -348,6 +352,9 @@
    */
   Stream<AnalysisStatus> get status => _statusSupport.stream;
 
+  @visibleForTesting
+  AnalysisDriverTestView get test => _testView;
+
   /**
    * Return the priority of work that the driver needs to perform.
    */
@@ -841,6 +848,7 @@
         _sourceFactory,
         file.path,
         file.uri,
+        file.exists,
         content,
         file.contentHash,
         file.lineInfo,
@@ -907,7 +915,11 @@
     // Verify all changed files one at a time.
     if (_changedFiles.isNotEmpty) {
       String path = _removeFirst(_changedFiles);
-      _verifyApiSignature(path);
+      // If the file has not been accessed yet, we either will eventually read
+      // it later while analyzing one of the added files, or don't need it.
+      if (_fsState.knownFilePaths.contains(path)) {
+        _verifyApiSignature(path);
+      }
       return;
     }
 
@@ -1256,6 +1268,15 @@
   }
 }
 
+@visibleForTesting
+class AnalysisDriverTestView {
+  final AnalysisDriver driver;
+
+  AnalysisDriverTestView(this.driver);
+
+  Set<String> get filesToAnalyze => driver._filesToAnalyze;
+}
+
 /**
  * The result of analyzing of a single file.
  *
@@ -1291,6 +1312,11 @@
   final Uri uri;
 
   /**
+   * Return `true` if the file exists.
+   */
+  final bool exists;
+
+  /**
    * The content of the file that was scanned, parsed and resolved.
    */
   final String content;
@@ -1325,6 +1351,7 @@
       this.sourceFactory,
       this.path,
       this.uri,
+      this.exists,
       this.content,
       this.contentHash,
       this.lineInfo,
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 04e2fe9..0bc2d9a 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -362,6 +362,9 @@
     provider.updateFile(b, 'var B = 1.2;');
     driver.changeFile(b);
 
+    // "b" is not an added file, so it is not scheduled for analysis.
+    expect(driver.test.filesToAnalyze, isEmpty);
+
     // While "b" is not analyzed explicitly, it is analyzed implicitly.
     // The change causes "a" to be reanalyzed.
     await _waitForIdle();
@@ -372,6 +375,28 @@
     }
   }
 
+  test_changeFile_notUsed() async {
+    var a = _p('/test/lib/a.dart');
+    var b = _p('/other/b.dart');
+    provider.newFile(a, '');
+    provider.newFile(b, 'class B1 {}');
+
+    driver.addFile(a);
+
+    await _waitForIdle();
+    allResults.clear();
+
+    // Change "b" and notify.
+    // Nothing depends on "b", so nothing is analyzed.
+    provider.updateFile(b, 'class B2 {}');
+    driver.changeFile(b);
+    await _waitForIdle();
+    expect(allResults, isEmpty);
+
+    // This should not add "b" to the file state.
+    expect(driver.fsState.knownFilePaths, isNot(contains(b)));
+  }
+
   test_changeFile_selfConsistent() async {
     var a = _p('/test/lib/a.dart');
     var b = _p('/test/lib/b.dart');
@@ -455,6 +480,9 @@
     // Notify the driver about the change.
     driver.changeFile(testFile);
 
+    // The file was added, so it is scheduled for analysis.
+    expect(driver.test.filesToAnalyze, contains(testFile));
+
     // We get a new result.
     {
       await _waitForIdle();
@@ -570,6 +598,7 @@
     AnalysisResult result = await driver.getResult(testFile);
     expect(result.path, testFile);
     expect(result.uri.toString(), 'package:test/test.dart');
+    expect(result.exists, isTrue);
     expect(result.content, content);
     expect(result.contentHash, _md5(content));
     expect(result.unit, isNotNull);
@@ -605,6 +634,16 @@
     expect(result.errors, isEmpty);
   }
 
+  test_getResult_doesNotExist() async {
+    var a = _p('/test/lib/a.dart');
+
+    AnalysisResult result = await driver.getResult(a);
+    expect(result.path, a);
+    expect(result.uri.toString(), 'package:test/a.dart');
+    expect(result.exists, isFalse);
+    expect(result.content, '');
+  }
+
   test_getResult_errors() async {
     String content = 'main() { int vv; }';
     addTestFile(content, priority: true);
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index 2b75a64..c83cffc 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -8,6 +8,7 @@
 
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/src/command_line/arguments.dart';
+import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer_cli/src/driver.dart';
 import 'package:args/args.dart';
 import 'package:cli_util/cli_util.dart' show getSdkDir;
@@ -32,9 +33,6 @@
 
 /// Analyzer commandline configuration options.
 class CommandLineOptions {
-  /// The path to an analysis options file
-  final String analysisOptionsFile;
-
   /// The path to output analysis results when in build mode.
   final String buildAnalysisOutput;
 
@@ -67,15 +65,15 @@
   /// Whether to suppress a nonzero exit code in build mode.
   final bool buildSuppressExitCode;
 
+  /// The options defining the context in which analysis is performed.
+  final ContextBuilderOptions contextBuilderOptions;
+
   /// The path to the dart SDK.
   String dartSdkPath;
 
   /// The path to the dart SDK summary file.
   String dartSdkSummaryPath;
 
-  /// A table mapping the names of defined variables to their values.
-  final Map<String, String> definedVariables;
-
   /// Whether to disable cache flushing.  This option can improve analysis
   /// speed at the expense of memory usage.  It may also be useful for working
   /// around bugs.
@@ -90,13 +88,6 @@
   /// Whether to enable null-aware operators (DEP 9).
   final bool enableNullAwareOperators;
 
-  /// Whether to strictly follow the specification when generating warnings on
-  /// "call" methods (fixes dartbug.com/21938).
-  final bool enableStrictCallChecks;
-
-  /// Whether to relax restrictions on mixins (DEP 34).
-  final bool enableSuperMixins;
-
   /// Whether to treat type mismatches found during constant evaluation as
   /// errors.
   final bool enableTypeChecks;
@@ -116,12 +107,6 @@
   /// Whether to use machine format for error display
   final bool machineFormat;
 
-  /// The path to the package root
-  final String packageRootPath;
-
-  /// The path to a `.packages` configuration file
-  final String packageConfigPath;
-
   /// The path to a file to write a performance log.
   /// (Or null if not enabled.)
   final String perfReport;
@@ -157,8 +142,7 @@
   final bool lintsAreFatal;
 
   /// Initialize options from the given parsed [args].
-  CommandLineOptions._fromArgs(
-      ArgResults args, Map<String, String> definedVariables)
+  CommandLineOptions._fromArgs(ArgResults args)
       : buildAnalysisOutput = args['build-analysis-output'],
         buildMode = args['build-mode'],
         buildModePersistentWorker = args['persistent_worker'],
@@ -170,24 +154,19 @@
         buildSummaryOutput = args['build-summary-output'],
         buildSummaryOutputSemantic = args['build-summary-output-semantic'],
         buildSuppressExitCode = args['build-suppress-exit-code'],
+        contextBuilderOptions = createContextBuilderOptions(args),
         dartSdkPath = args['dart-sdk'],
         dartSdkSummaryPath = args['dart-sdk-summary'],
-        definedVariables = definedVariables,
-        analysisOptionsFile = args['options'],
         disableCacheFlushing = args['disable-cache-flushing'],
         disableHints = args['no-hints'],
         displayVersion = args['version'],
         enableNullAwareOperators = args['enable-null-aware-operators'],
-        enableStrictCallChecks = args['enable-strict-call-checks'],
-        enableSuperMixins = args['supermixin'],
         enableTypeChecks = args['enable_type_checks'],
         hintsAreFatal = args['fatal-hints'],
         ignoreUnrecognizedFlags = args['ignore-unrecognized-flags'],
         lints = args['lints'],
         log = args['log'],
         machineFormat = args['machine'] || args['format'] == 'machine',
-        packageConfigPath = args['packages'],
-        packageRootPath = args['package-root'],
         perfReport = args['x-perf-report'],
         shouldBatch = args['batch'],
         showPackageWarnings = args['show-package-warnings'] ||
@@ -202,6 +181,30 @@
         implicitDynamic = !args['no-implicit-dynamic'],
         lintsAreFatal = args['fatal-lints'];
 
+  /// The path to an analysis options file
+  String get analysisOptionsFile =>
+      contextBuilderOptions.defaultAnalysisOptionsFilePath;
+
+  /// A table mapping the names of defined variables to their values.
+  Map<String, String> get definedVariables =>
+      contextBuilderOptions.declaredVariables;
+
+  /// Whether to strictly follow the specification when generating warnings on
+  /// "call" methods (fixes dartbug.com/21938).
+  bool get enableStrictCallChecks =>
+      contextBuilderOptions.defaultOptions.enableStrictCallChecks;
+
+  /// Whether to relax restrictions on mixins (DEP 34).
+  bool get enableSuperMixins =>
+      contextBuilderOptions.defaultOptions.enableSuperMixins;
+
+  /// The path to the package root
+  String get packageRootPath =>
+      contextBuilderOptions.defaultPackagesDirectoryPath;
+
+  /// The path to a `.packages` configuration file
+  String get packageConfigPath => contextBuilderOptions.defaultPackageFilePath;
+
   /// Parse [args] into [CommandLineOptions] describing the specified
   /// analyzer options. In case of a format error, calls [printAndFail], which
   /// by default prints an error message to stderr and exits.
@@ -454,8 +457,6 @@
       // TODO(scheglov) https://code.google.com/p/dart/issues/detail?id=11061
       args =
           args.map((String arg) => arg == '-batch' ? '--batch' : arg).toList();
-      Map<String, String> definedVariables = <String, String>{};
-      args = extractDefinedVariables(args, definedVariables);
       if (args.contains('--$ignoreUnrecognizedFlagsFlag')) {
         args = filterUnknownArguments(args, parser);
       }
@@ -479,7 +480,7 @@
               'option. Got: $args');
           return null; // Only reachable in testing.
         }
-        return new CommandLineOptions._fromArgs(results, definedVariables);
+        return new CommandLineOptions._fromArgs(results);
       }
 
       // Help requests.
@@ -515,7 +516,7 @@
           return null; // Only reachable in testing.
         }
       }
-      return new CommandLineOptions._fromArgs(results, definedVariables);
+      return new CommandLineOptions._fromArgs(results);
     } on FormatException catch (e) {
       errorSink.writeln(e.message);
       _showUsage(parser);
diff --git a/pkg/analyzer_cli/test/options_test.dart b/pkg/analyzer_cli/test/options_test.dart
index 0a34dfc..c0ca301 100644
--- a/pkg/analyzer_cli/test/options_test.dart
+++ b/pkg/analyzer_cli/test/options_test.dart
@@ -55,11 +55,9 @@
 
       test('defined variables', () {
         CommandLineOptions options = CommandLineOptions
-            .parse(['--dart-sdk', '.', '-Dfoo=bar', '-Da', 'b', 'foo.dart']);
+            .parse(['--dart-sdk', '.', '-Dfoo=bar', 'foo.dart']);
         expect(options.definedVariables['foo'], equals('bar'));
         expect(options.definedVariables['bar'], isNull);
-        expect(options.definedVariables['a'], equals('b'));
-        expect(options.definedVariables['b'], isNull);
       });
 
       test('disable cache flushing', () {
diff --git a/pkg/compiler/lib/src/common/backend_api.dart b/pkg/compiler/lib/src/common/backend_api.dart
index aef574d..e0c396c 100644
--- a/pkg/compiler/lib/src/common/backend_api.dart
+++ b/pkg/compiler/lib/src/common/backend_api.dart
@@ -103,7 +103,7 @@
   }
 
   /// Generates the output and returns the total size of the generated code.
-  int assembleProgram();
+  int assembleProgram(ClosedWorld closedWorld);
 
   List<CompilerTask> get tasks;
 
@@ -311,7 +311,10 @@
 
   /// Called when the compiler starts running the codegen enqueuer. The
   /// [WorldImpact] of enabled backend features is returned.
-  WorldImpact onCodegenStart() => const WorldImpact();
+  WorldImpact onCodegenStart(ClosedWorld closedWorld) => const WorldImpact();
+
+  /// Called when code generation has been completed.
+  void onCodegenEnd() {}
 
   // Does this element belong in the output
   bool shouldOutput(Element element) => true;
@@ -418,6 +421,7 @@
   ClassElement get indexableImplementation;
   ClassElement get mutableIndexableImplementation;
   ClassElement get indexingBehaviorImplementation;
+  ClassElement get interceptorImplementation;
 
   bool isDefaultEqualityImplementation(Element element);
   bool isInterceptorClass(ClassElement cls);
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index d3e98c0..07d9c89 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -78,7 +78,7 @@
         WorldImpactBuilder,
         WorldImpactBuilderImpl;
 import 'util/util.dart' show Link, Setlet;
-import 'world.dart' show ClosedWorld, ClosedWorldRefiner, OpenWorld, WorldImpl;
+import 'world.dart' show ClosedWorld, ClosedWorldRefiner, WorldImpl;
 
 typedef Backend MakeBackendFuncion(Compiler compiler);
 
@@ -89,7 +89,6 @@
   Measurer get measurer;
 
   final IdGenerator idGenerator = new IdGenerator();
-  WorldImpl get _world => resolverWorld.openWorld;
   Types types;
   _CompilerCoreTypes _coreTypes;
   CompilerDiagnosticReporter _reporter;
@@ -130,8 +129,6 @@
 
   ResolvedUriTranslator get resolvedUriTranslator;
 
-  Tracer tracer;
-
   LibraryElement mainApp;
   FunctionElement mainFunction;
 
@@ -217,7 +214,6 @@
     // make its field final.
     _coreTypes = new _CompilerCoreTypes(_resolution, reporter);
     types = new Types(_resolution);
-    tracer = new Tracer(this, this.outputProvider);
 
     if (options.verbose) {
       progress = new Stopwatch()..start();
@@ -279,13 +275,6 @@
     tasks.addAll(backend.tasks);
   }
 
-  /// The closed world after resolution and inference.
-  ClosedWorld get closedWorld {
-    assert(invariant(CURRENT_ELEMENT_SPANNABLE, _world.isClosed,
-        message: "Closed world not computed yet."));
-    return _world;
-  }
-
   /// Creates the backend.
   ///
   /// Override this to mock the backend for testing.
@@ -344,7 +333,6 @@
         return new Future.sync(() => runInternal(uri))
             .catchError((error) => _reporter.onError(uri, error))
             .whenComplete(() {
-          tracer.close();
           measurer.stopWallClock();
         }).then((_) {
           return !compilationFailed;
@@ -708,6 +696,9 @@
         assert(mainFunction != null);
 
         ClosedWorldRefiner closedWorldRefiner = closeResolution();
+        // TODO(johnniwinther): Make [ClosedWorld] a property of
+        // [ClosedWorldRefiner].
+        ClosedWorld closedWorld = resolverWorld.closedWorldForTesting;
 
         reporter.log('Inferring types...');
         globalInference.runGlobalTypeInference(
@@ -720,7 +711,7 @@
         reporter.log('Compiling...');
         phase = PHASE_COMPILING;
 
-        enqueuer.codegen.applyImpact(backend.onCodegenStart());
+        enqueuer.codegen.applyImpact(backend.onCodegenStart(closedWorld));
         if (compileAll) {
           libraryLoader.libraries.forEach((LibraryElement library) {
             enqueuer.codegen.applyImpact(computeImpactForLibrary(library));
@@ -730,14 +721,14 @@
             onProgress: showCodegenProgress);
         enqueuer.codegen.logSummary(reporter.log);
 
-        int programSize = backend.assembleProgram();
+        int programSize = backend.assembleProgram(closedWorld);
 
         if (options.dumpInfo) {
           dumpInfoTask.reportSize(programSize);
           dumpInfoTask.dumpInfo(closedWorld);
         }
 
-        backend.sourceInformationStrategy.onComplete();
+        backend.onCodegenEnd();
 
         checkQueues();
       });
diff --git a/pkg/compiler/lib/src/elements/elements.dart b/pkg/compiler/lib/src/elements/elements.dart
index 9fef687..95acc7b 100644
--- a/pkg/compiler/lib/src/elements/elements.dart
+++ b/pkg/compiler/lib/src/elements/elements.dart
@@ -1664,7 +1664,7 @@
 abstract class JumpTarget extends Local {
   Node get statement;
   int get nestingLevel;
-  Link<LabelDefinition> get labels;
+  List<LabelDefinition> get labels;
 
   bool get isTarget;
   bool get isBreakTarget;
diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
index b479367..c2d2e75 100644
--- a/pkg/compiler/lib/src/elements/modelx.dart
+++ b/pkg/compiler/lib/src/elements/modelx.dart
@@ -3209,7 +3209,7 @@
   final ExecutableElement executableContext;
   final Node statement;
   final int nestingLevel;
-  Link<LabelDefinition> labels = const Link<LabelDefinition>();
+  List<LabelDefinition> labels = <LabelDefinition>[];
   bool isBreakTarget = false;
   bool isContinueTarget = false;
 
@@ -3223,7 +3223,7 @@
 
   LabelDefinition addLabel(Label label, String labelName) {
     LabelDefinition result = new LabelDefinitionX(label, labelName, this);
-    labels = labels.prepend(result);
+    labels.add(result);
     return result;
   }
 
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
index 6a5d7f7..ef9fbfa 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
@@ -862,7 +862,7 @@
     // The JavaScript backend may turn this literal into an integer at
     // runtime.
     return types.getConcreteTypeFor(
-        computeTypeMask(compiler, constantSystem.createDouble(node.value)));
+        computeTypeMask(closedWorld, constantSystem.createDouble(node.value)));
   }
 
   T visitLiteralInt(LiteralInt node) {
@@ -870,7 +870,7 @@
     // The JavaScript backend may turn this literal into a double at
     // runtime.
     return types.getConcreteTypeFor(
-        computeTypeMask(compiler, constantSystem.createInt(node.value)));
+        computeTypeMask(closedWorld, constantSystem.createInt(node.value)));
   }
 
   T visitLiteralList(LiteralList node) {
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
index 1ac65fc..332e256 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
@@ -863,7 +863,7 @@
                   // Although we might find a better type, we have to keep
                   // the old type around to ensure that we get a complete view
                   // of the type graph and do not drop any flow edges.
-                  TypeMask refinedType = computeTypeMask(compiler, value);
+                  TypeMask refinedType = computeTypeMask(closedWorld, value);
                   assert(TypeMask.assertIsNormalized(refinedType, closedWorld));
                   type = new NarrowTypeInformation(type, refinedType);
                   types.allocatedTypes.add(type);
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index f5018bf..fe066c7 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -45,6 +45,7 @@
 import '../library_loader.dart' show LibraryLoader, LoadedLibraries;
 import '../native/native.dart' as native;
 import '../ssa/ssa.dart' show SsaFunctionCompiler;
+import '../tracer.dart';
 import '../tree/tree.dart';
 import '../types/types.dart';
 import '../universe/call_structure.dart' show CallStructure;
@@ -88,7 +89,7 @@
 
 abstract class FunctionCompiler {
   /// Generates JavaScript code for `work.element`.
-  jsAst.Fun compile(CodegenWorkItem work);
+  jsAst.Fun compile(CodegenWorkItem work, ClosedWorld closedWorld);
 
   Iterable get tasks;
 }
@@ -305,7 +306,7 @@
 class JavaScriptBackend extends Backend {
   String get patchVersion => emitter.patchVersion;
 
-  bool get supportsReflection => emitter.emitter.supportsReflection;
+  bool get supportsReflection => emitter.supportsReflection;
 
   final Annotations annotations;
 
@@ -343,7 +344,13 @@
   bool needToInitializeIsolateAffinityTag = false;
   bool needToInitializeDispatchProperty = false;
 
-  final Namer namer;
+  Namer _namer;
+
+  Namer get namer {
+    assert(invariant(NO_LOCATION_SPANNABLE, _namer != null,
+        message: "Namer has not been created yet."));
+    return _namer;
+  }
 
   /**
    * A collection of selectors that must have a one shot interceptor
@@ -553,13 +560,14 @@
 
   final JSFrontendAccess frontend;
 
+  Tracer tracer;
+
   JavaScriptBackend(Compiler compiler,
       {bool generateSourceMap: true,
       bool useStartupEmitter: false,
       bool useNewSourceInfo: false,
       bool useKernel: false})
-      : namer = determineNamer(compiler),
-        oneShotInterceptors = new Map<jsAst.Name, Selector>(),
+      : oneShotInterceptors = new Map<jsAst.Name, Selector>(),
         interceptedElements = new Map<String, Set<Element>>(),
         rti = new _RuntimeTypes(compiler),
         rtiEncoder = new _RuntimeTypesEncoder(compiler),
@@ -574,8 +582,8 @@
         impacts = new BackendImpacts(compiler),
         frontend = new JSFrontendAccess(compiler),
         super(compiler) {
-    emitter = new CodeEmitterTask(
-        compiler, namer, generateSourceMap, useStartupEmitter);
+    emitter =
+        new CodeEmitterTask(compiler, generateSourceMap, useStartupEmitter);
     typeVariableHandler = new TypeVariableHandler(compiler);
     customElementsAnalysis = new CustomElementsAnalysis(this);
     lookupMapAnalysis = new LookupMapAnalysis(this, reporter);
@@ -640,12 +648,12 @@
         library == helpers.jsHelperLibrary;
   }
 
-  static Namer determineNamer(Compiler compiler) {
+  Namer determineNamer(ClosedWorld closedWorld) {
     return compiler.options.enableMinification
         ? compiler.options.useFrequencyNamer
-            ? new FrequencyBasedNamer(compiler)
-            : new MinifyNamer(compiler)
-        : new Namer(compiler);
+            ? new FrequencyBasedNamer(this, closedWorld)
+            : new MinifyNamer(this, closedWorld)
+        : new Namer(this, closedWorld);
   }
 
   /// The backend must *always* call this method when enqueuing an
@@ -893,8 +901,7 @@
     if (elements.isEmpty) return false;
     return elements.any((element) {
       return selector.applies(element) &&
-          (mask == null ||
-              mask.canHit(element, selector, compiler.closedWorld));
+          (mask == null || mask.canHit(element, selector, _closedWorld));
     });
   }
 
@@ -950,11 +957,10 @@
   }
 
   Set<ClassElement> nativeSubclassesOfMixin(ClassElement mixin) {
-    ClosedWorld closedWorld = compiler.closedWorld;
-    Iterable<MixinApplicationElement> uses = closedWorld.mixinUsesOf(mixin);
+    Iterable<MixinApplicationElement> uses = _closedWorld.mixinUsesOf(mixin);
     Set<ClassElement> result = null;
     for (MixinApplicationElement use in uses) {
-      closedWorld.forEachStrictSubclassOf(use, (ClassElement subclass) {
+      _closedWorld.forEachStrictSubclassOf(use, (ClassElement subclass) {
         if (isNativeOrExtendsNative(subclass)) {
           if (result == null) result = new Set<ClassElement>();
           result.add(subclass);
@@ -1494,7 +1500,7 @@
       }
     }
 
-    jsAst.Fun function = functionCompiler.compile(work);
+    jsAst.Fun function = functionCompiler.compile(work, _closedWorld);
     if (function.sourceInformation == null) {
       function = function.withSourceInformation(
           sourceInformationStrategy.buildSourceMappedMarker());
@@ -1534,8 +1540,8 @@
     return jsAst.prettyPrint(generatedCode[element], compiler);
   }
 
-  int assembleProgram() {
-    int programSize = emitter.assembleProgram();
+  int assembleProgram(ClosedWorld closedWorld) {
+    int programSize = emitter.assembleProgram(namer, closedWorld);
     noSuchMethodRegistry.emitDiagnostic();
     int totalMethodCount = generatedCode.length;
     if (totalMethodCount != preMirrorsMethodCount) {
@@ -1747,7 +1753,7 @@
     if (!type.isRaw) return false;
     ClassElement classElement = type.element;
     if (isInterceptorClass(classElement)) return false;
-    return compiler.closedWorld.hasOnlySubclasses(classElement);
+    return _closedWorld.hasOnlySubclasses(classElement);
   }
 
   WorldImpact registerUsedElement(Element element, {bool forResolution}) {
@@ -2357,7 +2363,24 @@
     jsInteropAnalysis.onQueueClosed();
   }
 
-  WorldImpact onCodegenStart() {
+  // TODO(johnniwinther): Create a CodegenPhase object for the backend to hold
+  // data only available during code generation.
+  ClosedWorld _closedWorldCache;
+  ClosedWorld get _closedWorld {
+    assert(invariant(NO_LOCATION_SPANNABLE, _closedWorldCache != null,
+        message: "ClosedWorld has not be set yet."));
+    return _closedWorldCache;
+  }
+
+  void set _closedWorld(ClosedWorld value) {
+    _closedWorldCache = value;
+  }
+
+  WorldImpact onCodegenStart(ClosedWorld closedWorld) {
+    _closedWorld = closedWorld;
+    _namer = determineNamer(_closedWorld);
+    tracer = new Tracer(_closedWorld, namer, compiler.outputProvider);
+    emitter.createEmitter(_namer, _closedWorld);
     lookupMapAnalysis.onCodegenStart();
     if (hasIsolateSupport) {
       return enableIsolateSupport(forResolution: false);
@@ -2365,6 +2388,11 @@
     return const WorldImpact();
   }
 
+  void onCodegenEnd() {
+    sourceInformationStrategy.onComplete();
+    tracer.close();
+  }
+
   /// Process backend specific annotations.
   void processAnnotations(
       Element element, ClosedWorldRefiner closedWorldRefiner) {
@@ -3206,6 +3234,7 @@
       helpers.jsMutableIndexableClass;
   ClassElement get indexingBehaviorImplementation =>
       helpers.jsIndexingBehaviorInterface;
+  ClassElement get interceptorImplementation => helpers.jsInterceptorClass;
 
   bool isDefaultEqualityImplementation(Element element) {
     assert(element.name == '==');
diff --git a/pkg/compiler/lib/src/js_backend/enqueuer.dart b/pkg/compiler/lib/src/js_backend/enqueuer.dart
index 4784df0..da79b0e 100644
--- a/pkg/compiler/lib/src/js_backend/enqueuer.dart
+++ b/pkg/compiler/lib/src/js_backend/enqueuer.dart
@@ -86,7 +86,8 @@
   CodegenWorldBuilder get universe => _universe;
 
   // TODO(johnniwinther): Remove these hacks:
-  ClosedWorld get _world => _backend.compiler.closedWorld;
+  ClosedWorld get _world =>
+      _backend.compiler.resolverWorld.closedWorldForTesting;
   DumpInfoTask get _dumpInfoTask => _backend.compiler.dumpInfoTask;
 
   bool get queueIsEmpty => _queue.isEmpty;
diff --git a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
index b5e3c71..d7a3ca9 100644
--- a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
+++ b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
@@ -24,8 +24,7 @@
       names = new _FieldNamingScope.forBox(element.box, fieldRegistry);
     } else {
       ClassElement cls = element.enclosingClass;
-      names = new _FieldNamingScope.forClass(
-          cls, compiler.closedWorld, fieldRegistry);
+      names = new _FieldNamingScope.forClass(cls, closedWorld, fieldRegistry);
     }
 
     if (names.containsField(element)) {
diff --git a/pkg/compiler/lib/src/js_backend/frequency_namer.dart b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
index 9636e67..0d4157b 100644
--- a/pkg/compiler/lib/src/js_backend/frequency_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
@@ -25,7 +25,8 @@
   jsAst.Name get staticsPropertyName =>
       _staticsPropertyName ??= getFreshName(instanceScope, 'static');
 
-  FrequencyBasedNamer(Compiler compiler) : super(compiler) {
+  FrequencyBasedNamer(JavaScriptBackend backend, ClosedWorld closedWorld)
+      : super(backend, closedWorld) {
     fieldRegistry = new _FieldNamingRegistry(this);
   }
 
diff --git a/pkg/compiler/lib/src/js_backend/minify_namer.dart b/pkg/compiler/lib/src/js_backend/minify_namer.dart
index 3e689d4..10504c4 100644
--- a/pkg/compiler/lib/src/js_backend/minify_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/minify_namer.dart
@@ -12,7 +12,8 @@
         _MinifiedFieldNamer,
         _MinifyConstructorBodyNamer,
         _MinifiedOneShotInterceptorNamer {
-  MinifyNamer(Compiler compiler) : super(compiler) {
+  MinifyNamer(JavaScriptBackend backend, ClosedWorld closedWorld)
+      : super(backend, closedWorld) {
     reserveBackendNames();
     fieldRegistry = new _FieldNamingRegistry(this);
   }
diff --git a/pkg/compiler/lib/src/js_backend/mirrors_analysis.dart b/pkg/compiler/lib/src/js_backend/mirrors_analysis.dart
index 5207421..e7be92d 100644
--- a/pkg/compiler/lib/src/js_backend/mirrors_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/mirrors_analysis.dart
@@ -82,7 +82,7 @@
     return includedEnclosing || _backend.requiredByMirrorSystem(element);
   }
 
-  /// Enqeue the constructor [ctor] if it is required for reflection.
+  /// Enqueue the constructor [ctor] if it is required for reflection.
   ///
   /// [enclosingWasIncluded] provides a hint whether the enclosing element was
   /// needed for reflection.
@@ -99,7 +99,7 @@
     }
   }
 
-  /// Enqeue the member [element] if it is required for reflection.
+  /// Enqueue the member [element] if it is required for reflection.
   ///
   /// [enclosingWasIncluded] provides a hint whether the enclosing element was
   /// needed for reflection.
@@ -131,7 +131,7 @@
     }
   }
 
-  /// Enqeue the member [element] if it is required for reflection.
+  /// Enqueue the member [element] if it is required for reflection.
   ///
   /// [enclosingWasIncluded] provides a hint whether the enclosing element was
   /// needed for reflection.
@@ -163,7 +163,7 @@
     }
   }
 
-  /// Enqeue special classes that might not be visible by normal means or that
+  /// Enqueue special classes that might not be visible by normal means or that
   /// would not normally be enqueued:
   ///
   /// [Closure] is treated specially as it is the superclass of all closures.
@@ -182,7 +182,7 @@
     }
   }
 
-  /// Enqeue all local members of the library [lib] if they are required for
+  /// Enqueue all local members of the library [lib] if they are required for
   /// reflection.
   void _enqueueReflectiveElementsInLibrary(
       LibraryElement lib, Iterable<ClassEntity> recents) {
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index e0511a3..c03056a 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -402,7 +402,8 @@
   static final RegExp IDENTIFIER = new RegExp(r'^[A-Za-z_$][A-Za-z0-9_$]*$');
   static final RegExp NON_IDENTIFIER_CHAR = new RegExp(r'[^A-Za-z_0-9$]');
 
-  final Compiler compiler;
+  final JavaScriptBackend backend;
+  final ClosedWorld closedWorld;
 
   /// Used disambiguated names in the global namespace, issued by
   /// [_disambiguateGlobal], and [_disambiguateInternalGlobal].
@@ -459,23 +460,22 @@
   final Map<LibraryElement, String> _libraryKeys =
       new HashMap<LibraryElement, String>();
 
-  Namer(Compiler compiler)
-      : compiler = compiler,
-        constantHasher = new ConstantCanonicalHasher(compiler),
-        functionTypeNamer = new FunctionTypeNamer(compiler) {
+  Namer(JavaScriptBackend backend, this.closedWorld)
+      : this.backend = backend,
+        constantHasher =
+            new ConstantCanonicalHasher(backend.rtiEncoder, backend.reporter),
+        functionTypeNamer = new FunctionTypeNamer(backend.rtiEncoder) {
     _literalAsyncPrefix = new StringBackedName(asyncPrefix);
     _literalGetterPrefix = new StringBackedName(getterPrefix);
     _literalSetterPrefix = new StringBackedName(setterPrefix);
     _literalLazyGetterPrefix = new StringBackedName(lazyGetterPrefix);
   }
 
-  JavaScriptBackend get backend => compiler.backend;
-
   BackendHelpers get helpers => backend.helpers;
 
-  DiagnosticReporter get reporter => compiler.reporter;
+  DiagnosticReporter get reporter => backend.reporter;
 
-  CoreClasses get coreClasses => compiler.coreClasses;
+  CoreClasses get coreClasses => closedWorld.coreClasses;
 
   String get deferredTypesName => 'deferredTypes';
   String get isolateName => 'Isolate';
@@ -591,8 +591,9 @@
   String constantLongName(ConstantValue constant) {
     String longName = constantLongNames[constant];
     if (longName == null) {
-      longName =
-          new ConstantNamingVisitor(compiler, constantHasher).getName(constant);
+      longName = new ConstantNamingVisitor(
+              backend.rtiEncoder, reporter, constantHasher)
+          .getName(constant);
       constantLongNames[constant] = longName;
     }
     return longName;
@@ -854,7 +855,6 @@
     // mangle the field names of classes extending native classes.
     // Methods on such classes are stored on the interceptor, not the instance,
     // so only fields have the potential to clash with a native property name.
-    ClosedWorld closedWorld = compiler.closedWorld;
     if (closedWorld.isUsedAsMixin(enclosingClass) ||
         _isShadowingSuperField(element) ||
         _isUserClassExtendingNative(enclosingClass)) {
@@ -1643,7 +1643,8 @@
   static const MAX_EXTRA_LENGTH = 30;
   static const DEFAULT_TAG_LENGTH = 3;
 
-  final Compiler compiler;
+  final RuntimeTypesEncoder rtiEncoder;
+  final DiagnosticReporter reporter;
   final ConstantCanonicalHasher hasher;
 
   String root = null; // First word, usually a type name.
@@ -1651,9 +1652,7 @@
   List<String> fragments = <String>[];
   int length = 0;
 
-  ConstantNamingVisitor(this.compiler, this.hasher);
-
-  DiagnosticReporter get reporter => compiler.reporter;
+  ConstantNamingVisitor(this.rtiEncoder, this.reporter, this.hasher);
 
   String getName(ConstantValue constant) {
     _visit(constant);
@@ -1797,8 +1796,7 @@
     String name = type.element?.name;
     if (name == null) {
       // e.g. DartType 'dynamic' has no element.
-      JavaScriptBackend backend = compiler.backend;
-      name = backend.rtiEncoder.getTypeRepresentationForTypeConstant(type);
+      name = rtiEncoder.getTypeRepresentationForTypeConstant(type);
     }
     addIdentifier(name);
     add(getHashTag(constant, 3));
@@ -1846,12 +1844,11 @@
   static const _MASK = 0x1fffffff;
   static const _UINT32_LIMIT = 4 * 1024 * 1024 * 1024;
 
-  final Compiler compiler;
+  final DiagnosticReporter reporter;
+  final RuntimeTypesEncoder rtiEncoder;
   final Map<ConstantValue, int> hashes = new Map<ConstantValue, int>();
 
-  ConstantCanonicalHasher(this.compiler);
-
-  DiagnosticReporter get reporter => compiler.reporter;
+  ConstantCanonicalHasher(this.rtiEncoder, this.reporter);
 
   int getHash(ConstantValue constant) => _visit(constant);
 
@@ -1918,9 +1915,8 @@
   @override
   int visitType(TypeConstantValue constant, [_]) {
     DartType type = constant.representedType;
-    JavaScriptBackend backend = compiler.backend;
     // This name includes the library name and type parameters.
-    String name = backend.rtiEncoder.getTypeRepresentationForTypeConstant(type);
+    String name = rtiEncoder.getTypeRepresentationForTypeConstant(type);
     return _hashString(4, name);
   }
 
@@ -2027,12 +2023,10 @@
 }
 
 class FunctionTypeNamer extends BaseDartTypeVisitor {
-  final Compiler compiler;
+  final RuntimeTypesEncoder rtiEncoder;
   StringBuffer sb;
 
-  FunctionTypeNamer(this.compiler);
-
-  JavaScriptBackend get backend => compiler.backend;
+  FunctionTypeNamer(this.rtiEncoder);
 
   String computeName(DartType type) {
     sb = new StringBuffer();
@@ -2049,7 +2043,7 @@
   }
 
   visitFunctionType(FunctionType type, _) {
-    if (backend.rtiEncoder.isSimpleFunctionType(type)) {
+    if (rtiEncoder.isSimpleFunctionType(type)) {
       sb.write('args${type.parameterTypes.length}');
       return;
     }
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 96d991a..d4e36a0 100644
--- a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
@@ -6,10 +6,14 @@
 
 class ClassStubGenerator {
   final Namer namer;
-  final Compiler compiler;
   final JavaScriptBackend backend;
+  final CodegenWorldBuilder codegenWorld;
+  final ClosedWorld closedWorld;
+  final bool enableMinification;
 
-  ClassStubGenerator(this.compiler, this.namer, this.backend);
+  ClassStubGenerator(
+      this.namer, this.backend, this.codegenWorld, this.closedWorld,
+      {this.enableMinification});
 
   jsAst.Expression generateClassConstructor(ClassElement classElement,
       Iterable<jsAst.Name> fields, bool hasRtiField) {
@@ -93,7 +97,7 @@
     for (Selector selector in selectors.keys) {
       if (generatedSelectors.contains(selector)) continue;
       if (!selector.appliesUnnamed(member)) continue;
-      if (selectors[selector].applies(member, selector, compiler.closedWorld)) {
+      if (selectors[selector].applies(member, selector, closedWorld)) {
         generatedSelectors.add(selector);
 
         jsAst.Name invocationName = namer.invocationName(selector);
@@ -126,7 +130,7 @@
     Map<jsAst.Name, Selector> jsNames = <jsAst.Name, Selector>{};
 
     // Do not generate no such method handlers if there is no class.
-    if (compiler.codegenWorld.directlyInstantiatedClasses.isEmpty) {
+    if (codegenWorld.directlyInstantiatedClasses.isEmpty) {
       return jsNames;
     }
 
@@ -134,16 +138,16 @@
         String ignore, Map<Selector, SelectorConstraints> selectors) {
       for (Selector selector in selectors.keys) {
         SelectorConstraints maskSet = selectors[selector];
-        if (maskSet.needsNoSuchMethodHandling(selector, compiler.closedWorld)) {
+        if (maskSet.needsNoSuchMethodHandling(selector, closedWorld)) {
           jsAst.Name jsName = namer.invocationMirrorInternalName(selector);
           jsNames[jsName] = selector;
         }
       }
     }
 
-    compiler.codegenWorld.forEachInvokedName(addNoSuchMethodHandlers);
-    compiler.codegenWorld.forEachInvokedGetter(addNoSuchMethodHandlers);
-    compiler.codegenWorld.forEachInvokedSetter(addNoSuchMethodHandlers);
+    codegenWorld.forEachInvokedName(addNoSuchMethodHandlers);
+    codegenWorld.forEachInvokedGetter(addNoSuchMethodHandlers);
+    codegenWorld.forEachInvokedSetter(addNoSuchMethodHandlers);
     return jsNames;
   }
 
@@ -175,8 +179,8 @@
           'noSuchMethodName': namer.noSuchMethodName,
           'createInvocationMirror': backend.emitter
               .staticFunctionAccess(backend.helpers.createInvocationMirror),
-          'methodName': js.quoteName(
-              compiler.options.enableMinification ? internalName : methodName),
+          'methodName':
+              js.quoteName(enableMinification ? internalName : methodName),
           'internalName': js.quoteName(internalName),
           'type': js.number(type),
           'arguments':
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 eabb905..9c39229 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -13,12 +13,11 @@
  * The code for the containing (used) methods must exist in the `universe`.
  */
 class CodeEmitterTask extends CompilerTask {
-  // TODO(floitsch): the code-emitter task should not need a namer.
-  final Namer namer;
-  final TypeTestRegistry typeTestRegistry;
+  TypeTestRegistry typeTestRegistry;
   NativeEmitter nativeEmitter;
   MetadataCollector metadataCollector;
-  Emitter emitter;
+  EmitterFactory _emitterFactory;
+  Emitter _emitter;
   final Compiler compiler;
 
   /// Records if a type variable is read dynamically for type tests.
@@ -34,30 +33,36 @@
   /// Contains a list of all classes that are emitted.
   Set<ClassElement> neededClasses;
 
-  CodeEmitterTask(Compiler compiler, Namer namer, bool generateSourceMap,
-      bool useStartupEmitter)
+  CodeEmitterTask(
+      Compiler compiler, bool generateSourceMap, bool useStartupEmitter)
       : compiler = compiler,
-        this.namer = namer,
-        this.typeTestRegistry = new TypeTestRegistry(compiler),
         super(compiler.measurer) {
     nativeEmitter = new NativeEmitter(this);
     if (USE_LAZY_EMITTER) {
-      emitter = new lazy_js_emitter.Emitter(compiler, namer, nativeEmitter);
+      _emitterFactory = new lazy_js_emitter.EmitterFactory();
     } else if (useStartupEmitter) {
-      emitter = new startup_js_emitter.Emitter(
-          compiler, namer, nativeEmitter, generateSourceMap);
+      _emitterFactory = new startup_js_emitter.EmitterFactory(
+          generateSourceMap: generateSourceMap);
     } else {
-      emitter =
-          new full_js_emitter.Emitter(compiler, namer, generateSourceMap, this);
+      _emitterFactory = new full_js_emitter.EmitterFactory(
+          generateSourceMap: generateSourceMap);
     }
-    metadataCollector = new MetadataCollector(compiler, emitter);
+  }
+
+  Emitter get emitter {
+    assert(invariant(NO_LOCATION_SPANNABLE, _emitter != null,
+        message: "Emitter has not been created yet."));
+    return _emitter;
   }
 
   String get name => 'Code emitter';
 
   /// Returns the string that is used to find library patches that are
   /// specialized for the emitter.
-  String get patchVersion => emitter.patchVersion;
+  String get patchVersion => _emitterFactory.patchVersion;
+
+  /// Returns true, if the emitter supports reflection.
+  bool get supportsReflection => _emitterFactory.supportsReflection;
 
   /// Returns the closure expression of a static function.
   jsAst.Expression isolateStaticClosureAccess(MethodElement element) {
@@ -138,13 +143,22 @@
     return typeTestRegistry.computeRtiNeededClasses();
   }
 
-  int assembleProgram() {
+  /// Creates the [Emitter] for this task.
+  void createEmitter(Namer namer, ClosedWorld closedWorld) {
+    measure(() {
+      _emitter = _emitterFactory.createEmitter(this, namer, closedWorld);
+      metadataCollector = new MetadataCollector(compiler, _emitter);
+      typeTestRegistry = new TypeTestRegistry(compiler, closedWorld);
+    });
+  }
+
+  int assembleProgram(Namer namer, ClosedWorld closedWorld) {
     return measure(() {
       emitter.invalidateCaches();
 
       Set<ClassElement> rtiNeededClasses = _finalizeRti();
-      ProgramBuilder programBuilder =
-          new ProgramBuilder(compiler, namer, this, emitter, rtiNeededClasses);
+      ProgramBuilder programBuilder = new ProgramBuilder(
+          compiler, namer, this, emitter, closedWorld, rtiNeededClasses);
       int size = emitter.emitProgram(programBuilder);
       // TODO(floitsch): we shouldn't need the `neededClasses` anymore.
       neededClasses = programBuilder.collector.neededClasses;
@@ -153,18 +167,24 @@
   }
 }
 
-abstract class Emitter {
+abstract class EmitterFactory {
   /// Returns the string that is used to find library patches that are
   /// specialized for this emitter.
   String get patchVersion;
 
+  /// Returns true, if the emitter supports reflection.
+  bool get supportsReflection;
+
+  /// Create the [Emitter] for the emitter [task] that uses the given [namer].
+  Emitter createEmitter(
+      CodeEmitterTask task, Namer namer, ClosedWorld closedWorld);
+}
+
+abstract class Emitter {
   /// Uses the [programBuilder] to generate a model of the program, emits
   /// the program, and returns the size of the generated output.
   int emitProgram(ProgramBuilder programBuilder);
 
-  /// Returns true, if the emitter supports reflection.
-  bool get supportsReflection;
-
   /// Returns the JS function that must be invoked to get the value of the
   /// lazily initialized static.
   jsAst.Expression isolateLazyInitializerAccess(FieldElement element);
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
index 5a6fb44..3f813ad 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
@@ -5,8 +5,13 @@
 part of dart2js.js_emitter.full_emitter;
 
 class ClassEmitter extends CodeEmitterHelper {
+  final ClosedWorld closedWorld;
+
+  ClassEmitter(this.closedWorld);
+
   ClassStubGenerator get _stubGenerator =>
-      new ClassStubGenerator(compiler, namer, backend);
+      new ClassStubGenerator(namer, backend, codegenWorld, closedWorld,
+          enableMinification: compiler.options.enableMinification);
 
   /**
    * Documentation wanted -- johnniwinther
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/code_emitter_helper.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/code_emitter_helper.dart
index 6c7ee56..c1acde7 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/code_emitter_helper.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/code_emitter_helper.dart
@@ -19,6 +19,8 @@
 
   DiagnosticReporter get reporter => compiler.reporter;
 
+  CodegenWorldBuilder get codegenWorld => compiler.codegenWorld;
+
   String get n => emitter.n;
 
   String get _ => emitter._;
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
index af5e764..1affdaf 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
@@ -52,13 +52,15 @@
         TypeVariableHandler;
 import '../../universe/call_structure.dart' show CallStructure;
 import '../../universe/selector.dart' show Selector;
+import '../../universe/world_builder.dart' show CodegenWorldBuilder;
 import '../../util/characters.dart' show $$, $A, $HASH, $Z, $a, $z;
 import '../../util/uri_extras.dart' show relativize;
 import '../../util/util.dart' show equalElements;
+import '../../world.dart' show ClosedWorld;
 import '../constant_ordering.dart' show deepCompareConstants;
 import '../headers.dart';
-import '../js_emitter.dart' hide Emitter;
-import '../js_emitter.dart' as js_emitter show Emitter;
+import '../js_emitter.dart' hide Emitter, EmitterFactory;
+import '../js_emitter.dart' as js_emitter show Emitter, EmitterFactory;
 import '../model.dart';
 import '../program_builder/program_builder.dart';
 
@@ -72,6 +74,25 @@
 part 'nsm_emitter.dart';
 part 'setup_program_builder.dart';
 
+class EmitterFactory implements js_emitter.EmitterFactory {
+  final bool generateSourceMap;
+
+  EmitterFactory({this.generateSourceMap});
+
+  @override
+  String get patchVersion => "full";
+
+  @override
+  bool get supportsReflection => true;
+
+  @override
+  Emitter createEmitter(
+      CodeEmitterTask task, Namer namer, ClosedWorld closedWorld) {
+    return new Emitter(
+        task.compiler, namer, closedWorld, generateSourceMap, task);
+  }
+}
+
 class Emitter implements js_emitter.Emitter {
   final Compiler compiler;
   final CodeEmitterTask task;
@@ -83,9 +104,9 @@
   List<TypedefElement> typedefsNeededForReflection;
 
   final ContainerBuilder containerBuilder = new ContainerBuilder();
-  final ClassEmitter classEmitter = new ClassEmitter();
-  final NsmEmitter nsmEmitter = new NsmEmitter();
-  final InterceptorEmitter interceptorEmitter = new InterceptorEmitter();
+  final ClassEmitter classEmitter;
+  final NsmEmitter nsmEmitter;
+  final InterceptorEmitter interceptorEmitter;
 
   // TODO(johnniwinther): Wrap these fields in a caching strategy.
   final Set<ConstantValue> cachedEmittedConstants;
@@ -154,18 +175,30 @@
 
   final bool generateSourceMap;
 
-  Emitter(Compiler compiler, Namer namer, this.generateSourceMap, this.task)
+  Emitter(Compiler compiler, Namer namer, ClosedWorld closedWorld,
+      this.generateSourceMap, this.task)
       : this.compiler = compiler,
         this.namer = namer,
         cachedEmittedConstants = compiler.cacheStrategy.newSet(),
         cachedClassBuilders = compiler.cacheStrategy.newMap(),
-        cachedElements = compiler.cacheStrategy.newSet() {
+        cachedElements = compiler.cacheStrategy.newSet(),
+        classEmitter = new ClassEmitter(closedWorld),
+        interceptorEmitter = new InterceptorEmitter(closedWorld),
+        nsmEmitter = new NsmEmitter(closedWorld) {
     constantEmitter = new ConstantEmitter(
         compiler, namer, this.constantReference, constantListGenerator);
     containerBuilder.emitter = this;
     classEmitter.emitter = this;
     nsmEmitter.emitter = this;
     interceptorEmitter.emitter = this;
+    if (compiler.options.hasIncrementalSupport) {
+      // Much like a scout, an incremental compiler is always prepared. For
+      // mixins, classes, and lazy statics, at least.
+      needsClassSupport = true;
+      needsMixinSupport = true;
+      needsLazyInitializer = true;
+      needsStructuredMemberInfo = true;
+    }
   }
 
   DiagnosticReporter get reporter => compiler.reporter;
@@ -189,9 +222,6 @@
   }
 
   @override
-  String get patchVersion => "full";
-
-  @override
   bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) {
     if (constant.isFunction) return true; // Already emitted.
     if (constant.isPrimitive) return true; // Inlined.
@@ -273,9 +303,6 @@
   String get globalsHolder => r"$globals$";
 
   @override
-  bool get supportsReflection => true;
-
-  @override
   jsAst.Expression generateEmbeddedGlobalAccess(String global) {
     return js(generateEmbeddedGlobalAccessString(global));
   }
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/interceptor_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/interceptor_emitter.dart
index 0da9ca3..1c90f92 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/interceptor_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/interceptor_emitter.dart
@@ -5,8 +5,11 @@
 part of dart2js.js_emitter.full_emitter;
 
 class InterceptorEmitter extends CodeEmitterHelper {
+  final ClosedWorld closedWorld;
   final Set<jsAst.Name> interceptorInvocationNames = new Set<jsAst.Name>();
 
+  InterceptorEmitter(this.closedWorld);
+
   void recordMangledNameOfMemberMethod(
       FunctionElement member, jsAst.Name name) {
     if (backend.isInterceptedMethod(member)) {
@@ -17,7 +20,7 @@
   jsAst.Expression buildGetInterceptorMethod(
       jsAst.Name key, Set<ClassElement> classes) {
     InterceptorStubGenerator stubGenerator =
-        new InterceptorStubGenerator(compiler, namer, backend);
+        new InterceptorStubGenerator(compiler, namer, backend, closedWorld);
     jsAst.Expression function =
         stubGenerator.generateGetInterceptorMethod(classes);
 
@@ -53,7 +56,7 @@
       ..sort();
 
     InterceptorStubGenerator stubGenerator =
-        new InterceptorStubGenerator(compiler, namer, backend);
+        new InterceptorStubGenerator(compiler, namer, backend, closedWorld);
     String globalObject =
         namer.globalObjectFor(backend.helpers.interceptorsLibrary);
     for (jsAst.Name name in names) {
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
index f0a6e0f..9bdf146 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
@@ -5,8 +5,11 @@
 part of dart2js.js_emitter.full_emitter;
 
 class NsmEmitter extends CodeEmitterHelper {
+  final ClosedWorld closedWorld;
   final List<Selector> trivialNsmHandlers = <Selector>[];
 
+  NsmEmitter(this.closedWorld);
+
   /// If this is true then we can generate the noSuchMethod handlers at startup
   /// time, instead of them being emitted as part of the Object class.
   bool get generateTrivialNsmHandlers => true;
@@ -19,8 +22,9 @@
   static const MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING = 4;
 
   void emitNoSuchMethodHandlers(AddPropertyFunction addProperty) {
-    ClassStubGenerator generator =
-        new ClassStubGenerator(compiler, namer, backend);
+    ClassStubGenerator generator = new ClassStubGenerator(
+        namer, backend, codegenWorld, closedWorld,
+        enableMinification: compiler.options.enableMinification);
 
     // Keep track of the JavaScript names we've already added so we
     // do not introduce duplicates (bad for code size).
@@ -55,7 +59,7 @@
             generator.generateStubForNoSuchMethod(jsName, selector);
         addProperty(method.name, method.code);
         if (reflectionName != null) {
-          bool accessible = compiler.closedWorld.allFunctions
+          bool accessible = closedWorld.allFunctions
               .filter(selector, null)
               .any((Element e) => backend.isAccessibleByReflection(e));
           addProperty(
diff --git a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
index 265c946..9a7d2cc 100644
--- a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
@@ -8,8 +8,10 @@
   final Compiler compiler;
   final Namer namer;
   final JavaScriptBackend backend;
+  final ClosedWorld closedWorld;
 
-  InterceptorStubGenerator(this.compiler, this.namer, this.backend);
+  InterceptorStubGenerator(
+      this.compiler, this.namer, this.backend, this.closedWorld);
 
   Emitter get emitter => backend.emitter.emitter;
 
@@ -248,8 +250,8 @@
       bool containsJsIndexable =
           helpers.jsIndexingBehaviorInterface.isResolved &&
               classes.any((cls) {
-                return compiler.closedWorld
-                    .isSubtypeOf(cls, helpers.jsIndexingBehaviorInterface);
+                return closedWorld.isSubtypeOf(
+                    cls, helpers.jsIndexingBehaviorInterface);
               });
       // The index set operator requires a check on its set value in
       // checked mode, so we don't optimize the interceptor if the
diff --git a/pkg/compiler/lib/src/js_emitter/js_emitter.dart b/pkg/compiler/lib/src/js_emitter/js_emitter.dart
index e902ab5..5d715a3 100644
--- a/pkg/compiler/lib/src/js_emitter/js_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/js_emitter.dart
@@ -56,8 +56,10 @@
         TypeVariableHandler;
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart' show Selector;
-import '../universe/world_builder.dart' show SelectorConstraints;
+import '../universe/world_builder.dart'
+    show CodegenWorldBuilder, SelectorConstraints;
 import '../util/util.dart' show Setlet;
+import '../world.dart' show ClosedWorld;
 import 'full_emitter/emitter.dart' as full_js_emitter;
 import 'lazy_emitter/emitter.dart' as lazy_js_emitter;
 import 'model.dart';
diff --git a/pkg/compiler/lib/src/js_emitter/lazy_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/lazy_emitter/emitter.dart
index 64e1f79b..3714a08 100644
--- a/pkg/compiler/lib/src/js_emitter/lazy_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/lazy_emitter/emitter.dart
@@ -13,12 +13,27 @@
     show ClassElement, Element, FieldElement, FunctionElement;
 import '../../js/js.dart' as js;
 import '../../js_backend/js_backend.dart' show JavaScriptBackend, Namer;
-import '../js_emitter.dart' show NativeEmitter;
-import '../js_emitter.dart' as emitterTask show Emitter;
+import '../../world.dart' show ClosedWorld;
+import '../js_emitter.dart' show CodeEmitterTask, NativeEmitter;
+import '../js_emitter.dart' as emitterTask show Emitter, EmitterFactory;
 import '../model.dart';
 import '../program_builder/program_builder.dart' show ProgramBuilder;
 import 'model_emitter.dart';
 
+class EmitterFactory implements emitterTask.EmitterFactory {
+  @override
+  String get patchVersion => "lazy";
+
+  @override
+  bool get supportsReflection => false;
+
+  @override
+  Emitter createEmitter(
+      CodeEmitterTask task, Namer namer, ClosedWorld closedWorld) {
+    return new Emitter(task.compiler, namer, task.nativeEmitter);
+  }
+}
+
 class Emitter implements emitterTask.Emitter {
   final Compiler _compiler;
   final Namer namer;
@@ -34,17 +49,11 @@
   DiagnosticReporter get reporter => _compiler.reporter;
 
   @override
-  String get patchVersion => "lazy";
-
-  @override
   int emitProgram(ProgramBuilder programBuilder) {
     Program program = programBuilder.buildProgram();
     return _emitter.emitProgram(program);
   }
 
-  @override
-  bool get supportsReflection => false;
-
   // TODO(floitsch): copied from full emitter. Adjust or share.
   @override
   bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) {
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 c63527d..ad7f2ed 100644
--- a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
@@ -10,8 +10,10 @@
   final Namer namer;
   final Compiler compiler;
   final JavaScriptBackend backend;
+  final ClosedWorld closedWorld;
 
-  ParameterStubGenerator(this.compiler, this.namer, this.backend);
+  ParameterStubGenerator(
+      this.compiler, this.namer, this.backend, this.closedWorld);
 
   Emitter get emitter => backend.emitter.emitter;
   CodeEmitterTask get emitterTask => backend.emitter;
@@ -267,8 +269,7 @@
     for (Selector selector in selectors.keys) {
       if (renamedCallSelectors.contains(selector)) continue;
       if (!selector.appliesUnnamed(member)) continue;
-      if (!selectors[selector]
-          .applies(member, selector, compiler.closedWorld)) {
+      if (!selectors[selector].applies(member, selector, closedWorld)) {
         continue;
       }
 
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
index 6e43f98..5389c2c 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
@@ -14,6 +14,7 @@
   // TODO(floitsch): the code-emitter task should not need a namer.
   final Namer namer;
   final Compiler compiler;
+  final ClosedWorld closedWorld;
   final Set<ClassElement> rtiNeededClasses;
   final Emitter emitter;
 
@@ -46,7 +47,8 @@
 
   CoreClasses get coreClasses => compiler.coreClasses;
 
-  Collector(this.compiler, this.namer, this.rtiNeededClasses, this.emitter);
+  Collector(this.compiler, this.namer, this.closedWorld, this.rtiNeededClasses,
+      this.emitter);
 
   Set<ClassElement> computeInterceptorsReferencedFromConstants() {
     Set<ClassElement> classes = new Set<ClassElement>();
@@ -129,7 +131,7 @@
         final onlyForRti = classesOnlyNeededForRti.contains(cls);
         if (!onlyForRti) {
           backend.retainMetadataOf(cls);
-          new FieldVisitor(compiler, namer).visitFields(cls, false,
+          new FieldVisitor(compiler, namer, closedWorld).visitFields(cls, false,
               (Element member, js.Name name, js.Name accessorName,
                   bool needsGetter, bool needsSetter, bool needsCheckedSetter) {
             bool needsAccessor = needsGetter || needsSetter;
@@ -169,8 +171,8 @@
   /// Compute all the classes and typedefs that must be emitted.
   void computeNeededDeclarations() {
     // Compute needed typedefs.
-    typedefsNeededForReflection = Elements.sortedByPosition(compiler
-        .closedWorld.allTypedefs
+    typedefsNeededForReflection = Elements.sortedByPosition(closedWorld
+        .allTypedefs
         .where(backend.isAccessibleByReflection)
         .toList());
 
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart b/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
index 1f6956d..75ca6f5 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
@@ -33,10 +33,11 @@
 class FieldVisitor {
   final Compiler compiler;
   final Namer namer;
+  final ClosedWorld closedWorld;
 
   JavaScriptBackend get backend => compiler.backend;
 
-  FieldVisitor(this.compiler, this.namer);
+  FieldVisitor(this.compiler, this.namer, this.closedWorld);
 
   /**
    * Invokes [f] for each of the fields of [element].
@@ -140,7 +141,7 @@
     if (fieldAccessNeverThrows(field)) return false;
     if (backend.shouldRetainGetter(field)) return true;
     return field.isClassMember &&
-        compiler.codegenWorld.hasInvokedGetter(field, compiler.closedWorld);
+        compiler.codegenWorld.hasInvokedGetter(field, closedWorld);
   }
 
   bool fieldNeedsSetter(VariableElement field) {
@@ -149,7 +150,7 @@
     if (field.isFinal || field.isConst) return false;
     if (backend.shouldRetainSetter(field)) return true;
     return field.isClassMember &&
-        compiler.codegenWorld.hasInvokedSetter(field, compiler.closedWorld);
+        compiler.codegenWorld.hasInvokedSetter(field, closedWorld);
   }
 
   static bool fieldAccessNeverThrows(VariableElement field) {
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 1ee47ed..fd18152 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -34,6 +34,7 @@
 import '../../universe/selector.dart' show Selector;
 import '../../universe/world_builder.dart'
     show CodegenWorldBuilder, SelectorConstraints;
+import '../../world.dart' show ClosedWorld;
 import '../js_emitter.dart'
     show
         ClassStubGenerator,
@@ -57,6 +58,7 @@
   final Compiler _compiler;
   final Namer namer;
   final CodeEmitterTask _task;
+  final ClosedWorld closedWorld;
 
   /// Contains the collected information the program builder used to build
   /// the model.
@@ -71,11 +73,12 @@
   bool _storeFunctionTypesInMetadata = false;
 
   ProgramBuilder(Compiler compiler, Namer namer, this._task, Emitter emitter,
-      Set<ClassElement> rtiNeededClasses)
+      ClosedWorld closedWorld, Set<ClassElement> rtiNeededClasses)
       : this._compiler = compiler,
         this.namer = namer,
-        this.collector =
-            new Collector(compiler, namer, rtiNeededClasses, emitter),
+        this.closedWorld = closedWorld,
+        this.collector = new Collector(
+            compiler, namer, closedWorld, rtiNeededClasses, emitter),
         this._registry = new Registry(compiler);
 
   JavaScriptBackend get backend => _compiler.backend;
@@ -205,7 +208,7 @@
 
   js.Expression _buildTypeToInterceptorMap() {
     InterceptorStubGenerator stubGenerator =
-        new InterceptorStubGenerator(_compiler, namer, backend);
+        new InterceptorStubGenerator(_compiler, namer, backend, closedWorld);
     return stubGenerator.generateTypeToInterceptorMap();
   }
 
@@ -517,8 +520,9 @@
     List<Method> methods = [];
     List<StubMethod> callStubs = <StubMethod>[];
 
-    ClassStubGenerator classStubGenerator =
-        new ClassStubGenerator(_compiler, namer, backend);
+    ClassStubGenerator classStubGenerator = new ClassStubGenerator(
+        namer, backend, universe, closedWorld,
+        enableMinification: _compiler.options.enableMinification);
     RuntimeTypeGenerator runtimeTypeGenerator =
         new RuntimeTypeGenerator(_compiler, _task, namer);
 
@@ -676,7 +680,7 @@
 
   bool _methodCanBeApplied(FunctionElement method) {
     return backend.hasFunctionApplySupport &&
-        _compiler.closedWorld.getMightBePassedToApply(method);
+        closedWorld.getMightBePassedToApply(method);
   }
 
   // TODO(herhut): Refactor incremental compilation and remove method.
@@ -736,9 +740,8 @@
         isClosureCallMethod = true;
       } else {
         // Careful with operators.
-        canTearOff =
-            universe.hasInvokedGetter(element, _compiler.closedWorld) ||
-                (canBeReflected && !element.isOperator);
+        canTearOff = universe.hasInvokedGetter(element, closedWorld) ||
+            (canBeReflected && !element.isOperator);
         assert(canTearOff ||
             !universe.methodsNeedingSuperGetter.contains(element));
         tearOffName = namer.getterForElement(element);
@@ -813,7 +816,7 @@
     if (!_methodNeedsStubs(element)) return const <ParameterStubMethod>[];
 
     ParameterStubGenerator generator =
-        new ParameterStubGenerator(_compiler, namer, backend);
+        new ParameterStubGenerator(_compiler, namer, backend, closedWorld);
     return generator.generateParameterStubs(element, canTearOff: canTearOff);
   }
 
@@ -841,7 +844,7 @@
 
   Iterable<StaticStubMethod> _generateGetInterceptorMethods() {
     InterceptorStubGenerator stubGenerator =
-        new InterceptorStubGenerator(_compiler, namer, backend);
+        new InterceptorStubGenerator(_compiler, namer, backend, closedWorld);
 
     String holderName = namer.globalObjectFor(helpers.interceptorsLibrary);
     // TODO(floitsch): we shouldn't update the registry in the middle of
@@ -860,9 +863,13 @@
 
   List<Field> _buildFields(Element holder, bool visitStatics) {
     List<Field> fields = <Field>[];
-    new FieldVisitor(_compiler, namer).visitFields(holder, visitStatics,
-        (VariableElement field, js.Name name, js.Name accessorName,
-            bool needsGetter, bool needsSetter, bool needsCheckedSetter) {
+    new FieldVisitor(_compiler, namer, closedWorld)
+        .visitFields(holder, visitStatics, (VariableElement field,
+            js.Name name,
+            js.Name accessorName,
+            bool needsGetter,
+            bool needsSetter,
+            bool needsCheckedSetter) {
       assert(invariant(field, field.isDeclaration));
 
       int getterFlags = 0;
@@ -901,7 +908,7 @@
 
   Iterable<StaticStubMethod> _generateOneShotInterceptors() {
     InterceptorStubGenerator stubGenerator =
-        new InterceptorStubGenerator(_compiler, namer, backend);
+        new InterceptorStubGenerator(_compiler, namer, backend, closedWorld);
 
     String holderName = namer.globalObjectFor(helpers.interceptorsLibrary);
     // TODO(floitsch): we shouldn't update the registry in the middle of
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
index 07be9d6..bac4f1e 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
@@ -14,12 +14,32 @@
     show ClassElement, Element, FieldElement, FunctionElement;
 import '../../js/js.dart' as js;
 import '../../js_backend/js_backend.dart' show JavaScriptBackend, Namer;
-import '../js_emitter.dart' show NativeEmitter;
-import '../js_emitter.dart' as emitterTask show Emitter;
+import '../../world.dart' show ClosedWorld;
+import '../js_emitter.dart' show CodeEmitterTask, NativeEmitter;
+import '../js_emitter.dart' as emitterTask show Emitter, EmitterFactory;
 import '../model.dart';
 import '../program_builder/program_builder.dart' show ProgramBuilder;
 import 'model_emitter.dart';
 
+class EmitterFactory implements emitterTask.EmitterFactory {
+  final bool generateSourceMap;
+
+  EmitterFactory({this.generateSourceMap});
+
+  @override
+  String get patchVersion => "startup";
+
+  @override
+  bool get supportsReflection => false;
+
+  @override
+  Emitter createEmitter(
+      CodeEmitterTask task, Namer namer, ClosedWorld closedWorld) {
+    return new Emitter(
+        task.compiler, namer, task.nativeEmitter, generateSourceMap);
+  }
+}
+
 class Emitter implements emitterTask.Emitter {
   final Compiler _compiler;
   final Namer namer;
@@ -37,18 +57,12 @@
   DiagnosticReporter get reporter => _compiler.reporter;
 
   @override
-  String get patchVersion => "startup";
-
-  @override
   int emitProgram(ProgramBuilder programBuilder) {
     Program program = programBuilder.buildProgram();
     return _emitter.emitProgram(program);
   }
 
   @override
-  bool get supportsReflection => false;
-
-  @override
   bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) {
     return _emitter.isConstantInlinedOrAlreadyEmitted(constant);
   }
diff --git a/pkg/compiler/lib/src/js_emitter/type_test_registry.dart b/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
index c1ff342..040a4eb 100644
--- a/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
+++ b/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
@@ -37,8 +37,9 @@
   }
 
   final Compiler compiler;
+  final ClosedWorld closedWorld;
 
-  TypeTestRegistry(this.compiler);
+  TypeTestRegistry(this.compiler, this.closedWorld);
 
   JavaScriptBackend get backend => compiler.backend;
 
@@ -105,8 +106,7 @@
         return false;
       } else if (function.isInstanceMember) {
         if (!function.enclosingClass.isClosure) {
-          return compiler.codegenWorld
-              .hasInvokedGetter(function, compiler.closedWorld);
+          return compiler.codegenWorld.hasInvokedGetter(function, closedWorld);
         }
       }
       return false;
diff --git a/pkg/compiler/lib/src/kernel/kernel.dart b/pkg/compiler/lib/src/kernel/kernel.dart
index 77c7e2b..155f2a0 100644
--- a/pkg/compiler/lib/src/kernel/kernel.dart
+++ b/pkg/compiler/lib/src/kernel/kernel.dart
@@ -302,13 +302,8 @@
     }
   }
 
-  // TODO(ahe): Remove this method when dart2js support generic type arguments.
-  List<ir.TypeParameter> typeParametersNotImplemented() {
-    return const <ir.TypeParameter>[];
-  }
-
   ir.FunctionType functionTypeToIr(FunctionType type) {
-    List<ir.TypeParameter> typeParameters = typeParametersNotImplemented();
+    List<ir.TypeParameter> typeParameters = <ir.TypeParameter>[];
     int requiredParameterCount = type.parameterTypes.length;
     List<ir.DartType> positionalParameters =
         new List<ir.DartType>.from(typesToIr(type.parameterTypes))
@@ -462,6 +457,8 @@
           procedure.kind = irFunction.kind;
         }
         endFactoryScope(function);
+        irFunction.node.typeParameters
+            .addAll(typeVariablesToIr(function.typeVariables));
         member.transformerFlags = visitor.transformerFlags;
         assert(() {
           visitor.locals.forEach(checkMember);
@@ -556,11 +553,14 @@
     return typeParameters.putIfAbsent(variable, () {
       ir.TypeParameter parameter = new ir.TypeParameter(variable.name, null);
       addWork(variable, () {
-        // TODO(ahe): This assignment will probably not be correct when dart2js
-        // supports generic methods.
-        ClassElement cls = variable.typeDeclaration;
-        cls.ensureResolved(compiler.resolution);
-        parameter.parent = classToIr(cls);
+        if (variable.typeDeclaration.isClass) {
+          ClassElement cls = variable.typeDeclaration;
+          cls.ensureResolved(compiler.resolution);
+          parameter.parent = classToIr(cls);
+        } else {
+          FunctionElement method = variable.typeDeclaration;
+          parameter.parent = functionToIr(method).function;
+        }
         parameter.bound = typeToIr(variable.bound);
       });
       return parameter;
diff --git a/pkg/compiler/lib/src/kernel/kernel_visitor.dart b/pkg/compiler/lib/src/kernel/kernel_visitor.dart
index 2c3fcda..ea28f68 100644
--- a/pkg/compiler/lib/src/kernel/kernel_visitor.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_visitor.dart
@@ -404,6 +404,7 @@
       ir.Statement statement, Node node, JumpTarget jumpTarget) {
     assert(node.isValidBreakTarget());
     assert(jumpTarget == elements.getTargetDefinition(node));
+    associateNode(statement, node);
     if (jumpTarget != null && jumpTarget.isBreakTarget) {
       ir.LabeledStatement breakTarget = getBreakTarget(jumpTarget);
       breakTarget.body = statement;
@@ -2025,8 +2026,7 @@
   }
 
   ir.FunctionNode buildFunctionNode(FunctionElement function, Node bodyNode) {
-    List<ir.TypeParameter> typeParameters =
-        kernel.typeParametersNotImplemented();
+    List<ir.TypeParameter> typeParameters = <ir.TypeParameter>[];
     List<ir.VariableDeclaration> positionalParameters =
         <ir.VariableDeclaration>[];
     List<ir.VariableDeclaration> namedParameters = <ir.VariableDeclaration>[];
diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart
index 300a650..bd37b4c 100644
--- a/pkg/compiler/lib/src/native/enqueue.dart
+++ b/pkg/compiler/lib/src/native/enqueue.dart
@@ -487,7 +487,7 @@
 
     // Give an info so that library developers can compile with -v to find why
     // all the native classes are included.
-    if (unusedBefore == matchingClasses.length) {
+    if (unusedBefore > 0 && unusedBefore == matchingClasses.length) {
       reporter.log('All native types marked as used due to $cause.');
     }
   }
diff --git a/pkg/compiler/lib/src/native/ssa.dart b/pkg/compiler/lib/src/native/ssa.dart
index 945995d..a7f185f 100644
--- a/pkg/compiler/lib/src/native/ssa.dart
+++ b/pkg/compiler/lib/src/native/ssa.dart
@@ -29,7 +29,8 @@
     HInstruction local = builder.localsHandler.readLocal(parameter);
     ConstantValue arityConstant =
         builder.constantSystem.createInt(type.computeArity());
-    HInstruction arity = builder.graph.addConstant(arityConstant, compiler);
+    HInstruction arity =
+        builder.graph.addConstant(arityConstant, builder.closedWorld);
     // TODO(ngeoffray): For static methods, we could pass a method with a
     // defined arity.
     Element helper = backend.helpers.closureConverter;
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index e167b44..0c0998a 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -3001,7 +3001,11 @@
 
   ResolutionResult visitSend(Send node) {
     // Resolve type arguments to ensure that these are well-formed types.
-    visit(node.typeArgumentsNode);
+    if (node.typeArgumentsNode != null) {
+      for (TypeAnnotation type in node.typeArgumentsNode.nodes) {
+        resolveTypeAnnotation(type, registerCheckedModeCheck: false);
+      }
+    }
     if (node.isOperator) {
       // `a && b`, `a + b`, `-a`, or `a is T`.
       return handleOperatorSend(node);
diff --git a/pkg/compiler/lib/src/resolution/tree_elements.dart b/pkg/compiler/lib/src/resolution/tree_elements.dart
index fd0080f..f9c239c 100644
--- a/pkg/compiler/lib/src/resolution/tree_elements.dart
+++ b/pkg/compiler/lib/src/resolution/tree_elements.dart
@@ -361,9 +361,7 @@
   }
 
   void defineTarget(Node node, JumpTarget target) {
-    if (_definedTargets == null) {
-      _definedTargets = new Maplet<Node, JumpTarget>();
-    }
+    _definedTargets ??= new Maplet<Node, JumpTarget>();
     _definedTargets[node] = target;
   }
 
@@ -382,9 +380,7 @@
   }
 
   void registerTargetOf(GotoStatement node, JumpTarget target) {
-    if (_usedTargets == null) {
-      _usedTargets = new Maplet<GotoStatement, JumpTarget>();
-    }
+    _usedTargets ??= new Maplet<GotoStatement, JumpTarget>();
     _usedTargets[node] = target;
   }
 
@@ -394,9 +390,7 @@
   }
 
   void defineLabel(Label label, LabelDefinition target) {
-    if (_definedLabels == null) {
-      _definedLabels = new Maplet<Label, LabelDefinition>();
-    }
+    _definedLabels ??= new Maplet<Label, LabelDefinition>();
     _definedLabels[label] = target;
   }
 
diff --git a/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart b/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart
index c839c95..3f58490 100644
--- a/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart
@@ -587,12 +587,11 @@
     }
     jumpTargetLabels.forEach((JumpTargetX jumpTarget, List<int> labelIds) {
       if (labelIds.isEmpty) return;
-      LinkBuilder<LabelDefinition> linkBuilder =
-          new LinkBuilder<LabelDefinition>();
+      List<LabelDefinition> labels = <LabelDefinition>[];
       for (int labelId in labelIds) {
-        linkBuilder.addLast(labelDefinitions[labelId]);
+        labels.add(labelDefinitions[labelId]);
       }
-      jumpTarget.labels = linkBuilder.toLink();
+      jumpTarget.labels = labels;
     });
 
     ListDecoder dataDecoder = objectDecoder.getList(Key.DATA, isOptional: true);
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index cda5d75..25f7fe8 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -66,7 +66,7 @@
 
   DiagnosticReporter get reporter => compiler.reporter;
 
-  HGraph build(CodegenWorkItem work) {
+  HGraph build(CodegenWorkItem work, ClosedWorld closedWorld) {
     return measure(() {
       Element element = work.element.implementation;
       return reporter.withCurrentElement(element, () {
@@ -75,6 +75,7 @@
             work.resolvedAst,
             work.registry,
             backend,
+            closedWorld,
             emitter.nativeEmitter,
             sourceInformationFactory);
         HGraph graph = builder.build();
@@ -91,7 +92,7 @@
             work.registry.registerCompileTimeConstant(constant);
           });
         }
-        if (compiler.tracer.isEnabled) {
+        if (backend.tracer.isEnabled) {
           String name;
           if (element.isClassMember) {
             String className = element.enclosingClass.name;
@@ -103,8 +104,8 @@
           } else {
             name = "${element.name}";
           }
-          compiler.tracer.traceCompilation(name);
-          compiler.tracer.traceGraph('builder', graph);
+          backend.tracer.traceCompilation(name);
+          backend.tracer.traceGraph('builder', graph);
         }
         return graph;
       });
@@ -127,6 +128,7 @@
     implements SemanticSendVisitor {
   /// The element for which this SSA builder is being used.
   final Element target;
+  final ClosedWorld closedWorld;
 
   ResolvedAst resolvedAst;
 
@@ -198,6 +200,7 @@
       this.resolvedAst,
       this.registry,
       JavaScriptBackend backend,
+      this.closedWorld,
       this.nativeEmitter,
       SourceInformationStrategy sourceInformationFactory)
       : this.infoReporter = backend.compiler.dumpInfoTask,
@@ -576,7 +579,7 @@
           instanceType: instanceType);
       inlinedFrom(functionResolvedAst, () {
         if (!isReachable) {
-          emitReturn(graph.addConstantNull(compiler), null);
+          emitReturn(graph.addConstantNull(closedWorld), null);
         } else {
           doInline(functionResolvedAst);
         }
@@ -637,7 +640,7 @@
         backend.constants.getConstantValue(parameter.constant);
     assert(invariant(parameter, constantValue != null,
         message: 'No constant computed for $parameter'));
-    return graph.addConstant(constantValue, compiler);
+    return graph.addConstant(constantValue, closedWorld);
   }
 
   ClassElement get currentNonClosureClass {
@@ -674,7 +677,7 @@
   }
 
   HInstruction addConstant(ast.Node node) {
-    return graph.addConstant(getConstantForNode(node), compiler);
+    return graph.addConstant(getConstantForNode(node), closedWorld);
   }
 
   /**
@@ -709,12 +712,12 @@
             node: function,
             visitCondition: () {
               HParameterValue parameter = parameters.values.first;
-              push(new HIdentity(parameter, graph.addConstantNull(compiler),
+              push(new HIdentity(parameter, graph.addConstantNull(closedWorld),
                   null, commonMasks.boolType));
             },
             visitThen: () {
               closeAndGotoExit(new HReturn(
-                  graph.addConstantBool(false, compiler),
+                  graph.addConstantBool(false, closedWorld),
                   sourceInformationBuilder
                       .buildImplicitReturn(functionElement)));
             },
@@ -859,7 +862,7 @@
     localsHandler.closureData =
         compiler.closureToClassMapper.getClosureToClassMapping(resolvedAst);
     returnLocal = new SyntheticLocal("result", function);
-    localsHandler.updateLocal(returnLocal, graph.addConstantNull(compiler));
+    localsHandler.updateLocal(returnLocal, graph.addConstantNull(closedWorld));
 
     inTryStatement = false; // TODO(lry): why? Document.
 
@@ -984,7 +987,7 @@
           for (TypeVariableType variable in typeVariables) {
             localsHandler.updateLocal(
                 localsHandler.getTypeVariableAsLocal(variable),
-                graph.addConstantNull(compiler));
+                graph.addConstantNull(closedWorld));
           }
         }
       }
@@ -1187,7 +1190,7 @@
           // Unassigned fields of native classes are not initialized to
           // prevent overwriting pre-initialized native properties.
           if (!backend.isNativeOrExtendsNative(classElement)) {
-            fieldValues[member] = graph.addConstantNull(compiler);
+            fieldValues[member] = graph.addConstantNull(closedWorld);
           }
         } else {
           ast.Node right = initializer;
@@ -1351,7 +1354,7 @@
         if (interceptor == null) {
           ConstantValue constant =
               new InterceptorConstantValue(classElement.thisType);
-          interceptor = graph.addConstant(constant, compiler);
+          interceptor = graph.addConstant(constant, closedWorld);
         }
         bodyCallInputs.add(interceptor);
       }
@@ -1508,7 +1511,8 @@
     if (JavaScriptBackend.TRACE_METHOD == 'post') {
       if (element == backend.helpers.traceHelper) return;
       // TODO(sigmund): create a better uuid for elements.
-      HConstant idConstant = graph.addConstantInt(element.hashCode, compiler);
+      HConstant idConstant =
+          graph.addConstantInt(element.hashCode, closedWorld);
       HConstant nameConstant = addConstantString(element.name);
       add(new HInvokeStatic(backend.helpers.traceHelper,
           <HInstruction>[idConstant, nameConstant], commonMasks.dynamicType));
@@ -1521,8 +1525,8 @@
         localsHandler.substInContext(subtype), sourceElement);
     HInstruction supertypeInstruction = typeBuilder.analyzeTypeArgument(
         localsHandler.substInContext(supertype), sourceElement);
-    HInstruction messageInstruction =
-        graph.addConstantString(new ast.DartString.literal(message), compiler);
+    HInstruction messageInstruction = graph.addConstantString(
+        new ast.DartString.literal(message), closedWorld);
     MethodElement element = helpers.assertIsSubtype;
     var inputs = <HInstruction>[
       subtypeInstruction,
@@ -1674,7 +1678,7 @@
 
     HInstruction buildCondition() {
       if (node.condition == null) {
-        return graph.addConstantBool(true, compiler);
+        return graph.addConstantBool(true, closedWorld);
       }
       visit(node.condition);
       return popBoolified();
@@ -1766,7 +1770,7 @@
         localsHandler =
             savedLocals.mergeMultiple(continueHandlers, conditionBlock);
         SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock);
-        List<LabelDefinition> labels = jumpHandler.labels();
+        List<LabelDefinition> labels = jumpHandler.labels;
         HSubGraphBlockInformation bodyInfo =
             new HSubGraphBlockInformation(bodyGraph);
         HLabeledBlockInformation info;
@@ -1990,7 +1994,7 @@
       HConstant constant = operand;
       ConstantValue folded = operation.fold(constant.constant);
       if (folded != null) {
-        stack.add(graph.addConstant(folded, compiler));
+        stack.add(graph.addConstant(folded, closedWorld));
         return;
       }
     }
@@ -2111,7 +2115,7 @@
       assert(invariant(node, element == null || element.isMalformed));
       // TODO(ahe): Do something like the above, that is, emit a runtime
       // error.
-      stack.add(graph.addConstantNull(compiler));
+      stack.add(graph.addConstantNull(closedWorld));
     }
   }
 
@@ -2125,10 +2129,10 @@
     PrefixElement prefix =
         compiler.deferredLoadTask.deferredPrefixElement(node, elements);
     if (prefix != null) {
-      instruction =
-          graph.addDeferredConstant(value, prefix, sourceInformation, compiler);
+      instruction = graph.addDeferredConstant(
+          value, prefix, sourceInformation, compiler, closedWorld);
     } else {
-      instruction = graph.addConstant(value, compiler,
+      instruction = graph.addConstant(value, closedWorld,
           sourceInformation: sourceInformation);
     }
     stack.add(instruction);
@@ -2355,7 +2359,7 @@
       generateNoSuchSetter(location, element, send == null ? null : value);
     } else if (Elements.isMalformed(element)) {
       // TODO(ahe): Do something like [generateWrongArgumentCountError].
-      stack.add(graph.addConstantNull(compiler));
+      stack.add(graph.addConstantNull(closedWorld));
     } else {
       stack.add(value);
       LocalElement local = element;
@@ -2465,7 +2469,7 @@
       HInstruction isFieldName = addConstantStringFromName(operator);
       HInstruction asFieldName = closedWorld.hasAnyStrictSubtype(element)
           ? addConstantStringFromName(backend.namer.substitutionName(element))
-          : graph.addConstantNull(compiler);
+          : graph.addConstantNull(closedWorld);
       List<HInstruction> inputs = <HInstruction>[
         expression,
         isFieldName,
@@ -2667,7 +2671,8 @@
         'text': 'Mismatch between number of placeholders'
             ' and number of arguments.'
       });
-      stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+      // Result expected on stack.
+      stack.add(graph.addConstantNull(closedWorld));
       return;
     }
 
@@ -2763,7 +2768,7 @@
         reporter.reportErrorMessage(node, MessageKind.GENERIC,
             {'text': 'Error: Unknown internal flag "$name".'});
     }
-    stack.add(graph.addConstantBool(value, compiler));
+    stack.add(graph.addConstantBool(value, closedWorld));
   }
 
   void handleForeignJsGetName(ast.Send node) {
@@ -2891,7 +2896,7 @@
         if (argumentConstant is TypeConstantValue) {
           ConstantValue constant =
               new InterceptorConstantValue(argumentConstant.representedType);
-          HInstruction instruction = graph.addConstant(constant, compiler);
+          HInstruction instruction = graph.addConstant(constant, closedWorld);
           stack.add(instruction);
           return;
         }
@@ -2899,7 +2904,7 @@
     }
     reporter.reportErrorMessage(
         node, MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT);
-    stack.add(graph.addConstantNull(compiler));
+    stack.add(graph.addConstantNull(closedWorld));
   }
 
   void handleForeignJsCallInIsolate(ast.Send node) {
@@ -3011,7 +3016,7 @@
     } else if (name == 'JS_GET_FLAG') {
       handleForeignJsGetFlag(node);
     } else if (name == 'JS_EFFECT') {
-      stack.add(graph.addConstantNull(compiler));
+      stack.add(graph.addConstantNull(closedWorld));
     } else if (name == BackendHelpers.JS_INTERCEPTOR_CONSTANT) {
       handleJsInterceptorConstant(node);
     } else if (name == 'JS_STRING_CONCAT') {
@@ -3030,7 +3035,7 @@
     String loadId =
         compiler.deferredLoadTask.getImportDeferName(node, prefixElement);
     var inputs = [
-      graph.addConstantString(new ast.DartString.literal(loadId), compiler)
+      graph.addConstantString(new ast.DartString.literal(loadId), closedWorld)
     ];
     push(new HInvokeStatic(loadFunction, inputs, commonMasks.nonNullType,
         targetCanThrow: false)..sourceInformation = sourceInformation);
@@ -3069,7 +3074,7 @@
     for (String argumentName in selector.namedArguments) {
       ConstantValue argumentNameConstant =
           constantSystem.createString(new ast.DartString.literal(argumentName));
-      argumentNames.add(graph.addConstant(argumentNameConstant, compiler));
+      argumentNames.add(graph.addConstant(argumentNameConstant, closedWorld));
     }
     var argumentNamesInstruction = buildLiteralList(argumentNames);
     add(argumentNamesInstruction);
@@ -3081,9 +3086,9 @@
         null,
         createInvocationMirror,
         [
-          graph.addConstant(nameConstant, compiler),
-          graph.addConstantStringFromName(internalName, compiler),
-          graph.addConstant(kindConstant, compiler),
+          graph.addConstant(nameConstant, closedWorld),
+          graph.addConstantStringFromName(internalName, closedWorld),
+          graph.addConstant(kindConstant, closedWorld),
           argumentsInstruction,
           argumentNamesInstruction
         ],
@@ -3396,7 +3401,7 @@
 
     if (compiler.elementHasCompileTimeError(constructor)) {
       // TODO(ahe): Do something like [generateWrongArgumentCountError].
-      stack.add(graph.addConstantNull(compiler));
+      stack.add(graph.addConstantNull(closedWorld));
       return;
     }
 
@@ -3431,7 +3436,7 @@
         backend.isNativeOrExtendsNative(constructor.enclosingClass) &&
         !backend.isJsInterop(constructor)) {
       // Native class generative constructors take a pre-constructed object.
-      inputs.add(graph.addConstantNull(compiler));
+      inputs.add(graph.addConstantNull(closedWorld));
     }
     inputs.addAll(makeStaticArgumentList(
         callStructure, send.arguments, constructorImplementation));
@@ -3721,18 +3726,18 @@
       handleInvalidStaticInvoke(node, element);
     } else {
       // TODO(ahe): Do something like [generateWrongArgumentCountError].
-      stack.add(graph.addConstantNull(compiler));
+      stack.add(graph.addConstantNull(closedWorld));
     }
     return;
   }
 
   HConstant addConstantString(String string) {
     ast.DartString dartString = new ast.DartString.literal(string);
-    return graph.addConstantString(dartString, compiler);
+    return graph.addConstantString(dartString, closedWorld);
   }
 
   HConstant addConstantStringFromName(js.Name name) {
-    return graph.addConstantStringFromName(name, compiler);
+    return graph.addConstantStringFromName(name, closedWorld);
   }
 
   visitClassTypeLiteralGet(ast.Send node, ConstantExpression constant, _) {
@@ -3862,10 +3867,10 @@
     Element helper = helpers.throwNoSuchMethod;
     ConstantValue receiverConstant =
         constantSystem.createString(new ast.DartString.empty());
-    HInstruction receiver = graph.addConstant(receiverConstant, compiler);
+    HInstruction receiver = graph.addConstant(receiverConstant, closedWorld);
     ast.DartString dartString = new ast.DartString.literal(methodName);
     ConstantValue nameConstant = constantSystem.createString(dartString);
-    HInstruction name = graph.addConstant(nameConstant, compiler);
+    HInstruction name = graph.addConstant(nameConstant, closedWorld);
     if (argumentValues == null) {
       argumentValues = <HInstruction>[];
       argumentNodes.forEach((argumentNode) {
@@ -3880,14 +3885,14 @@
     if (existingArguments != null) {
       List<HInstruction> existingNames = <HInstruction>[];
       for (String name in existingArguments) {
-        HInstruction nameConstant =
-            graph.addConstantString(new ast.DartString.literal(name), compiler);
+        HInstruction nameConstant = graph.addConstantString(
+            new ast.DartString.literal(name), closedWorld);
         existingNames.add(nameConstant);
       }
       existingNamesList = buildLiteralList(existingNames);
       add(existingNamesList);
     } else {
-      existingNamesList = graph.addConstantNull(compiler);
+      existingNamesList = graph.addConstantNull(closedWorld);
     }
     pushInvokeStatic(
         diagnosticNode, helper, [receiver, name, arguments, existingNamesList],
@@ -3938,7 +3943,7 @@
       }
     } else if (Elements.isMalformed(element)) {
       // TODO(ahe): Do something like [generateWrongArgumentCountError].
-      stack.add(graph.addConstantNull(compiler));
+      stack.add(graph.addConstantNull(closedWorld));
     } else if (node.isConst) {
       stack.add(addConstant(node));
       if (isSymbolConstructor) {
@@ -4206,7 +4211,7 @@
       ast.SendSet node, HInstruction receiver, Link<ast.Node> arguments) {
     HInstruction rhs;
     if (node.isPrefix || node.isPostfix) {
-      rhs = graph.addConstantInt(1, compiler);
+      rhs = graph.addConstantInt(1, closedWorld);
     } else {
       visit(arguments.head);
       assert(arguments.tail.isEmpty);
@@ -4966,19 +4971,19 @@
   }
 
   void visitLiteralInt(ast.LiteralInt node) {
-    stack.add(graph.addConstantInt(node.value, compiler));
+    stack.add(graph.addConstantInt(node.value, closedWorld));
   }
 
   void visitLiteralDouble(ast.LiteralDouble node) {
-    stack.add(graph.addConstantDouble(node.value, compiler));
+    stack.add(graph.addConstantDouble(node.value, closedWorld));
   }
 
   void visitLiteralBool(ast.LiteralBool node) {
-    stack.add(graph.addConstantBool(node.value, compiler));
+    stack.add(graph.addConstantBool(node.value, closedWorld));
   }
 
   void visitLiteralString(ast.LiteralString node) {
-    stack.add(graph.addConstantString(node.dartString, compiler));
+    stack.add(graph.addConstantString(node.dartString, closedWorld));
   }
 
   void visitLiteralSymbol(ast.LiteralSymbol node) {
@@ -4989,7 +4994,7 @@
   void visitStringJuxtaposition(ast.StringJuxtaposition node) {
     if (!node.isInterpolation) {
       // This is a simple string with no interpolations.
-      stack.add(graph.addConstantString(node.dartString, compiler));
+      stack.add(graph.addConstantString(node.dartString, closedWorld));
       return;
     }
     StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node);
@@ -4998,7 +5003,7 @@
   }
 
   void visitLiteralNull(ast.LiteralNull node) {
-    stack.add(graph.addConstantNull(compiler));
+    stack.add(graph.addConstantNull(closedWorld));
   }
 
   visitNodeList(ast.NodeList node) {
@@ -5044,7 +5049,7 @@
   visitRethrow(ast.Rethrow node) {
     HInstruction exception = rethrowableException;
     if (exception == null) {
-      exception = graph.addConstantNull(compiler);
+      exception = graph.addConstantNull(closedWorld);
       reporter.internalError(node, 'rethrowableException should not be null.');
     }
     handleInTryStatement();
@@ -5089,7 +5094,7 @@
         inputs.add(handleConstantForOptionalParameter(optionalParameter));
       } else {
         // Wrong.
-        inputs.add(graph.addConstantNull(compiler));
+        inputs.add(graph.addConstantNull(closedWorld));
       }
     }
 
@@ -5160,7 +5165,7 @@
     }
     HInstruction value;
     if (node.expression == null) {
-      value = graph.addConstantNull(compiler);
+      value = graph.addConstantNull(closedWorld);
     } else {
       visit(node.expression);
       value = pop();
@@ -5218,7 +5223,7 @@
       ast.Node definition = link.head;
       LocalElement local = elements[definition];
       if (definition is ast.Identifier) {
-        HInstruction initialValue = graph.addConstantNull(compiler);
+        HInstruction initialValue = graph.addConstantNull(closedWorld);
         localsHandler.updateLocal(local, initialValue);
       } else {
         ast.SendSet node = definition;
@@ -5357,7 +5362,7 @@
     visit(node.expression);
     HInstruction expression = pop();
     pushInvokeStatic(node, helpers.streamIteratorConstructor,
-        [expression, graph.addConstantNull(compiler)]);
+        [expression, graph.addConstantNull(closedWorld)]);
     streamIterator = pop();
 
     void buildInitializer() {}
@@ -5533,9 +5538,9 @@
     void buildInitializer() {
       visit(node.expression);
       array = pop();
-      isFixed = isFixedLength(array.instructionType, compiler);
+      isFixed = isFixedLength(array.instructionType, closedWorld);
       localsHandler.updateLocal(
-          indexVariable, graph.addConstantInt(0, compiler));
+          indexVariable, graph.addConstantInt(0, closedWorld));
       originalLength = buildGetLength();
     }
 
@@ -5579,7 +5584,7 @@
       // but the code is horrible as `i+1` is carried around the loop in an
       // additional variable.
       HInstruction index = localsHandler.readLocal(indexVariable);
-      HInstruction one = graph.addConstantInt(1, compiler);
+      HInstruction one = graph.addConstantInt(1, closedWorld);
       HInstruction addInstruction =
           new HAdd(index, one, null, commonMasks.positiveIntType);
       add(addInstruction);
@@ -5630,7 +5635,7 @@
       // There was at least one reachable break, so the label is needed.
       entryBlock.setBlockFlow(
           new HLabeledBlockInformation(
-              new HSubGraphBlockInformation(bodyGraph), handler.labels()),
+              new HSubGraphBlockInformation(bodyGraph), handler.labels),
           joinBlock);
     }
     handler.close();
@@ -5848,7 +5853,7 @@
     //   }
 
     JumpTarget switchTarget = elements.getTargetDefinition(node);
-    HInstruction initialValue = graph.addConstantNull(compiler);
+    HInstruction initialValue = graph.addConstantNull(closedWorld);
     localsHandler.updateLocal(switchTarget, initialValue);
 
     JumpHandler jumpHandler = createJumpHandler(node, isLoopJump: false);
@@ -5884,11 +5889,11 @@
       if (switchCase != null) {
         // Generate 'target = i; break;' for switch case i.
         int index = caseIndex[switchCase];
-        HInstruction value = graph.addConstantInt(index, compiler);
+        HInstruction value = graph.addConstantInt(index, closedWorld);
         localsHandler.updateLocal(switchTarget, value);
       } else {
         // Generate synthetic default case 'target = null; break;'.
-        HInstruction value = graph.addConstantNull(compiler);
+        HInstruction value = graph.addConstantNull(closedWorld);
         localsHandler.updateLocal(switchTarget, value);
       }
       jumpTargets[switchTarget].generateBreak();
@@ -5898,7 +5903,7 @@
         isDefaultCase, buildSwitchCase);
     jumpHandler.close();
 
-    HInstruction buildCondition() => graph.addConstantBool(true, compiler);
+    HInstruction buildCondition() => graph.addConstantBool(true, closedWorld);
 
     void buildSwitch() {
       HInstruction buildExpression() {
@@ -5993,7 +5998,7 @@
       ast.SwitchCase switchCase = caseIterator.next();
       HBasicBlock block = graph.addNewBlock();
       for (ConstantValue constant in getConstants(switchCase)) {
-        HConstant hConstant = graph.addConstant(constant, compiler);
+        HConstant hConstant = graph.addConstant(constant, closedWorld);
         switchInstruction.inputs.add(hConstant);
         hConstant.usedBy.add(switchInstruction);
         expressionEnd.addSuccessor(block);
@@ -6076,8 +6081,8 @@
         new HSubExpressionBlockInformation(
             new SubExpression(expressionStart, expressionEnd));
     expressionStart.setBlockFlow(
-        new HSwitchBlockInformation(expressionInfo, statements,
-            jumpHandler.target, jumpHandler.labels()),
+        new HSwitchBlockInformation(
+            expressionInfo, statements, jumpHandler.target, jumpHandler.labels),
         joinBlock);
 
     jumpHandler.close();
@@ -6248,7 +6253,7 @@
           ast.VariableDefinitions declaration = catchBlock.formals.nodes.head;
           HInstruction condition = null;
           if (declaration.type == null) {
-            condition = graph.addConstantBool(true, compiler);
+            condition = graph.addConstantBool(true, closedWorld);
             stack.add(condition);
           } else {
             // TODO(aprelev@gmail.com): Once old catch syntax is removed
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index c02f096..7c92668 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:kernel/ast.dart' as ir;
-import 'package:kernel/text/ast_to_text.dart' show debugNodeToString;
 
 import '../closure.dart';
 import '../common.dart';
@@ -26,14 +25,15 @@
 import '../native/native.dart' as native;
 import '../resolution/tree_elements.dart';
 import '../tree/dartstring.dart';
-import '../tree/nodes.dart' show FunctionExpression, Node;
+import '../tree/nodes.dart' show Node, BreakStatement;
 import '../types/masks.dart';
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart';
-import '../universe/use.dart' show StaticUse, TypeUse;
 import '../universe/side_effects.dart' show SideEffects;
-import '../world.dart' show ClosedWorld;
+import '../universe/use.dart' show StaticUse;
+import '../world.dart';
 import 'graph_builder.dart';
+import 'jump_handler.dart';
 import 'kernel_ast_adapter.dart';
 import 'kernel_string_builder.dart';
 import 'locals_handler.dart';
@@ -53,15 +53,21 @@
       : backend = backend,
         super(backend.compiler.measurer);
 
-  HGraph build(CodegenWorkItem work) {
+  HGraph build(CodegenWorkItem work, ClosedWorld closedWorld) {
     return measure(() {
       AstElement element = work.element.implementation;
       Kernel kernel = backend.kernelTask.kernel;
-      KernelSsaBuilder builder = new KernelSsaBuilder(element, work.resolvedAst,
-          backend.compiler, work.registry, sourceInformationFactory, kernel);
+      KernelSsaBuilder builder = new KernelSsaBuilder(
+          element,
+          work.resolvedAst,
+          backend.compiler,
+          closedWorld,
+          work.registry,
+          sourceInformationFactory,
+          kernel);
       HGraph graph = builder.build();
 
-      if (backend.compiler.tracer.isEnabled) {
+      if (backend.tracer.isEnabled) {
         String name;
         if (element.isClassMember) {
           String className = element.enclosingClass.name;
@@ -73,8 +79,8 @@
         } else {
           name = "${element.name}";
         }
-        backend.compiler.tracer.traceCompilation(name);
-        backend.compiler.tracer.traceGraph('builder', graph);
+        backend.tracer.traceCompilation(name);
+        backend.tracer.traceGraph('builder', graph);
       }
 
       return graph;
@@ -86,6 +92,7 @@
   ir.Node target;
   final AstElement targetElement;
   final ResolvedAst resolvedAst;
+  final ClosedWorld closedWorld;
   final CodegenRegistry registry;
 
   /// Helper accessor for all kernel function-like targets (Procedure,
@@ -126,6 +133,7 @@
       this.targetElement,
       this.resolvedAst,
       Compiler compiler,
+      this.closedWorld,
       this.registry,
       SourceInformationStrategy sourceInformationFactory,
       Kernel kernel) {
@@ -192,7 +200,7 @@
           fieldValue, astAdapter.getDartType(field.type));
       stack.add(checkInstruction);
     } else {
-      stack.add(graph.addConstantNull(compiler));
+      stack.add(graph.addConstantNull(closedWorld));
     }
     HInstruction value = pop();
     closeAndGotoExit(new HReturn(value, null));
@@ -267,7 +275,7 @@
 
     for (var field in clazz.fields) {
       if (field.initializer == null) {
-        fieldValues[field] = graph.addConstantNull(compiler);
+        fieldValues[field] = graph.addConstantNull(closedWorld);
       } else {
         field.initializer.accept(this);
         fieldValues[field] = pop();
@@ -332,7 +340,7 @@
               backend.constants.getConstantValue(element.constant);
           assert(invariant(element, constantValue != null,
               message: 'No constant computed for $element'));
-          builtArguments.add(graph.addConstant(constantValue, compiler));
+          builtArguments.add(graph.addConstant(constantValue, closedWorld));
         }
       });
     } else {
@@ -348,7 +356,7 @@
               backend.constants.getConstantValue(element.constant);
           assert(invariant(element, constantValue != null,
               message: 'No constant computed for $element'));
-          builtArguments.add(graph.addConstant(constantValue, compiler));
+          builtArguments.add(graph.addConstant(constantValue, closedWorld));
         }
       });
     }
@@ -428,7 +436,7 @@
 
   /// Pushes a boolean checking [expression] against null.
   pushCheckNull(HInstruction expression) {
-    push(new HIdentity(expression, graph.addConstantNull(compiler), null,
+    push(new HIdentity(expression, graph.addConstantNull(closedWorld), null,
         commonMasks.boolType));
   }
 
@@ -445,9 +453,9 @@
   }
 
   void _trap(String message) {
-    HInstruction nullValue = graph.addConstantNull(compiler);
+    HInstruction nullValue = graph.addConstantNull(closedWorld);
     HInstruction errorMessage =
-        graph.addConstantString(new DartString.literal(message), compiler);
+        graph.addConstantString(new DartString.literal(message), closedWorld);
     HInstruction trap = new HForeignCode(js.js.parseForeignJS("#.#"),
         commonMasks.dynamicType, <HInstruction>[nullValue, errorMessage]);
     trap.sideEffects
@@ -507,7 +515,7 @@
   void visitReturnStatement(ir.ReturnStatement returnStatement) {
     HInstruction value;
     if (returnStatement.expression == null) {
-      value = graph.addConstantNull(compiler);
+      value = graph.addConstantNull(closedWorld);
     } else {
       assert(_targetFunction != null && _targetFunction is ir.FunctionNode);
       returnStatement.expression.accept(this);
@@ -532,7 +540,7 @@
 
     HInstruction buildCondition() {
       if (forStatement.condition == null) {
-        return graph.addConstantBool(true, compiler);
+        return graph.addConstantBool(true, closedWorld);
       }
       forStatement.condition.accept(this);
       return popBoolified();
@@ -564,7 +572,7 @@
     }
     // If the expression being iterated over is a JS indexable type, we can
     // generate an optimized version of for-in that uses indexing.
-    if (astAdapter.isJsIndexableIterator(forInStatement)) {
+    if (astAdapter.isJsIndexableIterator(forInStatement, closedWorld)) {
       _buildForInIndexable(forInStatement);
     } else {
       _buildForInIterator(forInStatement);
@@ -617,9 +625,9 @@
     void buildInitializer() {
       forInStatement.iterable.accept(this);
       array = pop();
-      isFixed = astAdapter.isFixedLength(array.instructionType);
+      isFixed = astAdapter.isFixedLength(array.instructionType, closedWorld);
       localsHandler.updateLocal(
-          indexVariable, graph.addConstantInt(0, compiler));
+          indexVariable, graph.addConstantInt(0, closedWorld));
       originalLength = buildGetLength();
     }
 
@@ -664,7 +672,7 @@
       // but the code is horrible as `i+1` is carried around the loop in an
       // additional variable.
       HInstruction index = localsHandler.readLocal(indexVariable);
-      HInstruction one = graph.addConstantInt(1, compiler);
+      HInstruction one = graph.addConstantInt(1, closedWorld);
       HInstruction addInstruction =
           new HAdd(index, one, null, commonMasks.positiveIntType);
       add(addInstruction);
@@ -783,7 +791,7 @@
 
   void generateError(ir.Node node, String message, TypeMask typeMask) {
     HInstruction errorMessage =
-        graph.addConstantString(new DartString.literal(message), compiler);
+        graph.addConstantString(new DartString.literal(message), closedWorld);
     _pushStaticInvocation(node, [errorMessage], typeMask);
   }
 
@@ -820,6 +828,59 @@
   }
 
   @override
+  void visitBreakStatement(ir.BreakStatement breakStatement) {
+    assert(!isAborted());
+    JumpTarget target = astAdapter.getJumpTarget(breakStatement.target);
+    assert(target != null);
+    JumpHandler handler = jumpTargets[target];
+    assert(handler != null);
+    handler.generateBreak(handler.labels.first);
+  }
+
+  @override
+  void visitLabeledStatement(ir.LabeledStatement labeledStatement) {
+    JumpTarget target = astAdapter.getJumpTarget(labeledStatement);
+    JumpHandler handler = new JumpHandler(this, target);
+
+    ir.Statement body = labeledStatement.body;
+    if (body is ir.WhileStatement ||
+        body is ir.DoStatement ||
+        body is ir.ForStatement ||
+        body is ir.ForInStatement) {
+      // loops handle breaks on their own
+      body.accept(this);
+      return;
+    }
+    LocalsHandler beforeLocals = new LocalsHandler.from(localsHandler);
+
+    HBasicBlock newBlock = openNewBlock();
+    body.accept(this);
+    SubGraph bodyGraph = new SubGraph(newBlock, lastOpenedBlock);
+
+    HBasicBlock joinBlock = graph.addNewBlock();
+    List<LocalsHandler> breakHandlers = <LocalsHandler>[];
+    handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) {
+      breakInstruction.block.addSuccessor(joinBlock);
+      breakHandlers.add(locals);
+    });
+
+    if (!isAborted()) {
+      goto(current, joinBlock);
+      breakHandlers.add(localsHandler);
+    }
+
+    open(joinBlock);
+    localsHandler = beforeLocals.mergeMultiple(breakHandlers, joinBlock);
+
+    // There was at least one reachable break, so the label is needed.
+    newBlock.setBlockFlow(
+        new HLabeledBlockInformation(
+            new HSubGraphBlockInformation(bodyGraph), handler.labels),
+        joinBlock);
+    handler.close();
+  }
+
+  @override
   void visitConditionalExpression(ir.ConditionalExpression conditional) {
     SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler);
     brancher.handleConditional(
@@ -838,35 +899,35 @@
 
   @override
   void visitIntLiteral(ir.IntLiteral intLiteral) {
-    stack.add(graph.addConstantInt(intLiteral.value, compiler));
+    stack.add(graph.addConstantInt(intLiteral.value, closedWorld));
   }
 
   @override
   void visitDoubleLiteral(ir.DoubleLiteral doubleLiteral) {
-    stack.add(graph.addConstantDouble(doubleLiteral.value, compiler));
+    stack.add(graph.addConstantDouble(doubleLiteral.value, closedWorld));
   }
 
   @override
   void visitBoolLiteral(ir.BoolLiteral boolLiteral) {
-    stack.add(graph.addConstantBool(boolLiteral.value, compiler));
+    stack.add(graph.addConstantBool(boolLiteral.value, closedWorld));
   }
 
   @override
   void visitStringLiteral(ir.StringLiteral stringLiteral) {
     stack.add(graph.addConstantString(
-        new DartString.literal(stringLiteral.value), compiler));
+        new DartString.literal(stringLiteral.value), closedWorld));
   }
 
   @override
   void visitSymbolLiteral(ir.SymbolLiteral symbolLiteral) {
     stack.add(graph.addConstant(
-        astAdapter.getConstantForSymbol(symbolLiteral), compiler));
+        astAdapter.getConstantForSymbol(symbolLiteral), closedWorld));
     registry?.registerConstSymbol(symbolLiteral.value);
   }
 
   @override
   void visitNullLiteral(ir.NullLiteral nullLiteral) {
-    stack.add(graph.addConstantNull(compiler));
+    stack.add(graph.addConstantNull(closedWorld));
   }
 
   /// Set the runtime type information if necessary.
@@ -890,8 +951,8 @@
   void visitListLiteral(ir.ListLiteral listLiteral) {
     HInstruction listInstruction;
     if (listLiteral.isConst) {
-      listInstruction =
-          graph.addConstant(astAdapter.getConstantFor(listLiteral), compiler);
+      listInstruction = graph.addConstant(
+          astAdapter.getConstantFor(listLiteral), closedWorld);
     } else {
       List<HInstruction> elements = <HInstruction>[];
       for (ir.Expression element in listLiteral.expressions) {
@@ -905,7 +966,8 @@
           setListRuntimeTypeInfoIfNeeded(listInstruction, listLiteral);
     }
 
-    TypeMask type = astAdapter.typeOfListLiteral(targetElement, listLiteral);
+    TypeMask type =
+        astAdapter.typeOfListLiteral(targetElement, listLiteral, closedWorld);
     if (!type.containsAll(closedWorld)) {
       listInstruction.instructionType = type;
     }
@@ -915,8 +977,8 @@
   @override
   void visitMapLiteral(ir.MapLiteral mapLiteral) {
     if (mapLiteral.isConst) {
-      stack.add(
-          graph.addConstant(astAdapter.getConstantFor(mapLiteral), compiler));
+      stack.add(graph.addConstant(
+          astAdapter.getConstantFor(mapLiteral), closedWorld));
       return;
     }
 
@@ -1001,7 +1063,7 @@
     ir.DartType type = typeLiteral.type;
     if (type is ir.InterfaceType) {
       ConstantValue constant = astAdapter.getConstantForType(type);
-      stack.add(graph.addConstant(constant, compiler));
+      stack.add(graph.addConstant(constant, closedWorld));
       return;
     }
     if (type is ir.TypeParameterType) {
@@ -1033,7 +1095,7 @@
     } else if (staticTarget is ir.Field && staticTarget.isConst) {
       assert(staticTarget.initializer != null);
       stack.add(graph.addConstant(
-          astAdapter.getConstantFor(staticTarget.initializer), compiler));
+          astAdapter.getConstantFor(staticTarget.initializer), closedWorld));
     } else {
       if (_isLazyStatic(staticTarget)) {
         push(new HLazyStatic(astAdapter.getField(staticTarget),
@@ -1098,7 +1160,9 @@
     propertySet.value.accept(this);
     HInstruction value = pop();
 
-    _pushDynamicInvocation(propertySet, astAdapter.typeOfSet(propertySet),
+    _pushDynamicInvocation(
+        propertySet,
+        astAdapter.typeOfSet(propertySet, closedWorld),
         <HInstruction>[receiver, value]);
 
     pop();
@@ -1116,7 +1180,7 @@
   void visitVariableDeclaration(ir.VariableDeclaration declaration) {
     Local local = astAdapter.getLocal(declaration);
     if (declaration.initializer == null) {
-      HInstruction initialValue = graph.addConstantNull(compiler);
+      HInstruction initialValue = graph.addConstantNull(closedWorld);
       localsHandler.updateLocal(local, initialValue);
     } else {
       declaration.initializer.accept(this);
@@ -1231,12 +1295,12 @@
 
   HInstruction _defaultValueForParameter(ir.VariableDeclaration parameter) {
     ir.Expression initializer = parameter.initializer;
-    if (initializer == null) return graph.addConstantNull(compiler);
+    if (initializer == null) return graph.addConstantNull(closedWorld);
     // TODO(sra): Evaluate constant in ir.Node domain.
     ConstantValue constant =
         astAdapter.getConstantForParameterDefaultValue(initializer);
-    if (constant == null) return graph.addConstantNull(compiler);
-    return graph.addConstant(constant, compiler);
+    if (constant == null) return graph.addConstantNull(closedWorld);
+    return graph.addConstant(constant, closedWorld);
   }
 
   @override
@@ -1282,7 +1346,7 @@
     } else if (name == 'JS_GET_FLAG') {
       handleForeignJsGetFlag(invocation);
     } else if (name == 'JS_EFFECT') {
-      stack.add(graph.addConstantNull(compiler));
+      stack.add(graph.addConstantNull(closedWorld));
     } else if (name == 'JS_INTERCEPTOR_CONSTANT') {
       handleJsInterceptorConstant(invocation);
     } else if (name == 'JS_STRING_CONCAT') {
@@ -1368,7 +1432,8 @@
 
   void handleForeignJsCurrentIsolateContext(ir.StaticInvocation invocation) {
     if (_unexpectedForeignArguments(invocation, 0, 0)) {
-      stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+      // Result expected on stack.
+      stack.add(graph.addConstantNull(closedWorld));
       return;
     }
 
@@ -1394,7 +1459,8 @@
 
   void handleForeignJsCallInIsolate(ir.StaticInvocation invocation) {
     if (_unexpectedForeignArguments(invocation, 2, 2)) {
-      stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+      // Result expected on stack.
+      stack.add(graph.addConstantNull(closedWorld));
       return;
     }
 
@@ -1426,7 +1492,8 @@
   void handleForeignRawFunctionRef(
       ir.StaticInvocation invocation, String name) {
     if (_unexpectedForeignArguments(invocation, 1, 1)) {
-      stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+      // Result expected on stack.
+      stack.add(graph.addConstantNull(closedWorld));
       return;
     }
 
@@ -1458,13 +1525,14 @@
 
     compiler.reporter.reportErrorMessage(astAdapter.getNode(invocation),
         MessageKind.GENERIC, {'text': "'$name' $problem."});
-    stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+    stack.add(graph.addConstantNull(closedWorld)); // Result expected on stack.
     return;
   }
 
   void handleForeignJsSetStaticState(ir.StaticInvocation invocation) {
     if (_unexpectedForeignArguments(invocation, 1, 1)) {
-      stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+      // Result expected on stack.
+      stack.add(graph.addConstantNull(closedWorld));
       return;
     }
 
@@ -1481,7 +1549,8 @@
 
   void handleForeignJsGetStaticState(ir.StaticInvocation invocation) {
     if (_unexpectedForeignArguments(invocation, 0, 0)) {
-      stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+      // Result expected on stack.
+      stack.add(graph.addConstantNull(closedWorld));
       return;
     }
 
@@ -1492,7 +1561,8 @@
 
   void handleForeignJsGetName(ir.StaticInvocation invocation) {
     if (_unexpectedForeignArguments(invocation, 1, 1)) {
-      stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+      // Result expected on stack.
+      stack.add(graph.addConstantNull(closedWorld));
       return;
     }
 
@@ -1503,7 +1573,7 @@
     if (instruction is HConstant) {
       js.Name name =
           astAdapter.getNameForJsGetName(argument, instruction.constant);
-      stack.add(graph.addConstantStringFromName(name, compiler));
+      stack.add(graph.addConstantStringFromName(name, closedWorld));
       return;
     }
 
@@ -1511,12 +1581,14 @@
         astAdapter.getNode(argument),
         MessageKind.GENERIC,
         {'text': 'Error: Expected a JsGetName enum value.'});
-    stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+    // Result expected on stack.
+    stack.add(graph.addConstantNull(closedWorld));
   }
 
   void handleForeignJsEmbeddedGlobal(ir.StaticInvocation invocation) {
     if (_unexpectedForeignArguments(invocation, 2, 2)) {
-      stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+      // Result expected on stack.
+      stack.add(graph.addConstantNull(closedWorld));
       return;
     }
     String globalName = _foreignConstantStringArgument(
@@ -1529,14 +1601,16 @@
     assert(invariant(astAdapter.getNode(invocation), nativeBehavior != null,
         message: "No NativeBehavior for $invocation"));
 
-    TypeMask ssaType = astAdapter.typeFromNativeBehavior(nativeBehavior);
+    TypeMask ssaType =
+        astAdapter.typeFromNativeBehavior(nativeBehavior, closedWorld);
     push(new HForeignCode(expr, ssaType, const <HInstruction>[],
         nativeBehavior: nativeBehavior));
   }
 
   void handleForeignJsBuiltin(ir.StaticInvocation invocation) {
     if (_unexpectedForeignArguments(invocation, 2)) {
-      stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+      // Result expected on stack.
+      stack.add(graph.addConstantNull(closedWorld));
       return;
     }
 
@@ -1555,7 +1629,8 @@
           astAdapter.getNode(nameArgument),
           MessageKind.GENERIC,
           {'text': 'Error: Expected a JsBuiltin enum value.'});
-      stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+      // Result expected on stack.
+      stack.add(graph.addConstantNull(closedWorld));
       return;
     }
 
@@ -1570,7 +1645,8 @@
     assert(invariant(astAdapter.getNode(invocation), nativeBehavior != null,
         message: "No NativeBehavior for $invocation"));
 
-    TypeMask ssaType = astAdapter.typeFromNativeBehavior(nativeBehavior);
+    TypeMask ssaType =
+        astAdapter.typeFromNativeBehavior(nativeBehavior, closedWorld);
     push(new HForeignCode(template, ssaType, inputs,
         nativeBehavior: nativeBehavior));
   }
@@ -1578,7 +1654,8 @@
   void handleForeignJsGetFlag(ir.StaticInvocation invocation) {
     if (_unexpectedForeignArguments(invocation, 1, 1)) {
       stack.add(
-          graph.addConstantBool(false, compiler)); // Result expected on stack.
+          // Result expected on stack.
+          graph.addConstantBool(false, closedWorld));
       return;
     }
     String name = _foreignConstantStringArgument(invocation, 0, 'JS_GET_FLAG');
@@ -1596,14 +1673,15 @@
             MessageKind.GENERIC,
             {'text': 'Error: Unknown internal flag "$name".'});
     }
-    stack.add(graph.addConstantBool(value, compiler));
+    stack.add(graph.addConstantBool(value, closedWorld));
   }
 
   void handleJsInterceptorConstant(ir.StaticInvocation invocation) {
     // Single argument must be a TypeConstant which is converted into a
     // InterceptorConstant.
     if (_unexpectedForeignArguments(invocation, 1, 1)) {
-      stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+      // Result expected on stack.
+      stack.add(graph.addConstantNull(closedWorld));
       return;
     }
     ir.Expression argument = invocation.arguments.positional.single;
@@ -1615,7 +1693,7 @@
         // TODO(sra): Check that type is a subclass of [Interceptor].
         ConstantValue constant =
             new InterceptorConstantValue(argumentConstant.representedType);
-        HInstruction instruction = graph.addConstant(constant, compiler);
+        HInstruction instruction = graph.addConstant(constant, closedWorld);
         stack.add(instruction);
         return;
       }
@@ -1623,12 +1701,13 @@
 
     compiler.reporter.reportErrorMessage(astAdapter.getNode(invocation),
         MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT);
-    stack.add(graph.addConstantNull(compiler));
+    stack.add(graph.addConstantNull(closedWorld));
   }
 
   void handleForeignJs(ir.StaticInvocation invocation) {
     if (_unexpectedForeignArguments(invocation, 2)) {
-      stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+      // Result expected on stack.
+      stack.add(graph.addConstantNull(closedWorld));
       return;
     }
 
@@ -1649,7 +1728,8 @@
         'text': 'Mismatch between number of placeholders'
             ' and number of arguments.'
       });
-      stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+      // Result expected on stack.
+      stack.add(graph.addConstantNull(closedWorld));
       return;
     }
 
@@ -1658,7 +1738,8 @@
           astAdapter.getNode(invocation), MessageKind.JS_PLACEHOLDER_CAPTURE);
     }
 
-    TypeMask ssaType = astAdapter.typeFromNativeBehavior(nativeBehavior);
+    TypeMask ssaType =
+        astAdapter.typeFromNativeBehavior(nativeBehavior, closedWorld);
 
     SourceInformation sourceInformation = null;
     push(new HForeignCode(nativeBehavior.codeTemplate, ssaType, inputs,
@@ -1669,7 +1750,8 @@
 
   void handleJsStringConcat(ir.StaticInvocation invocation) {
     if (_unexpectedForeignArguments(invocation, 2, 2)) {
-      stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+      // Result expected on stack.
+      stack.add(graph.addConstantNull(closedWorld));
       return;
     }
     List<HInstruction> inputs = _visitPositionalArguments(invocation.arguments);
@@ -1680,12 +1762,12 @@
       ir.Node target, List<HInstruction> arguments, TypeMask typeMask) {
     HInvokeStatic instruction = new HInvokeStatic(
         astAdapter.getMember(target), arguments, typeMask,
-        targetCanThrow: astAdapter.getCanThrow(target));
+        targetCanThrow: astAdapter.getCanThrow(target, closedWorld));
     if (currentImplicitInstantiations.isNotEmpty) {
       instruction.instantiatedTypes =
           new List<DartType>.from(currentImplicitInstantiations);
     }
-    instruction.sideEffects = astAdapter.getSideEffects(target);
+    instruction.sideEffects = astAdapter.getSideEffects(target, closedWorld);
 
     push(instruction);
   }
@@ -1771,7 +1853,7 @@
     Selector selector = astAdapter.getSelector(invocation);
     _pushDynamicInvocation(
         invocation,
-        astAdapter.typeOfInvocation(invocation),
+        astAdapter.typeOfInvocation(invocation, closedWorld),
         <HInstruction>[receiver]
           ..addAll(
               _visitArgumentsForDynamicTarget(selector, invocation.arguments)));
@@ -1867,7 +1949,7 @@
     type = localsHandler.substInContext(type).unaliased;
 
     if (type is MethodTypeVariableType) {
-      return graph.addConstantBool(true, compiler);
+      return graph.addConstantBool(true, closedWorld);
     }
 
     if (type is MalformedType) {
@@ -2124,8 +2206,8 @@
             catchBlock.exception, catchBlock.guard, unwrappedException);
         kernelBuilder.push(condition);
       } else {
-        kernelBuilder.stack.add(
-            kernelBuilder.graph.addConstantBool(true, kernelBuilder.compiler));
+        kernelBuilder.stack.add(kernelBuilder.graph
+            .addConstantBool(true, kernelBuilder.closedWorld));
       }
     }
 
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 98ccfb1..bf90d8e 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -59,36 +59,41 @@
             .buildDeclaration(resolvedAst));
   }
 
-  js.Expression generateCode(CodegenWorkItem work, HGraph graph) {
+  js.Expression generateCode(
+      CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) {
     if (work.element.isField) {
-      return generateLazyInitializer(work, graph);
+      return generateLazyInitializer(work, graph, closedWorld);
     } else {
-      return generateMethod(work, graph);
+      return generateMethod(work, graph, closedWorld);
     }
   }
 
-  js.Expression generateLazyInitializer(CodegenWorkItem work, HGraph graph) {
+  js.Expression generateLazyInitializer(
+      CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) {
     return measure(() {
-      compiler.tracer.traceGraph("codegen", graph);
+      backend.tracer.traceGraph("codegen", graph);
       SourceInformation sourceInformation = sourceInformationFactory
           .createBuilderForContext(work.resolvedAst)
           .buildDeclaration(work.resolvedAst);
-      SsaCodeGenerator codegen = new SsaCodeGenerator(backend, work);
+      SsaCodeGenerator codegen =
+          new SsaCodeGenerator(backend, closedWorld, work);
       codegen.visitGraph(graph);
       return new js.Fun(codegen.parameters, codegen.body)
           .withSourceInformation(sourceInformation);
     });
   }
 
-  js.Expression generateMethod(CodegenWorkItem work, HGraph graph) {
+  js.Expression generateMethod(
+      CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) {
     return measure(() {
       FunctionElement element = work.element;
       if (element.asyncMarker != AsyncMarker.SYNC) {
         work.registry.registerAsyncMarker(element);
       }
-      SsaCodeGenerator codegen = new SsaCodeGenerator(backend, work);
+      SsaCodeGenerator codegen =
+          new SsaCodeGenerator(backend, closedWorld, work);
       codegen.visitGraph(graph);
-      compiler.tracer.traceGraph("codegen", graph);
+      backend.tracer.traceGraph("codegen", graph);
       return buildJavaScriptFunction(
           work.resolvedAst, codegen.parameters, codegen.body);
     });
@@ -121,6 +126,7 @@
   bool isGeneratingExpression = false;
 
   final JavaScriptBackend backend;
+  final ClosedWorld closedWorld;
   final CodegenWorkItem work;
 
   final Set<HInstruction> generateAtUseSite;
@@ -163,7 +169,7 @@
   // if branches.
   SubGraph subGraph;
 
-  SsaCodeGenerator(this.backend, CodegenWorkItem work,
+  SsaCodeGenerator(this.backend, this.closedWorld, CodegenWorkItem work,
       {SourceInformation sourceInformation})
       : this.work = work,
         declaredLocals = new Set<String>(),
@@ -179,8 +185,6 @@
 
   Compiler get compiler => backend.compiler;
 
-  ClosedWorld get closedWorld => compiler.closedWorld;
-
   NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter;
 
   CodegenRegistry get registry => work.registry;
@@ -830,7 +834,7 @@
     js.Loop loop;
 
     switch (info.kind) {
-      // Treate all three "test-first" loops the same way.
+      // Treat all three "test-first" loops the same way.
       case HLoopBlockInformation.FOR_LOOP:
       case HLoopBlockInformation.WHILE_LOOP:
       case HLoopBlockInformation.FOR_IN_LOOP:
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index 6058b66..75109a9 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -147,7 +147,7 @@
         ConstantValue constant = new SyntheticConstantValue(
             SyntheticConstantKind.DUMMY_INTERCEPTOR,
             receiverArgument.instructionType);
-        HConstant dummy = graph.addConstant(constant, compiler);
+        HConstant dummy = graph.addConstant(constant, closedWorld);
         receiverArgument.usedBy.remove(node);
         node.inputs[1] = dummy;
         dummy.usedBy.add(node);
diff --git a/pkg/compiler/lib/src/ssa/graph_builder.dart b/pkg/compiler/lib/src/ssa/graph_builder.dart
index ed7683a..35566b8 100644
--- a/pkg/compiler/lib/src/ssa/graph_builder.dart
+++ b/pkg/compiler/lib/src/ssa/graph_builder.dart
@@ -6,6 +6,7 @@
 import '../common.dart';
 import '../common/codegen.dart' show CodegenRegistry;
 import '../compiler.dart';
+import '../constants/constant_system.dart';
 import '../dart_types.dart';
 import '../elements/elements.dart';
 import '../io/source_information.dart';
@@ -42,7 +43,7 @@
 
   CodegenRegistry get registry;
 
-  ClosedWorld get closedWorld => compiler.closedWorld;
+  ClosedWorld get closedWorld;
 
   CommonMasks get commonMasks => closedWorld.commonMasks;
 
@@ -82,7 +83,7 @@
 
   /// Pushes a boolean checking [expression] against null.
   pushCheckNull(HInstruction expression) {
-    push(new HIdentity(expression, graph.addConstantNull(compiler), null,
+    push(new HIdentity(expression, graph.addConstantNull(closedWorld), null,
         closedWorld.commonMasks.boolType));
   }
 
@@ -292,7 +293,8 @@
     List<String> names = type.namedParameters;
     for (int index = 0; index < names.length; index++) {
       ast.DartString dartString = new ast.DartString.literal(names[index]);
-      inputs.add(builder.graph.addConstantString(dartString, builder.compiler));
+      inputs.add(
+          builder.graph.addConstantString(dartString, builder.closedWorld));
       namedParameterTypes[index].accept(this, builder);
       inputs.add(builder.pop());
     }
diff --git a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
index 17de116..2d6a1a7 100644
--- a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
+++ b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
@@ -37,19 +37,19 @@
 class SsaSimplifyInterceptors extends HBaseVisitor
     implements OptimizationPhase {
   final String name = "SsaSimplifyInterceptors";
-  final ConstantSystem constantSystem;
+  final ClosedWorld closedWorld;
   final Compiler compiler;
   final Element element;
   HGraph graph;
 
-  SsaSimplifyInterceptors(this.compiler, this.constantSystem, this.element);
+  SsaSimplifyInterceptors(this.compiler, this.closedWorld, this.element);
 
   JavaScriptBackend get backend => compiler.backend;
 
-  ClosedWorld get closedWorld => compiler.closedWorld;
-
   BackendClasses get backendClasses => closedWorld.backendClasses;
 
+  ConstantSystem get constantSystem => closedWorld.constantSystem;
+
   void visitGraph(HGraph graph) {
     this.graph = graph;
     visitDominatorTree(graph);
@@ -136,7 +136,7 @@
 
     ConstantValue constant =
         new InterceptorConstantValue(constantInterceptor.thisType);
-    return graph.addConstant(constant, compiler);
+    return graph.addConstant(constant, closedWorld);
   }
 
   ClassElement tryComputeConstantInterceptorFromType(
@@ -320,7 +320,7 @@
           if (interceptorClass != null) {
             HInstruction constantInstruction = graph.addConstant(
                 new InterceptorConstantValue(interceptorClass.thisType),
-                compiler);
+                closedWorld);
             node.conditionalConstantInterceptor = constantInstruction;
             constantInstruction.usedBy.add(node);
             return false;
@@ -360,7 +360,7 @@
     } else if (user is HInvokeDynamic) {
       if (node == user.inputs[0]) {
         // Replace the user with a [HOneShotInterceptor].
-        HConstant nullConstant = graph.addConstantNull(compiler);
+        HConstant nullConstant = graph.addConstantNull(closedWorld);
         List<HInstruction> inputs = new List<HInstruction>.from(user.inputs);
         inputs[0] = nullConstant;
         HOneShotInterceptor oneShotInterceptor = new HOneShotInterceptor(
diff --git a/pkg/compiler/lib/src/ssa/jump_handler.dart b/pkg/compiler/lib/src/ssa/jump_handler.dart
index a50d496..d401ca8 100644
--- a/pkg/compiler/lib/src/ssa/jump_handler.dart
+++ b/pkg/compiler/lib/src/ssa/jump_handler.dart
@@ -12,12 +12,12 @@
 import 'nodes.dart';
 
 /// A single break/continue instruction.
-class JumpHandlerEntry {
+class _JumpHandlerEntry {
   final HJump jumpInstruction;
   final LocalsHandler locals;
   bool isBreak() => jumpInstruction is HBreak;
   bool isContinue() => jumpInstruction is HContinue;
-  JumpHandlerEntry(this.jumpInstruction, this.locals);
+  _JumpHandlerEntry(this.jumpInstruction, this.locals);
 }
 
 abstract class JumpHandler {
@@ -33,7 +33,7 @@
   bool hasAnyBreak();
   void close();
   final JumpTarget target;
-  List<LabelDefinition> labels();
+  List<LabelDefinition> get labels;
 }
 
 /// Jump handler used to avoid null checks when a target isn't used as the
@@ -60,7 +60,7 @@
   bool hasAnyContinue() => false;
   bool hasAnyBreak() => false;
 
-  List<LabelDefinition> labels() => const <LabelDefinition>[];
+  List<LabelDefinition> get labels => const <LabelDefinition>[];
   JumpTarget get target => null;
 }
 
@@ -71,11 +71,11 @@
 class TargetJumpHandler implements JumpHandler {
   final GraphBuilder builder;
   final JumpTarget target;
-  final List<JumpHandlerEntry> jumps;
+  final List<_JumpHandlerEntry> jumps;
 
   TargetJumpHandler(GraphBuilder builder, this.target)
       : this.builder = builder,
-        jumps = <JumpHandlerEntry>[] {
+        jumps = <_JumpHandlerEntry>[] {
     assert(builder.jumpTargets[target] == null);
     builder.jumpTargets[target] = this;
   }
@@ -89,7 +89,7 @@
     }
     LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
     builder.close(breakInstruction);
-    jumps.add(new JumpHandlerEntry(breakInstruction, locals));
+    jumps.add(new _JumpHandlerEntry(breakInstruction, locals));
   }
 
   void generateContinue([LabelDefinition label]) {
@@ -104,30 +104,30 @@
     }
     LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
     builder.close(continueInstruction);
-    jumps.add(new JumpHandlerEntry(continueInstruction, locals));
+    jumps.add(new _JumpHandlerEntry(continueInstruction, locals));
   }
 
   void forEachBreak(Function action) {
-    for (JumpHandlerEntry entry in jumps) {
+    for (_JumpHandlerEntry entry in jumps) {
       if (entry.isBreak()) action(entry.jumpInstruction, entry.locals);
     }
   }
 
   void forEachContinue(Function action) {
-    for (JumpHandlerEntry entry in jumps) {
+    for (_JumpHandlerEntry entry in jumps) {
       if (entry.isContinue()) action(entry.jumpInstruction, entry.locals);
     }
   }
 
   bool hasAnyContinue() {
-    for (JumpHandlerEntry entry in jumps) {
+    for (_JumpHandlerEntry entry in jumps) {
       if (entry.isContinue()) return true;
     }
     return false;
   }
 
   bool hasAnyBreak() {
-    for (JumpHandlerEntry entry in jumps) {
+    for (_JumpHandlerEntry entry in jumps) {
       if (entry.isBreak()) return true;
     }
     return false;
@@ -138,13 +138,13 @@
     builder.jumpTargets.remove(target);
   }
 
-  List<LabelDefinition> labels() {
+  List<LabelDefinition> get labels {
     List<LabelDefinition> result = null;
     for (LabelDefinition element in target.labels) {
-      if (result == null) result = <LabelDefinition>[];
+      result ??= <LabelDefinition>[];
       result.add(element);
     }
-    return (result == null) ? const <LabelDefinition>[] : result;
+    return result ?? const <LabelDefinition>[];
   }
 }
 
@@ -191,7 +191,7 @@
           new HBreak(target, breakSwitchContinueLoop: true);
       LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
       builder.close(breakInstruction);
-      jumps.add(new JumpHandlerEntry(breakInstruction, locals));
+      jumps.add(new _JumpHandlerEntry(breakInstruction, locals));
     } else {
       super.generateBreak(label);
     }
@@ -211,14 +211,14 @@
       // TODO(het): change the graph 'addConstantXXX' to take a ConstantSystem
       // instead of a Compiler.
       HInstruction value = builder.graph
-          .addConstantInt(targetIndexMap[label.target], builder.compiler);
+          .addConstantInt(targetIndexMap[label.target], builder.closedWorld);
       builder.localsHandler.updateLocal(target, value);
 
       assert(label.target.labels.contains(label));
       HInstruction continueInstruction = new HContinue(target);
       LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
       builder.close(continueInstruction);
-      jumps.add(new JumpHandlerEntry(continueInstruction, locals));
+      jumps.add(new _JumpHandlerEntry(continueInstruction, locals));
     } else {
       super.generateContinue(label);
     }
diff --git a/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart b/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
index ab92877..00e92f8 100644
--- a/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
+++ b/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
@@ -5,13 +5,14 @@
 import 'package:js_runtime/shared/embedded_names.dart';
 import 'package:kernel/ast.dart' as ir;
 
-import '../constants/expressions.dart';
 import '../common.dart';
 import '../common/names.dart';
 import '../compiler.dart';
+import '../constants/expressions.dart';
 import '../constants/values.dart';
 import '../dart_types.dart';
 import '../elements/elements.dart';
+import '../elements/modelx.dart';
 import '../js/js.dart' as js;
 import '../js_backend/backend_helpers.dart';
 import '../js_backend/js_backend.dart';
@@ -40,6 +41,8 @@
   final Map<ir.Node, Element> _nodeToElement;
   final Map<ir.VariableDeclaration, SyntheticLocal> _syntheticLocals =
       <ir.VariableDeclaration, SyntheticLocal>{};
+  final Map<ir.LabeledStatement, KernelJumpTarget> _jumpTargets =
+      <ir.LabeledStatement, KernelJumpTarget>{};
   DartTypeConverter _typeConverter;
 
   KernelAstAdapter(this.kernel, this._backend, this._resolvedAst,
@@ -67,7 +70,6 @@
   TreeElements get elements => _resolvedAst.elements;
   DiagnosticReporter get reporter => _compiler.reporter;
   Element get _target => _resolvedAst.element;
-  ClosedWorld get _closedWorld => _compiler.closedWorld;
 
   GlobalTypeInferenceResults get _globalInferenceResults =>
       _compiler.globalInference.results;
@@ -129,9 +131,9 @@
     return getElement(variable) as LocalElement;
   }
 
-  bool getCanThrow(ir.Node procedure) {
+  bool getCanThrow(ir.Node procedure, ClosedWorld closedWorld) {
     FunctionElement function = getElement(procedure);
-    return !_closedWorld.getCannotThrow(function);
+    return !closedWorld.getCannotThrow(function);
   }
 
   TypeMask returnTypeOf(ir.Member node) {
@@ -139,8 +141,8 @@
         getElement(node), _globalInferenceResults);
   }
 
-  SideEffects getSideEffects(ir.Node node) {
-    return _closedWorld.getSideEffectsOfElement(getElement(node));
+  SideEffects getSideEffects(ir.Node node, ClosedWorld closedWorld) {
+    return closedWorld.getSideEffectsOfElement(getElement(node));
   }
 
   CallStructure getCallStructure(ir.Arguments arguments) {
@@ -202,13 +204,13 @@
     return new Selector.setter(name);
   }
 
-  TypeMask typeOfInvocation(ir.MethodInvocation send) {
+  TypeMask typeOfInvocation(ir.MethodInvocation send, ClosedWorld closedWorld) {
     ast.Node operatorNode = kernel.nodeToAstOperator[send];
     if (operatorNode != null) {
       return _resultOf(_target).typeOfOperator(operatorNode);
     }
     if (send.name.name == '[]=') {
-      return _compiler.closedWorld.commonMasks.dynamicType;
+      return closedWorld.commonMasks.dynamicType;
     }
     return _resultOf(_target).typeOfSend(getNode(send));
   }
@@ -217,8 +219,8 @@
     return _resultOf(_target).typeOfSend(getNode(getter));
   }
 
-  TypeMask typeOfSet(ir.PropertySet setter) {
-    return _closedWorld.commonMasks.dynamicType;
+  TypeMask typeOfSet(ir.PropertySet setter, ClosedWorld closedWorld) {
+    return closedWorld.commonMasks.dynamicType;
   }
 
   TypeMask typeOfSend(ir.Expression send) {
@@ -226,14 +228,15 @@
     return _resultOf(_target).typeOfSend(getNode(send));
   }
 
-  TypeMask typeOfListLiteral(Element owner, ir.ListLiteral listLiteral) {
+  TypeMask typeOfListLiteral(
+      Element owner, ir.ListLiteral listLiteral, ClosedWorld closedWorld) {
     ast.Node node = getNodeOrNull(listLiteral);
     if (node == null) {
       assertNodeIsSynthetic(listLiteral);
-      return _closedWorld.commonMasks.growableListType;
+      return closedWorld.commonMasks.growableListType;
     }
     return _resultOf(owner).typeOfNewList(getNode(listLiteral)) ??
-        _closedWorld.commonMasks.dynamicType;
+        closedWorld.commonMasks.dynamicType;
   }
 
   TypeMask typeOfIterator(ir.ForInStatement forInStatement) {
@@ -248,27 +251,25 @@
     return _resultOf(_target).typeOfIteratorMoveNext(getNode(forInStatement));
   }
 
-  bool isJsIndexableIterator(ir.ForInStatement forInStatement) {
+  bool isJsIndexableIterator(
+      ir.ForInStatement forInStatement, ClosedWorld closedWorld) {
     TypeMask mask = typeOfIterator(forInStatement);
     return mask != null &&
-        mask.satisfies(_backend.helpers.jsIndexableClass, _closedWorld) &&
+        mask.satisfies(_backend.helpers.jsIndexableClass, closedWorld) &&
         // String is indexable but not iterable.
-        !mask.satisfies(_backend.helpers.jsStringClass, _closedWorld);
+        !mask.satisfies(_backend.helpers.jsStringClass, closedWorld);
   }
 
-  bool isFixedLength(TypeMask mask) {
-    JavaScriptBackend backend = _compiler.backend;
+  bool isFixedLength(TypeMask mask, ClosedWorld closedWorld) {
     if (mask.isContainer && (mask as ContainerTypeMask).length != null) {
       // A container on which we have inferred the length.
       return true;
     }
     // TODO(sra): Recognize any combination of fixed length indexables.
-    if (mask.containsOnly(
-            _closedWorld.backendClasses.fixedListImplementation) ||
-        mask.containsOnly(
-            _closedWorld.backendClasses.constListImplementation) ||
-        mask.containsOnlyString(_closedWorld) ||
-        _closedWorld.commonMasks.isTypedArray(mask)) {
+    if (mask.containsOnly(closedWorld.backendClasses.fixedListImplementation) ||
+        mask.containsOnly(closedWorld.backendClasses.constListImplementation) ||
+        mask.containsOnlyString(closedWorld) ||
+        closedWorld.commonMasks.isTypedArray(mask)) {
       return true;
     }
     return false;
@@ -289,8 +290,9 @@
         selector, mask, _globalInferenceResults);
   }
 
-  TypeMask typeFromNativeBehavior(native.NativeBehavior nativeBehavior) {
-    return TypeMaskFactory.fromNativeBehavior(nativeBehavior, _closedWorld);
+  TypeMask typeFromNativeBehavior(
+      native.NativeBehavior nativeBehavior, ClosedWorld closedWorld) {
+    return TypeMaskFactory.fromNativeBehavior(nativeBehavior, closedWorld);
   }
 
   ConstantValue getConstantFor(ir.Node node) {
@@ -342,6 +344,16 @@
   JumpTarget getTargetDefinition(ir.Node node) =>
       elements.getTargetDefinition(getNode(node));
 
+  JumpTarget getTargetOf(ir.Node node) => elements.getTargetOf(getNode(node));
+
+  KernelJumpTarget getJumpTarget(ir.LabeledStatement labeledStatement) =>
+      _jumpTargets.putIfAbsent(labeledStatement, () {
+        return new KernelJumpTarget();
+      });
+
+  LabelDefinition getTargetLabel(ir.Node node) =>
+      elements.getTargetLabel(getNode(node));
+
   ir.Class get mapLiteralClass =>
       kernel.classes[_backend.helpers.mapLiteralClass];
 
@@ -761,9 +773,14 @@
     } else if (node.parameter.parent is ir.FunctionNode) {
       ir.FunctionNode func = node.parameter.parent;
       int index = func.typeParameters.indexOf(node.parameter);
-      ConstructorElement constructorElement = astAdapter.getElement(func);
-      ClassElement classElement = constructorElement.enclosingClass;
-      return classElement.typeVariables[index];
+      Element element = astAdapter.getElement(func);
+      if (element.isConstructor) {
+        ClassElement classElement = element.enclosingClass;
+        return classElement.typeVariables[index];
+      } else {
+        GenericElement genericElement = element;
+        return genericElement.typeVariables[index];
+      }
     }
     throw new UnsupportedError('Unsupported type parameter type node $node.');
   }
@@ -875,3 +892,55 @@
     return new StringConstantExpression(node.value);
   }
 }
+
+class KernelJumpTarget extends JumpTarget {
+  static int index = 0;
+
+  KernelJumpTarget() {
+    labels = <LabelDefinition>[
+      new LabelDefinitionX(null, 'l${index++}', this)..setBreakTarget()
+    ];
+  }
+
+  @override
+  bool get isBreakTarget => true;
+
+  set isBreakTarget(bool x) {
+    // do nothing, these are always break targets
+  }
+
+  @override
+  bool get isContinueTarget => false;
+
+  set isContinueTarget(bool x) {
+    // do nothing, these are always break targets
+  }
+
+  @override
+  LabelDefinition addLabel(ast.Label label, String labelName) {
+    LabelDefinition result = new LabelDefinitionX(label, labelName, this);
+    labels.add(result);
+    return result;
+  }
+
+  @override
+  ExecutableElement get executableContext => null;
+
+  @override
+  bool get isSwitch => false;
+
+  @override
+  bool get isTarget => true;
+
+  @override
+  List<LabelDefinition> labels;
+
+  @override
+  String get name => null;
+
+  @override
+  int get nestingLevel => 1;
+
+  @override
+  ast.Node get statement => null;
+}
diff --git a/pkg/compiler/lib/src/ssa/locals_handler.dart b/pkg/compiler/lib/src/ssa/locals_handler.dart
index 1d9fdde..79d7372 100644
--- a/pkg/compiler/lib/src/ssa/locals_handler.dart
+++ b/pkg/compiler/lib/src/ssa/locals_handler.dart
@@ -575,7 +575,7 @@
   LocalsHandler mergeMultiple(
       List<LocalsHandler> localsHandlers, HBasicBlock joinBlock) {
     assert(localsHandlers.length > 0);
-    if (localsHandlers.length == 1) return localsHandlers[0];
+    if (localsHandlers.length == 1) return localsHandlers.single;
     Map<Local, HInstruction> joinedLocals = new Map<Local, HInstruction>();
     HInstruction thisValue = null;
     directLocals.forEach((Local local, HInstruction instruction) {
diff --git a/pkg/compiler/lib/src/ssa/loop_handler.dart b/pkg/compiler/lib/src/ssa/loop_handler.dart
index e897820..7edcfeb 100644
--- a/pkg/compiler/lib/src/ssa/loop_handler.dart
+++ b/pkg/compiler/lib/src/ssa/loop_handler.dart
@@ -106,12 +106,12 @@
       builder.localsHandler =
           continueHandlers[0].mergeMultiple(continueHandlers, updateBlock);
 
-      List<LabelDefinition> labels = jumpHandler.labels();
+      List<LabelDefinition> labels = jumpHandler.labels;
       JumpTarget target = getTargetDefinition(loop);
-      if (!labels.isEmpty) {
+      if (labels.isNotEmpty) {
         beginBodyBlock.setBlockFlow(
             new HLabeledBlockInformation(
-                new HSubGraphBlockInformation(bodyGraph), jumpHandler.labels(),
+                new HSubGraphBlockInformation(bodyGraph), jumpHandler.labels,
                 isContinue: true),
             updateBlock);
       } else if (target != null && target.isContinueTarget) {
@@ -222,7 +222,7 @@
 
     JumpHandler jumpHandler = createJumpHandler(node, isLoopJump: true);
     HBasicBlock loopEntry = builder.graph
-        .addNewLoopHeaderBlock(jumpHandler.target, jumpHandler.labels());
+        .addNewLoopHeaderBlock(jumpHandler.target, jumpHandler.labels);
     previousBlock.addSuccessor(loopEntry);
     builder.open(loopEntry);
 
@@ -350,7 +350,7 @@
 
 // TODO(het): Since kernel simplifies loop breaks and continues, we should
 // rewrite the loop handler from scratch to account for the simplified structure
-class KernelLoopHandler extends LoopHandler<ir.Node> {
+class KernelLoopHandler extends LoopHandler<ir.TreeNode> {
   final KernelSsaBuilder builder;
 
   KernelAstAdapter get astAdapter => builder.astAdapter;
@@ -360,33 +360,35 @@
         super(builder);
 
   @override
-  JumpHandler createJumpHandler(ir.Node node, {bool isLoopJump}) {
-    JumpTarget element = getTargetDefinition(node);
-    if (element == null || !identical(element.statement, node)) {
+  JumpHandler createJumpHandler(ir.TreeNode node, {bool isLoopJump}) {
+    if (node.parent is! ir.LabeledStatement) {
       // No breaks or continues to this node.
       return new NullJumpHandler(builder.compiler.reporter);
     }
-    if (isLoopJump && node is ast.SwitchStatement) {
-      // Create a special jump handler for loops created for switch statements
-      // with continue statements.
-      return new SwitchCaseJumpHandler(builder, element, getNode(node));
-    }
-    return new JumpHandler(builder, element);
+    // We must have already created a JumpHandler for the labeled statement
+    JumpHandler result =
+        builder.jumpTargets[astAdapter.getJumpTarget(node.parent)];
+    assert(result != null);
+    return result;
   }
 
   @override
-  ast.Node getNode(ir.Node node) => astAdapter.getNode(node);
+  ast.Node getNode(ir.TreeNode node) => astAdapter.getNode(node);
 
   @override
-  JumpTarget getTargetDefinition(ir.Node node) =>
-      astAdapter.getTargetDefinition(node);
+  JumpTarget getTargetDefinition(ir.TreeNode node) {
+    if (node.parent is ir.LabeledStatement) {
+      return astAdapter.getJumpTarget(node.parent);
+    }
+    return null;
+  }
 
   @override
-  int loopKind(ir.Node node) => node.accept(new _KernelLoopTypeVisitor());
+  int loopKind(ir.TreeNode node) => node.accept(new _KernelLoopTypeVisitor());
 
   // TODO(het): return the actual source information
   @override
-  SourceInformation loopSourceInformation(ir.Node node) => null;
+  SourceInformation loopSourceInformation(ir.TreeNode node) => null;
 }
 
 class _KernelLoopTypeVisitor extends ir.Visitor<int> {
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 83ecc44..a711e41 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -207,7 +207,7 @@
     return result;
   }
 
-  HConstant addConstant(ConstantValue constant, Compiler compiler,
+  HConstant addConstant(ConstantValue constant, ClosedWorld closedWorld,
       {SourceInformation sourceInformation}) {
     HConstant result = constants[constant];
     // TODO(johnniwinther): Support source information per constant reference.
@@ -216,7 +216,7 @@
         // We use `null` as the value for invalid constant expressions.
         constant = const NullConstantValue();
       }
-      TypeMask type = computeTypeMask(compiler, constant);
+      TypeMask type = computeTypeMask(closedWorld, constant);
       result = new HConstant.internal(constant, type)
         ..sourceInformation = sourceInformation;
       entry.addAtExit(result);
@@ -228,43 +228,47 @@
     return result;
   }
 
-  HConstant addDeferredConstant(ConstantValue constant, Entity prefix,
-      SourceInformation sourceInformation, Compiler compiler) {
+  HConstant addDeferredConstant(
+      ConstantValue constant,
+      Entity prefix,
+      SourceInformation sourceInformation,
+      Compiler compiler,
+      ClosedWorld closedWorld) {
     // TODO(sigurdm,johnniwinther): These deferred constants should be created
     // by the constant evaluator.
     ConstantValue wrapper = new DeferredConstantValue(constant, prefix);
     compiler.deferredLoadTask.registerConstantDeferredUse(wrapper, prefix);
-    return addConstant(wrapper, compiler, sourceInformation: sourceInformation);
+    return addConstant(wrapper, closedWorld,
+        sourceInformation: sourceInformation);
   }
 
-  HConstant addConstantInt(int i, Compiler compiler) {
-    return addConstant(compiler.backend.constantSystem.createInt(i), compiler);
+  HConstant addConstantInt(int i, ClosedWorld closedWorld) {
+    return addConstant(closedWorld.constantSystem.createInt(i), closedWorld);
   }
 
-  HConstant addConstantDouble(double d, Compiler compiler) {
+  HConstant addConstantDouble(double d, ClosedWorld closedWorld) {
+    return addConstant(closedWorld.constantSystem.createDouble(d), closedWorld);
+  }
+
+  HConstant addConstantString(ast.DartString str, ClosedWorld closedWorld) {
     return addConstant(
-        compiler.backend.constantSystem.createDouble(d), compiler);
+        closedWorld.constantSystem.createString(str), closedWorld);
   }
 
-  HConstant addConstantString(ast.DartString str, Compiler compiler) {
-    return addConstant(
-        compiler.backend.constantSystem.createString(str), compiler);
-  }
-
-  HConstant addConstantStringFromName(js.Name name, Compiler compiler) {
+  HConstant addConstantStringFromName(js.Name name, ClosedWorld closedWorld) {
     return addConstant(
         new SyntheticConstantValue(
             SyntheticConstantKind.NAME, js.quoteName(name)),
-        compiler);
+        closedWorld);
   }
 
-  HConstant addConstantBool(bool value, Compiler compiler) {
+  HConstant addConstantBool(bool value, ClosedWorld closedWorld) {
     return addConstant(
-        compiler.backend.constantSystem.createBool(value), compiler);
+        closedWorld.constantSystem.createBool(value), closedWorld);
   }
 
-  HConstant addConstantNull(Compiler compiler) {
-    return addConstant(compiler.backend.constantSystem.createNull(), compiler);
+  HConstant addConstantNull(ClosedWorld closedWorld) {
+    return addConstant(closedWorld.constantSystem.createNull(), closedWorld);
   }
 
   void finalize() {
@@ -2161,11 +2165,9 @@
 }
 
 class HBreak extends HJump {
-  /**
-   * Signals that this is a special break instruction for the synthetic loop
-   * generatedfor a switch statement with continue statements. See
-   * [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
-   */
+  /// Signals that this is a special break instruction for the synthetic loop
+  /// generated for a switch statement with continue statements. See
+  /// [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
   final bool breakSwitchContinueLoop;
   HBreak(JumpTarget target, {bool this.breakSwitchContinueLoop: false})
       : super(target);
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 0703f1c..2c6cdb8 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -8,7 +8,7 @@
 import '../compiler.dart' show Compiler;
 import '../constants/constant_system.dart';
 import '../constants/values.dart';
-import '../core_types.dart' show CommonElements, CoreClasses;
+import '../core_types.dart' show CommonElements;
 import '../dart_types.dart';
 import '../elements/elements.dart';
 import '../js/js.dart' as js;
@@ -35,22 +35,24 @@
 
 class SsaOptimizerTask extends CompilerTask {
   final JavaScriptBackend backend;
+
+  Map<HInstruction, Range> ranges = <HInstruction, Range>{};
+
   SsaOptimizerTask(JavaScriptBackend backend)
       : this.backend = backend,
         super(backend.compiler.measurer);
-  String get name => 'SSA optimizer';
-  Compiler get compiler => backend.compiler;
-  ClosedWorld get closedWorld => compiler.closedWorld;
-  Map<HInstruction, Range> ranges = <HInstruction, Range>{};
 
-  void optimize(CodegenWorkItem work, HGraph graph) {
+  String get name => 'SSA optimizer';
+
+  Compiler get compiler => backend.compiler;
+
+  void optimize(CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) {
     void runPhase(OptimizationPhase phase) {
       measureSubtask(phase.name, () => phase.visitGraph(graph));
-      compiler.tracer.traceGraph(phase.name, graph);
+      backend.tracer.traceGraph(phase.name, graph);
       assert(graph.isValid());
     }
 
-    ConstantSystem constantSystem = compiler.backend.constantSystem;
     bool trustPrimitives = compiler.options.trustPrimitives;
     CodegenRegistry registry = work.registry;
     Set<HInstruction> boundsChecked = new Set<HInstruction>();
@@ -59,36 +61,36 @@
       List<OptimizationPhase> phases = <OptimizationPhase>[
         // Run trivial instruction simplification first to optimize
         // some patterns useful for type conversion.
-        new SsaInstructionSimplifier(constantSystem, backend, this, registry),
+        new SsaInstructionSimplifier(backend, closedWorld, this, registry),
         new SsaTypeConversionInserter(closedWorld),
         new SsaRedundantPhiEliminator(),
         new SsaDeadPhiEliminator(),
-        new SsaTypePropagator(compiler),
+        new SsaTypePropagator(compiler, closedWorld),
         // After type propagation, more instructions can be
         // simplified.
-        new SsaInstructionSimplifier(constantSystem, backend, this, registry),
+        new SsaInstructionSimplifier(backend, closedWorld, this, registry),
         new SsaCheckInserter(
             trustPrimitives, backend, closedWorld, boundsChecked),
-        new SsaInstructionSimplifier(constantSystem, backend, this, registry),
+        new SsaInstructionSimplifier(backend, closedWorld, this, registry),
         new SsaCheckInserter(
             trustPrimitives, backend, closedWorld, boundsChecked),
-        new SsaTypePropagator(compiler),
+        new SsaTypePropagator(compiler, closedWorld),
         // Run a dead code eliminator before LICM because dead
         // interceptors are often in the way of LICM'able instructions.
-        new SsaDeadCodeEliminator(compiler, this),
-        new SsaGlobalValueNumberer(compiler),
+        new SsaDeadCodeEliminator(closedWorld, this),
+        new SsaGlobalValueNumberer(),
         // After GVN, some instructions might need their type to be
         // updated because they now have different inputs.
-        new SsaTypePropagator(compiler),
+        new SsaTypePropagator(compiler, closedWorld),
         codeMotion = new SsaCodeMotion(),
-        new SsaLoadElimination(compiler),
+        new SsaLoadElimination(compiler, closedWorld),
         new SsaRedundantPhiEliminator(),
         new SsaDeadPhiEliminator(),
-        new SsaTypePropagator(compiler),
-        new SsaValueRangeAnalyzer(compiler, constantSystem, this),
+        new SsaTypePropagator(compiler, closedWorld),
+        new SsaValueRangeAnalyzer(backend.helpers, closedWorld, this),
         // Previous optimizations may have generated new
         // opportunities for instruction simplification.
-        new SsaInstructionSimplifier(constantSystem, backend, this, registry),
+        new SsaInstructionSimplifier(backend, closedWorld, this, registry),
         new SsaCheckInserter(
             trustPrimitives, backend, closedWorld, boundsChecked),
       ];
@@ -98,28 +100,28 @@
       // required for implementation correctness because the code generator
       // assumes it is always performed.
       runPhase(
-          new SsaSimplifyInterceptors(compiler, constantSystem, work.element));
+          new SsaSimplifyInterceptors(compiler, closedWorld, work.element));
 
-      SsaDeadCodeEliminator dce = new SsaDeadCodeEliminator(compiler, this);
+      SsaDeadCodeEliminator dce = new SsaDeadCodeEliminator(closedWorld, this);
       runPhase(dce);
       if (codeMotion.movedCode || dce.eliminatedSideEffects) {
         phases = <OptimizationPhase>[
-          new SsaTypePropagator(compiler),
-          new SsaGlobalValueNumberer(compiler),
+          new SsaTypePropagator(compiler, closedWorld),
+          new SsaGlobalValueNumberer(),
           new SsaCodeMotion(),
-          new SsaValueRangeAnalyzer(compiler, constantSystem, this),
-          new SsaInstructionSimplifier(constantSystem, backend, this, registry),
+          new SsaValueRangeAnalyzer(backend.helpers, closedWorld, this),
+          new SsaInstructionSimplifier(backend, closedWorld, this, registry),
           new SsaCheckInserter(
               trustPrimitives, backend, closedWorld, boundsChecked),
-          new SsaSimplifyInterceptors(compiler, constantSystem, work.element),
-          new SsaDeadCodeEliminator(compiler, this),
+          new SsaSimplifyInterceptors(compiler, closedWorld, work.element),
+          new SsaDeadCodeEliminator(closedWorld, this),
         ];
       } else {
         phases = <OptimizationPhase>[
-          new SsaTypePropagator(compiler),
+          new SsaTypePropagator(compiler, closedWorld),
           // Run the simplifier to remove unneeded type checks inserted by
           // type propagation.
-          new SsaInstructionSimplifier(constantSystem, backend, this, registry),
+          new SsaInstructionSimplifier(backend, closedWorld, this, registry),
         ];
       }
       phases.forEach(runPhase);
@@ -131,9 +133,7 @@
 /// cannot change.  The current implementation is conservative for the purpose
 /// of identifying gvn-able lengths and mis-identifies some unions of fixed
 /// length indexables (see TODO) as not fixed length.
-bool isFixedLength(mask, Compiler compiler) {
-  ClosedWorld closedWorld = compiler.closedWorld;
-  JavaScriptBackend backend = compiler.backend;
+bool isFixedLength(mask, ClosedWorld closedWorld) {
   if (mask.isContainer && mask.length != null) {
     // A container on which we have inferred the length.
     return true;
@@ -161,21 +161,21 @@
 
   final String name = "SsaInstructionSimplifier";
   final JavaScriptBackend backend;
-  final ConstantSystem constantSystem;
+  final ClosedWorld closedWorld;
   final CodegenRegistry registry;
   HGraph graph;
   Compiler get compiler => backend.compiler;
   final SsaOptimizerTask optimizer;
 
   SsaInstructionSimplifier(
-      this.constantSystem, this.backend, this.optimizer, this.registry);
-
-  ClosedWorld get closedWorld => compiler.closedWorld;
+      this.backend, this.closedWorld, this.optimizer, this.registry);
 
   CommonElements get commonElements => closedWorld.commonElements;
 
   BackendHelpers get helpers => backend.helpers;
 
+  ConstantSystem get constantSystem => closedWorld.constantSystem;
+
   GlobalTypeInferenceResults get globalInferenceResults =>
       compiler.globalInference.results;
 
@@ -249,7 +249,7 @@
     if (node.usedBy.isEmpty) return;
     ConstantValue value = getConstantFromType(node);
     if (value != null) {
-      HConstant constant = graph.addConstant(value, compiler);
+      HConstant constant = graph.addConstant(value, closedWorld);
       for (HInstruction user in node.usedBy.toList()) {
         user.changeUse(node, constant);
       }
@@ -296,7 +296,7 @@
     // All values that cannot be 'true' are boolified to false.
     TypeMask mask = input.instructionType;
     if (!mask.contains(helpers.jsBoolClass, closedWorld)) {
-      return graph.addConstantBool(false, compiler);
+      return graph.addConstantBool(false, closedWorld);
     }
     return node;
   }
@@ -308,7 +308,7 @@
     if (input is HConstant) {
       HConstant constant = input;
       bool isTrue = constant.constant.isTrue;
-      return graph.addConstantBool(!isTrue, compiler);
+      return graph.addConstantBool(!isTrue, closedWorld);
     } else if (input is HNot) {
       return input.inputs[0];
     }
@@ -325,7 +325,7 @@
     if (operand is HConstant) {
       HConstant receiver = operand;
       ConstantValue folded = operation.fold(receiver.constant);
-      if (folded != null) return graph.addConstant(folded, compiler);
+      if (folded != null) return graph.addConstant(folded, closedWorld);
     }
     return null;
   }
@@ -336,14 +336,14 @@
       if (actualReceiver.isConstantString()) {
         HConstant constantInput = actualReceiver;
         StringConstantValue constant = constantInput.constant;
-        return graph.addConstantInt(constant.length, compiler);
+        return graph.addConstantInt(constant.length, closedWorld);
       } else if (actualReceiver.isConstantList()) {
         HConstant constantInput = actualReceiver;
         ListConstantValue constant = constantInput.constant;
-        return graph.addConstantInt(constant.length, compiler);
+        return graph.addConstantInt(constant.length, closedWorld);
       }
       MemberElement element = helpers.jsIndexableLength;
-      bool isFixed = isFixedLength(actualReceiver.instructionType, compiler);
+      bool isFixed = isFixedLength(actualReceiver.instructionType, closedWorld);
       TypeMask actualType = node.instructionType;
       TypeMask resultType = closedWorld.commonMasks.positiveIntType;
       // If we already have computed a more specific type, keep that type.
@@ -360,7 +360,7 @@
     } else if (actualReceiver.isConstantMap()) {
       HConstant constantInput = actualReceiver;
       MapConstantValue constant = constantInput.constant;
-      return graph.addConstantInt(constant.length, compiler);
+      return graph.addConstantInt(constant.length, closedWorld);
     }
     return null;
   }
@@ -585,7 +585,7 @@
       HConstant op1 = left;
       HConstant op2 = right;
       ConstantValue folded = operation.fold(op1.constant, op2.constant);
-      if (folded != null) return graph.addConstant(folded, compiler);
+      if (folded != null) return graph.addConstant(folded, closedWorld);
     }
     return null;
   }
@@ -646,8 +646,8 @@
     TypeMask leftType = left.instructionType;
     TypeMask rightType = right.instructionType;
 
-    HInstruction makeTrue() => graph.addConstantBool(true, compiler);
-    HInstruction makeFalse() => graph.addConstantBool(false, compiler);
+    HInstruction makeTrue() => graph.addConstantBool(true, closedWorld);
+    HInstruction makeFalse() => graph.addConstantBool(false, closedWorld);
 
     // Intersection of int and double return conflicting, so
     // we don't optimize on numbers to preserve the runtime semantics.
@@ -698,7 +698,7 @@
   void simplifyCondition(
       HBasicBlock block, HInstruction condition, bool value) {
     condition.dominatedUsers(block.first).forEach((user) {
-      HInstruction newCondition = graph.addConstantBool(value, compiler);
+      HInstruction newCondition = graph.addConstantBool(value, closedWorld);
       user.changeUse(condition, newCondition);
     });
   }
@@ -741,7 +741,7 @@
     }
 
     if (type.isObject || type.treatAsDynamic) {
-      return graph.addConstantBool(true, compiler);
+      return graph.addConstantBool(true, closedWorld);
     }
 
     HInstruction expression = node.expression;
@@ -749,30 +749,30 @@
       if (element == commonElements.intClass ||
           element == commonElements.numClass ||
           Elements.isNumberOrStringSupertype(element, commonElements)) {
-        return graph.addConstantBool(true, compiler);
+        return graph.addConstantBool(true, closedWorld);
       } else if (element == commonElements.doubleClass) {
         // We let the JS semantics decide for that check. Currently
         // the code we emit will always return true.
         return node;
       } else {
-        return graph.addConstantBool(false, compiler);
+        return graph.addConstantBool(false, closedWorld);
       }
     } else if (expression.isDouble(closedWorld)) {
       if (element == commonElements.doubleClass ||
           element == commonElements.numClass ||
           Elements.isNumberOrStringSupertype(element, commonElements)) {
-        return graph.addConstantBool(true, compiler);
+        return graph.addConstantBool(true, closedWorld);
       } else if (element == commonElements.intClass) {
         // We let the JS semantics decide for that check. Currently
         // the code we emit will return true for a double that can be
         // represented as a 31-bit integer and for -0.0.
         return node;
       } else {
-        return graph.addConstantBool(false, compiler);
+        return graph.addConstantBool(false, closedWorld);
       }
     } else if (expression.isNumber(closedWorld)) {
       if (element == commonElements.numClass) {
-        return graph.addConstantBool(true, compiler);
+        return graph.addConstantBool(true, closedWorld);
       } else {
         // We cannot just return false, because the expression may be of
         // type int or double.
@@ -792,9 +792,9 @@
           ? new TypeMask.subtype(element, closedWorld)
           : new TypeMask.nonNullSubtype(element, closedWorld);
       if (expressionMask.union(typeMask, closedWorld) == typeMask) {
-        return graph.addConstantBool(true, compiler);
+        return graph.addConstantBool(true, closedWorld);
       } else if (expressionMask.isDisjoint(typeMask, closedWorld)) {
-        return graph.addConstantBool(false, compiler);
+        return graph.addConstantBool(false, closedWorld);
       }
     }
     return node;
@@ -865,11 +865,12 @@
           return receiver.inputs[0];
         }
       } else if (receiver.isConstantList() || receiver.isConstantString()) {
-        return graph.addConstantInt(receiver.constant.length, compiler);
+        return graph.addConstantInt(receiver.constant.length, closedWorld);
       } else {
         var type = receiver.instructionType;
         if (type.isContainer && type.length != null) {
-          HInstruction constant = graph.addConstantInt(type.length, compiler);
+          HInstruction constant =
+              graph.addConstantInt(type.length, closedWorld);
           if (type.isNullable) {
             // If the container can be null, we update all uses of the
             // length access to use the constant instead, but keep the
@@ -893,7 +894,7 @@
         Map<Element, ConstantValue> fields = constructedConstant.fields;
         ConstantValue value = fields[node.element];
         if (value != null) {
-          return graph.addConstant(value, compiler);
+          return graph.addConstant(value, closedWorld);
         }
       }
     }
@@ -908,7 +909,7 @@
       instruction = node.index;
       int index = instruction.constant.primitiveValue;
       if (index >= 0 && index < entries.length) {
-        return graph.addConstant(entries[index], compiler);
+        return graph.addConstant(entries[index], closedWorld);
       }
     }
     return node;
@@ -1063,7 +1064,7 @@
     HInstruction folded = graph.addConstant(
         constantSystem.createString(new ast.DartString.concat(
             leftString.primitiveValue, rightString.primitiveValue)),
-        compiler);
+        closedWorld);
     if (prefix == null) return folded;
     return new HStringConcat(
         prefix, folded, closedWorld.commonMasks.stringType);
@@ -1087,7 +1088,7 @@
       }
       PrimitiveConstantValue primitive = constant.constant;
       return graph.addConstant(
-          constantSystem.createString(primitive.toDartString()), compiler);
+          constantSystem.createString(primitive.toDartString()), closedWorld);
     }
 
     HInstruction tryToString() {
@@ -1280,7 +1281,7 @@
         return finishSubstituted(
             object.element,
             // If there are type arguments, all type arguments are 'dynamic'.
-            (int i) => graph.addConstantNull(compiler));
+            (int i) => graph.addConstantNull(closedWorld));
       }
     }
 
@@ -1327,10 +1328,9 @@
 
   HBoundsCheck insertBoundsCheck(
       HInstruction indexNode, HInstruction array, HInstruction indexArgument) {
-    Compiler compiler = backend.compiler;
     HFieldGet length = new HFieldGet(helpers.jsIndexableLength, array,
         closedWorld.commonMasks.positiveIntType,
-        isAssignable: !isFixedLength(array.instructionType, compiler));
+        isAssignable: !isFixedLength(array.instructionType, closedWorld));
     indexNode.block.addBefore(indexNode, length);
 
     TypeMask type = indexArgument.isPositiveInteger(closedWorld)
@@ -1372,8 +1372,8 @@
     // `0` is the index we want to check, but we want to report `-1`, as if we
     // executed `a[a.length-1]`
     HBoundsCheck check = insertBoundsCheck(
-        node, node.receiver, graph.addConstantInt(0, backend.compiler));
-    HInstruction minusOne = graph.addConstantInt(-1, backend.compiler);
+        node, node.receiver, graph.addConstantInt(0, closedWorld));
+    HInstruction minusOne = graph.addConstantInt(-1, closedWorld);
     check.inputs.add(minusOne);
     minusOne.usedBy.add(check);
   }
@@ -1382,16 +1382,14 @@
 class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase {
   final String name = "SsaDeadCodeEliminator";
 
-  final Compiler compiler;
+  final ClosedWorld closedWorld;
   final SsaOptimizerTask optimizer;
   SsaLiveBlockAnalyzer analyzer;
   Map<HInstruction, bool> trivialDeadStoreReceivers =
       new Maplet<HInstruction, bool>();
   bool eliminatedSideEffects = false;
 
-  SsaDeadCodeEliminator(this.compiler, this.optimizer);
-
-  ClosedWorld get closedWorld => compiler.closedWorld;
+  SsaDeadCodeEliminator(this.closedWorld, this.optimizer);
 
   HInstruction zapInstructionCache;
   HInstruction get zapInstruction {
@@ -1399,7 +1397,7 @@
       // A constant with no type does not pollute types at phi nodes.
       ConstantValue constant = new SyntheticConstantValue(
           SyntheticConstantKind.EMPTY_VALUE, const TypeMask.nonNullEmpty());
-      zapInstructionCache = analyzer.graph.addConstant(constant, compiler);
+      zapInstructionCache = analyzer.graph.addConstant(constant, closedWorld);
     }
     return zapInstructionCache;
   }
@@ -1794,13 +1792,12 @@
 
 class SsaGlobalValueNumberer implements OptimizationPhase {
   final String name = "SsaGlobalValueNumberer";
-  final Compiler compiler;
   final Set<int> visited;
 
   List<int> blockChangesFlags;
   List<int> loopChangesFlags;
 
-  SsaGlobalValueNumberer(this.compiler) : visited = new Set<int>();
+  SsaGlobalValueNumberer() : visited = new Set<int>();
 
   void visitGraph(HGraph graph) {
     computeChangesFlags(graph);
@@ -2228,13 +2225,12 @@
  */
 class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase {
   final Compiler compiler;
+  final ClosedWorld closedWorld;
   final String name = "SsaLoadElimination";
   MemorySet memorySet;
   List<MemorySet> memories;
 
-  SsaLoadElimination(this.compiler);
-
-  ClosedWorld get closedWorld => compiler.closedWorld;
+  SsaLoadElimination(this.compiler, this.closedWorld);
 
   void visitGraph(HGraph graph) {
     memories = new List<MemorySet>(graph.blocks.length);
diff --git a/pkg/compiler/lib/src/ssa/ssa.dart b/pkg/compiler/lib/src/ssa/ssa.dart
index 55b13b0..92f05f9 100644
--- a/pkg/compiler/lib/src/ssa/ssa.dart
+++ b/pkg/compiler/lib/src/ssa/ssa.dart
@@ -10,6 +10,7 @@
 import '../io/source_information.dart';
 import '../js/js.dart' as js;
 import '../js_backend/backend.dart' show JavaScriptBackend, FunctionCompiler;
+import '../world.dart' show ClosedWorld;
 
 import 'builder.dart';
 import 'builder_kernel.dart';
@@ -36,11 +37,13 @@
 
   /// Generates JavaScript code for `work.element`.
   /// Using the ssa builder, optimizer and codegenerator.
-  js.Fun compile(CodegenWorkItem work) {
-    HGraph graph = useKernel ? builderKernel.build(work) : builder.build(work);
-    optimizer.optimize(work, graph);
+  js.Fun compile(CodegenWorkItem work, ClosedWorld closedWorld) {
+    HGraph graph = useKernel
+        ? builderKernel.build(work, closedWorld)
+        : builder.build(work, closedWorld);
+    optimizer.optimize(work, graph, closedWorld);
     Element element = work.element;
-    js.Expression result = generator.generateCode(work, graph);
+    js.Expression result = generator.generateCode(work, graph, closedWorld);
     if (element is FunctionElement) {
       // TODO(sigmund): replace by kernel transformer when `useKernel` is true.
       result = backend.rewriteAsync(element, result);
diff --git a/pkg/compiler/lib/src/ssa/ssa_branch_builder.dart b/pkg/compiler/lib/src/ssa/ssa_branch_builder.dart
index b34552c..8c1fa21 100644
--- a/pkg/compiler/lib/src/ssa/ssa_branch_builder.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_branch_builder.dart
@@ -171,7 +171,8 @@
     }
 
     handleIf(visitCondition, visitThen, null);
-    HConstant notIsAnd = builder.graph.addConstantBool(!isAnd, compiler);
+    HConstant notIsAnd =
+        builder.graph.addConstantBool(!isAnd, builder.closedWorld);
     HPhi result = new HPhi.manyInputs(
         null,
         <HInstruction>[boolifiedRight, notIsAnd],
diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
index ce13448..df84e84 100644
--- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
@@ -6,9 +6,8 @@
 
 import 'dart:async' show EventSink;
 
-import '../compiler.dart' show Compiler;
 import '../diagnostics/invariant.dart' show DEBUG_MODE;
-import '../js_backend/js_backend.dart';
+import '../js_backend/namer.dart' show Namer;
 import '../tracer.dart';
 import '../world.dart' show ClosedWorld;
 import 'nodes.dart';
@@ -19,10 +18,11 @@
  * to enable it.
  */
 class HTracer extends HGraphVisitor with TracerUtil {
-  Compiler compiler;
+  final ClosedWorld closedWorld;
+  final Namer namer;
   final EventSink<String> output;
 
-  HTracer(this.output, this.compiler);
+  HTracer(this.output, this.closedWorld, this.namer);
 
   void traceGraph(String name, HGraph graph) {
     DEBUG_MODE = true;
@@ -76,7 +76,7 @@
 
   void visitBasicBlock(HBasicBlock block) {
     HInstructionStringifier stringifier =
-        new HInstructionStringifier(block, compiler);
+        new HInstructionStringifier(block, closedWorld, namer);
     assert(block.id != null);
     tag("block", () {
       printProperty("name", "B${block.id}");
@@ -113,12 +113,11 @@
 }
 
 class HInstructionStringifier implements HVisitor<String> {
-  final Compiler compiler;
+  final ClosedWorld closedWorld;
+  final Namer namer;
   final HBasicBlock currentBlock;
 
-  HInstructionStringifier(this.currentBlock, this.compiler);
-
-  ClosedWorld get closedWorld => compiler.closedWorld;
+  HInstructionStringifier(this.currentBlock, this.closedWorld, this.namer);
 
   visit(HInstruction node) => '${node.accept(this)} ${node.instructionType}';
 
@@ -295,9 +294,7 @@
   String visitInterceptor(HInterceptor node) {
     String value = temporaryId(node.inputs[0]);
     if (node.interceptedClasses != null) {
-      JavaScriptBackend backend = compiler.backend;
-      String cls =
-          backend.namer.suffixForGetInterceptor(node.interceptedClasses);
+      String cls = namer.suffixForGetInterceptor(node.interceptedClasses);
       return "Interceptor ($cls): $value";
     }
     return "Interceptor: $value";
diff --git a/pkg/compiler/lib/src/ssa/type_builder.dart b/pkg/compiler/lib/src/ssa/type_builder.dart
index 517c091..48a7d98 100644
--- a/pkg/compiler/lib/src/ssa/type_builder.dart
+++ b/pkg/compiler/lib/src/ssa/type_builder.dart
@@ -72,7 +72,7 @@
       {SourceInformation sourceInformation}) {
     assert(assertTypeInContext(type));
     if (type is MethodTypeVariableType) {
-      return builder.graph.addConstantNull(builder.compiler);
+      return builder.graph.addConstantNull(builder.closedWorld);
     }
     bool isClosure = member.enclosingElement.isClosure;
     if (isClosure) {
@@ -177,7 +177,7 @@
     argument = argument.unaliased;
     if (argument.treatAsDynamic) {
       // Represent [dynamic] as [null].
-      return builder.graph.addConstantNull(builder.compiler);
+      return builder.graph.addConstantNull(builder.closedWorld);
     }
 
     if (argument.isTypeVariable) {
diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart
index 6412197..dd21826 100644
--- a/pkg/compiler/lib/src/ssa/types_propagation.dart
+++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
@@ -22,9 +22,7 @@
   JavaScriptBackend get backend => compiler.backend;
   String get name => 'type propagator';
 
-  SsaTypePropagator(Compiler compiler)
-      : this.compiler = compiler,
-        this.closedWorld = compiler.closedWorld;
+  SsaTypePropagator(this.compiler, this.closedWorld);
 
   TypeMask computeType(HInstruction instruction) {
     return instruction.accept(this);
diff --git a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
index 67e861e..3f041a0 100644
--- a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
+++ b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
@@ -2,11 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import '../compiler.dart' show Compiler;
 import '../constant_system_dart.dart';
 import '../constants/constant_system.dart';
 import '../constants/values.dart';
 import '../js_backend/js_backend.dart';
+import '../js_backend/backend_helpers.dart';
 import '../world.dart' show ClosedWorld;
 import 'nodes.dart';
 import 'optimize.dart';
@@ -601,18 +601,19 @@
    */
   final Map<HInstruction, Range> ranges = new Map<HInstruction, Range>();
 
-  final Compiler compiler;
-  final ConstantSystem constantSystem;
+  final BackendHelpers backendHelpers;
+  final ClosedWorld closedWorld;
   final ValueRangeInfo info;
   final SsaOptimizerTask optimizer;
 
   HGraph graph;
 
-  SsaValueRangeAnalyzer(this.compiler, constantSystem, this.optimizer)
-      : info = new ValueRangeInfo(constantSystem),
-        this.constantSystem = constantSystem;
+  SsaValueRangeAnalyzer(
+      this.backendHelpers, ClosedWorld closedWorld, this.optimizer)
+      : info = new ValueRangeInfo(closedWorld.constantSystem),
+        this.closedWorld = closedWorld;
 
-  ClosedWorld get closedWorld => compiler.closedWorld;
+  ConstantSystem get constantSystem => closedWorld.constantSystem;
 
   void visitGraph(HGraph graph) {
     this.graph = graph;
@@ -702,8 +703,7 @@
     if (!fieldGet.receiver.isIndexablePrimitive(closedWorld)) {
       return visitInstruction(fieldGet);
     }
-    JavaScriptBackend backend = compiler.backend;
-    assert(fieldGet.element == backend.helpers.jsIndexableLength);
+    assert(fieldGet.element == backendHelpers.jsIndexableLength);
     PositiveValue value = info.newPositiveValue(fieldGet);
     // We know this range is above zero. To simplify the analysis, we
     // put the zero value as the lower bound of this range. This
@@ -790,11 +790,11 @@
       handleEqualityCheck(relational);
     } else if (operation.apply(leftRange, rightRange)) {
       relational.block
-          .rewrite(relational, graph.addConstantBool(true, compiler));
+          .rewrite(relational, graph.addConstantBool(true, closedWorld));
       relational.block.remove(relational);
     } else if (negateOperation(operation).apply(leftRange, rightRange)) {
       relational.block
-          .rewrite(relational, graph.addConstantBool(false, compiler));
+          .rewrite(relational, graph.addConstantBool(false, closedWorld));
       relational.block.remove(relational);
     }
     return info.newUnboundRange();
@@ -804,7 +804,7 @@
     Range right = ranges[node.right];
     Range left = ranges[node.left];
     if (left.isSingleValue && right.isSingleValue && left == right) {
-      node.block.rewrite(node, graph.addConstantBool(true, compiler));
+      node.block.rewrite(node, graph.addConstantBool(true, closedWorld));
       node.block.remove(node);
     }
   }
diff --git a/pkg/compiler/lib/src/tracer.dart b/pkg/compiler/lib/src/tracer.dart
index e73e82a..0233143 100644
--- a/pkg/compiler/lib/src/tracer.dart
+++ b/pkg/compiler/lib/src/tracer.dart
@@ -7,10 +7,11 @@
 import 'dart:async' show EventSink;
 
 import '../compiler.dart' as api;
-import 'compiler.dart' show Compiler;
+import 'js_backend/namer.dart' show Namer;
 import 'ssa/nodes.dart' as ssa show HGraph;
 import 'ssa/ssa_tracer.dart' show HTracer;
 import 'util/util.dart' show Indentation;
+import 'world.dart' show ClosedWorld;
 
 /**
  * If non-null, we only trace methods whose name match the regexp defined by the
@@ -26,14 +27,15 @@
  * readable by IR Hydra.
  */
 class Tracer extends TracerUtil {
-  final Compiler compiler;
+  final ClosedWorld closedWorld;
+  final Namer namer;
   bool traceActive = false;
   final EventSink<String> output;
   final bool isEnabled = TRACE_FILTER != null;
 
-  Tracer(Compiler compiler, api.CompilerOutputProvider outputProvider)
-      : this.compiler = compiler,
-        output = TRACE_FILTER != null ? outputProvider('dart', 'cfg') : null;
+  Tracer(
+      this.closedWorld, this.namer, api.CompilerOutputProvider outputProvider)
+      : output = TRACE_FILTER != null ? outputProvider('dart', 'cfg') : null;
 
   void traceCompilation(String methodName) {
     if (!isEnabled) return;
@@ -49,7 +51,7 @@
   void traceGraph(String name, var irObject) {
     if (!traceActive) return;
     if (irObject is ssa.HGraph) {
-      new HTracer(output, compiler).traceGraph(name, irObject);
+      new HTracer(output, closedWorld, namer).traceGraph(name, irObject);
     }
   }
 
diff --git a/pkg/compiler/lib/src/types/constants.dart b/pkg/compiler/lib/src/types/constants.dart
index 60dbd90..c6cc7b8 100644
--- a/pkg/compiler/lib/src/types/constants.dart
+++ b/pkg/compiler/lib/src/types/constants.dart
@@ -5,119 +5,123 @@
 library types.constants;
 
 import '../common.dart';
+import '../constants/constant_system.dart' show ConstantSystem;
 import '../compiler.dart' show Compiler;
 import '../constants/values.dart';
-import '../js_backend/js_backend.dart' show SyntheticConstantKind;
+import '../js_backend/js_backend.dart'
+    show JavaScriptBackend, SyntheticConstantKind;
+import '../world.dart' show ClosedWorld;
 import 'masks.dart';
 
 /// Computes the [TypeMask] for the constant [value].
-TypeMask computeTypeMask(Compiler compiler, ConstantValue value) {
-  return value.accept(const ConstantValueTypeMasks(), compiler);
+TypeMask computeTypeMask(ClosedWorld closedWorld, ConstantValue value) {
+  return value.accept(const ConstantValueTypeMasks(), closedWorld);
 }
 
-class ConstantValueTypeMasks extends ConstantValueVisitor<TypeMask, Compiler> {
+class ConstantValueTypeMasks
+    extends ConstantValueVisitor<TypeMask, ClosedWorld> {
   const ConstantValueTypeMasks();
 
   @override
   TypeMask visitConstructed(
-      ConstructedConstantValue constant, Compiler compiler) {
-    if (compiler.backend.isInterceptorClass(constant.type.element)) {
-      return compiler.closedWorld.commonMasks.nonNullType;
+      ConstructedConstantValue constant, ClosedWorld closedWorld) {
+    if (closedWorld.backendClasses.isInterceptorClass(constant.type.element)) {
+      return closedWorld.commonMasks.nonNullType;
     }
-    return new TypeMask.nonNullExact(
-        constant.type.element, compiler.closedWorld);
+    return new TypeMask.nonNullExact(constant.type.element, closedWorld);
   }
 
   @override
-  TypeMask visitDeferred(DeferredConstantValue constant, Compiler compiler) {
-    return constant.referenced.accept(this, compiler);
+  TypeMask visitDeferred(
+      DeferredConstantValue constant, ClosedWorld closedWorld) {
+    return constant.referenced.accept(this, closedWorld);
   }
 
   @override
-  TypeMask visitDouble(DoubleConstantValue constant, Compiler compiler) {
+  TypeMask visitDouble(DoubleConstantValue constant, ClosedWorld closedWorld) {
     // We have to recognize double constants that are 'is int'.
-    if (compiler.backend.constantSystem.isInt(constant)) {
+    if (closedWorld.constantSystem.isInt(constant)) {
       if (constant.isMinusZero) {
-        return compiler.closedWorld.commonMasks.uint31Type;
+        return closedWorld.commonMasks.uint31Type;
       } else {
         assert(constant.isPositiveInfinity || constant.isNegativeInfinity);
-        return compiler.closedWorld.commonMasks.intType;
+        return closedWorld.commonMasks.intType;
       }
     }
-    return compiler.closedWorld.commonMasks.doubleType;
+    return closedWorld.commonMasks.doubleType;
   }
 
   @override
-  TypeMask visitSynthetic(SyntheticConstantValue constant, Compiler compiler) {
+  TypeMask visitSynthetic(
+      SyntheticConstantValue constant, ClosedWorld closedWorld) {
     switch (constant.valueKind) {
       case SyntheticConstantKind.DUMMY_INTERCEPTOR:
         return constant.payload;
       case SyntheticConstantKind.EMPTY_VALUE:
         return constant.payload;
       case SyntheticConstantKind.TYPEVARIABLE_REFERENCE:
-        return compiler.closedWorld.commonMasks.intType;
+        return closedWorld.commonMasks.intType;
       case SyntheticConstantKind.NAME:
-        return compiler.closedWorld.commonMasks.stringType;
+        return closedWorld.commonMasks.stringType;
       default:
-        DiagnosticReporter reporter = compiler.reporter;
-        reporter.internalError(
-            CURRENT_ELEMENT_SPANNABLE, "Unexpected DummyConstantKind.");
-        return null;
+        throw new SpannableAssertionFailure(CURRENT_ELEMENT_SPANNABLE,
+            "Unexpected DummyConstantKind: ${constant.toStructuredText()}.");
     }
   }
 
   @override
-  TypeMask visitBool(BoolConstantValue constant, Compiler compiler) {
-    return compiler.closedWorld.commonMasks.boolType;
+  TypeMask visitBool(BoolConstantValue constant, ClosedWorld closedWorld) {
+    return closedWorld.commonMasks.boolType;
   }
 
   @override
-  TypeMask visitFunction(FunctionConstantValue constant, Compiler compiler) {
-    return compiler.closedWorld.commonMasks.functionType;
+  TypeMask visitFunction(
+      FunctionConstantValue constant, ClosedWorld closedWorld) {
+    return closedWorld.commonMasks.functionType;
   }
 
   @override
-  TypeMask visitInt(IntConstantValue constant, Compiler compiler) {
-    if (constant.isUInt31()) return compiler.closedWorld.commonMasks.uint31Type;
-    if (constant.isUInt32()) return compiler.closedWorld.commonMasks.uint32Type;
-    if (constant.isPositive())
-      return compiler.closedWorld.commonMasks.positiveIntType;
-    return compiler.closedWorld.commonMasks.intType;
+  TypeMask visitInt(IntConstantValue constant, ClosedWorld closedWorld) {
+    if (constant.isUInt31()) return closedWorld.commonMasks.uint31Type;
+    if (constant.isUInt32()) return closedWorld.commonMasks.uint32Type;
+    if (constant.isPositive()) return closedWorld.commonMasks.positiveIntType;
+    return closedWorld.commonMasks.intType;
   }
 
   @override
   TypeMask visitInterceptor(
-      InterceptorConstantValue constant, Compiler compiler) {
-    return compiler.closedWorld.commonMasks.nonNullType;
+      InterceptorConstantValue constant, ClosedWorld closedWorld) {
+    return closedWorld.commonMasks.nonNullType;
   }
 
   @override
-  TypeMask visitList(ListConstantValue constant, Compiler compiler) {
-    return compiler.closedWorld.commonMasks.constListType;
+  TypeMask visitList(ListConstantValue constant, ClosedWorld closedWorld) {
+    return closedWorld.commonMasks.constListType;
   }
 
   @override
-  TypeMask visitMap(MapConstantValue constant, Compiler compiler) {
-    return compiler.closedWorld.commonMasks.constMapType;
+  TypeMask visitMap(MapConstantValue constant, ClosedWorld closedWorld) {
+    return closedWorld.commonMasks.constMapType;
   }
 
   @override
-  TypeMask visitNull(NullConstantValue constant, Compiler compiler) {
-    return compiler.closedWorld.commonMasks.nullType;
+  TypeMask visitNull(NullConstantValue constant, ClosedWorld closedWorld) {
+    return closedWorld.commonMasks.nullType;
   }
 
   @override
-  TypeMask visitNonConstant(NonConstantValue constant, Compiler compiler) {
-    return compiler.closedWorld.commonMasks.nullType;
+  TypeMask visitNonConstant(
+      NonConstantValue constant, ClosedWorld closedWorld) {
+    return closedWorld.commonMasks.nullType;
   }
 
   @override
-  TypeMask visitString(StringConstantValue constant, Compiler compiler) {
-    return compiler.closedWorld.commonMasks.stringType;
+  TypeMask visitString(StringConstantValue constant, ClosedWorld closedWorld) {
+    return closedWorld.commonMasks.stringType;
   }
 
   @override
-  TypeMask visitType(TypeConstantValue constant, Compiler compiler) {
-    return compiler.closedWorld.commonMasks.typeType;
+  TypeMask visitType(TypeConstantValue constant, ClosedWorld closedWorld) {
+    return closedWorld.commonMasks.typeType;
   }
 }
diff --git a/pkg/compiler/lib/src/types/masks.dart b/pkg/compiler/lib/src/types/masks.dart
index bee132d..f44446a 100644
--- a/pkg/compiler/lib/src/types/masks.dart
+++ b/pkg/compiler/lib/src/types/masks.dart
@@ -67,6 +67,7 @@
   TypeMask _fixedArrayType;
   TypeMask _extendableArrayType;
   TypeMask _unmodifiableArrayType;
+  TypeMask _interceptorType;
 
   TypeMask get dynamicType => _dynamicType ??=
       new TypeMask.subclass(closedWorld.coreClasses.objectClass, closedWorld);
@@ -164,6 +165,10 @@
       _unmodifiableArrayType ??= new TypeMask.nonNullExact(
           backendClasses.constListImplementation, closedWorld);
 
+  TypeMask get interceptorType =>
+      _interceptorType ??= new TypeMask.nonNullSubclass(
+          backendClasses.interceptorImplementation, closedWorld);
+
   bool isTypedArray(TypeMask mask) {
     // Just checking for [:TypedData:] is not sufficient, as it is an
     // abstract class any user-defined class can implement. So we also
diff --git a/pkg/compiler/lib/src/universe/world_builder.dart b/pkg/compiler/lib/src/universe/world_builder.dart
index 130b7eb..cd676bd 100644
--- a/pkg/compiler/lib/src/universe/world_builder.dart
+++ b/pkg/compiler/lib/src/universe/world_builder.dart
@@ -172,6 +172,11 @@
   /// The [OpenWorld] being created by this world builder.
   // TODO(johnniwinther): Merge this with [ResolutionWorldBuilder].
   OpenWorld get openWorld;
+
+  /// The closed world computed by this world builder.
+  ///
+  /// This is only available after the world builder has been closed.
+  ClosedWorld get closedWorldForTesting;
 }
 
 /// The type and kind of an instantiation registered through
@@ -425,7 +430,7 @@
   /// and classes.
   bool useInstantiationMap = false;
 
-  OpenWorld _openWorld;
+  WorldImpl _openWorld;
 
   final Backend _backend;
   final Resolution _resolution;
@@ -443,6 +448,14 @@
 
   OpenWorld get openWorld => _openWorld;
 
+  ClosedWorld get closedWorldForTesting {
+    if (!_openWorld.isClosed) {
+      throw new SpannableAssertionFailure(
+          NO_LOCATION_SPANNABLE, "The world builder has not yet been closed.");
+    }
+    return _openWorld;
+  }
+
   /// All directly instantiated classes, that is, classes with a generative
   /// constructor that has been called directly and not only through a
   /// super-call.
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index 3de6d0f..76b2bc3 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -8,6 +8,7 @@
 import 'closure.dart' show SynthesizedCallMethodElementX;
 import 'common/backend_api.dart' show BackendClasses;
 import 'common.dart';
+import 'constants/constant_system.dart';
 import 'core_types.dart' show CoreTypes, CoreClasses, CommonElements;
 import 'dart_types.dart';
 import 'elements/elements.dart'
@@ -53,6 +54,8 @@
 
   CommonMasks get commonMasks;
 
+  ConstantSystem get constantSystem;
+
   /// Returns `true` if [cls] is either directly or indirectly instantiated.
   bool isInstantiated(ClassElement cls);
 
@@ -908,6 +911,8 @@
 
   CoreClasses get coreClasses => commonElements;
 
+  ConstantSystem get constantSystem => _backend.constantSystem;
+
   /// Called to add [cls] to the set of known classes.
   ///
   /// This ensures that class hierarchy queries can be performed on [cls] and
diff --git a/pkg/dart2js_incremental/lib/caching_compiler.dart b/pkg/dart2js_incremental/lib/caching_compiler.dart
index 8bf1c64..44d56a6 100644
--- a/pkg/dart2js_incremental/lib/caching_compiler.dart
+++ b/pkg/dart2js_incremental/lib/caching_compiler.dart
@@ -68,16 +68,6 @@
             environment: environment));
     backend = compiler.backend;
 
-    full.Emitter emitter = backend.emitter.emitter;
-
-    // Much like a scout, an incremental compiler is always prepared. For
-    // mixins, classes, and lazy statics, at least.
-    emitter
-        ..needsClassSupport = true
-        ..needsMixinSupport = true
-        ..needsLazyInitializer = true
-        ..needsStructuredMemberInfo = true;
-
     Uri core = Uri.parse("dart:core");
 
     return compiler.setupSdk().then((_) {
diff --git a/pkg/dev_compiler/lib/js/amd/dart_sdk.js b/pkg/dev_compiler/lib/js/amd/dart_sdk.js
index c28cb0b..2a94c9f 100644
--- a/pkg/dev_compiler/lib/js/amd/dart_sdk.js
+++ b/pkg/dev_compiler/lib/js/amd/dart_sdk.js
@@ -34096,6 +34096,17 @@
       return result;
     }
   };
+  core.Function.is = function is_Function(o) {
+    return typeof o == "function";
+  };
+  core.Function.as = function as_Function(o) {
+    if (typeof o == "function" || o == null) return o;
+    return dart.as(o, core.Function);
+  };
+  core.Function._check = function check_String(o) {
+    if (typeof o == "function" || o == null) return o;
+    return dart.check(o, core.Function);
+  };
   dart.setSignature(core.Function, {
     statics: () => ({
       apply: dart.definiteFunctionType(dart.dynamic, [core.Function, core.List], [MapOfSymbol$dynamic()]),
@@ -52686,7 +52697,7 @@
       }
       if (args != null) args = core.List.from(args[dartx.map](dart.dynamic)(js._convertToJS));
       let fn = this[_jsObject][method];
-      if (!(fn instanceof Function)) {
+      if (typeof fn !== "function") {
         dart.throw(new core.NoSuchMethodError(this[_jsObject], core.Symbol.new(core.String._check(method)), args, dart.map({}, core.Symbol, dart.dynamic)));
       }
       return js._convertToDart(fn.apply(this[_jsObject], args));
@@ -52888,7 +52899,7 @@
   });
   js.JsArray = JsArray();
   js._isBrowserType = function(o) {
-    return o instanceof Blob || o instanceof Event || window.KeyRange && o instanceof KeyRange || o instanceof ImageData || o instanceof Node || window.TypedData && o instanceof TypedData || o instanceof Window;
+    return o instanceof Blob || o instanceof Event || window.KeyRange && o instanceof KeyRange || window.IDBKeyRange && o instanceof IDBKeyRange || o instanceof ImageData || o instanceof Node || window.Int8Array && o instanceof Int8Array.__proto__ || o instanceof Window;
   };
   dart.fn(js._isBrowserType, dynamicTobool$());
   const _dartObj = Symbol('_dartObj');
@@ -52933,11 +52944,15 @@
     } else if (js._DartObject.is(o) && dart.jsobject != dart.getReifiedType(o)) {
       return o[_dartObj];
     } else {
-      return js._putIfAbsent(js._dartProxies, o, js._wrapToDart);
+      return js._wrapToDart(o);
     }
   };
   dart.fn(js._convertToDart, dynamicToObject());
   js._wrapToDart = function(o) {
+    return js.JsObject._check(js._putIfAbsent(js._dartProxies, o, js._wrapToDartHelper));
+  };
+  dart.fn(js._wrapToDart, dynamicToJsObject());
+  js._wrapToDartHelper = function(o) {
     if (typeof o == "function") {
       return new js.JsFunction._fromJs(o);
     }
@@ -52946,7 +52961,7 @@
     }
     return new js.JsObject._fromJs(o);
   };
-  dart.fn(js._wrapToDart, dynamicToJsObject());
+  dart.fn(js._wrapToDartHelper, dynamicToJsObject());
   dart.defineLazy(js, {
     get _dartProxies() {
       return new WeakMap();
@@ -59491,10 +59506,10 @@
       return html$.Blob._check(html$.Blob._create_2(blobParts, bag));
     }
     static _create_1(parts) {
-      return new Blob(parts);
+      return new window.Blob(parts);
     }
     static _create_2(parts, bag) {
-      return new Blob(parts, bag);
+      return new window.Blob(parts, bag);
     }
     static _create_bag() {
       return {};
diff --git a/pkg/dev_compiler/lib/js/common/dart_sdk.js b/pkg/dev_compiler/lib/js/common/dart_sdk.js
index 5a032f3..f2826b9 100644
--- a/pkg/dev_compiler/lib/js/common/dart_sdk.js
+++ b/pkg/dev_compiler/lib/js/common/dart_sdk.js
@@ -34096,6 +34096,17 @@
       return result;
     }
   };
+  core.Function.is = function is_Function(o) {
+    return typeof o == "function";
+  };
+  core.Function.as = function as_Function(o) {
+    if (typeof o == "function" || o == null) return o;
+    return dart.as(o, core.Function);
+  };
+  core.Function._check = function check_String(o) {
+    if (typeof o == "function" || o == null) return o;
+    return dart.check(o, core.Function);
+  };
   dart.setSignature(core.Function, {
     statics: () => ({
       apply: dart.definiteFunctionType(dart.dynamic, [core.Function, core.List], [MapOfSymbol$dynamic()]),
@@ -52686,7 +52697,7 @@
       }
       if (args != null) args = core.List.from(args[dartx.map](dart.dynamic)(js._convertToJS));
       let fn = this[_jsObject][method];
-      if (!(fn instanceof Function)) {
+      if (typeof fn !== "function") {
         dart.throw(new core.NoSuchMethodError(this[_jsObject], core.Symbol.new(core.String._check(method)), args, dart.map({}, core.Symbol, dart.dynamic)));
       }
       return js._convertToDart(fn.apply(this[_jsObject], args));
@@ -52888,7 +52899,7 @@
   });
   js.JsArray = JsArray();
   js._isBrowserType = function(o) {
-    return o instanceof Blob || o instanceof Event || window.KeyRange && o instanceof KeyRange || o instanceof ImageData || o instanceof Node || window.TypedData && o instanceof TypedData || o instanceof Window;
+    return o instanceof Blob || o instanceof Event || window.KeyRange && o instanceof KeyRange || window.IDBKeyRange && o instanceof IDBKeyRange || o instanceof ImageData || o instanceof Node || window.Int8Array && o instanceof Int8Array.__proto__ || o instanceof Window;
   };
   dart.fn(js._isBrowserType, dynamicTobool$());
   const _dartObj = Symbol('_dartObj');
@@ -52933,11 +52944,15 @@
     } else if (js._DartObject.is(o) && dart.jsobject != dart.getReifiedType(o)) {
       return o[_dartObj];
     } else {
-      return js._putIfAbsent(js._dartProxies, o, js._wrapToDart);
+      return js._wrapToDart(o);
     }
   };
   dart.fn(js._convertToDart, dynamicToObject());
   js._wrapToDart = function(o) {
+    return js.JsObject._check(js._putIfAbsent(js._dartProxies, o, js._wrapToDartHelper));
+  };
+  dart.fn(js._wrapToDart, dynamicToJsObject());
+  js._wrapToDartHelper = function(o) {
     if (typeof o == "function") {
       return new js.JsFunction._fromJs(o);
     }
@@ -52946,7 +52961,7 @@
     }
     return new js.JsObject._fromJs(o);
   };
-  dart.fn(js._wrapToDart, dynamicToJsObject());
+  dart.fn(js._wrapToDartHelper, dynamicToJsObject());
   dart.defineLazy(js, {
     get _dartProxies() {
       return new WeakMap();
@@ -59491,10 +59506,10 @@
       return html$.Blob._check(html$.Blob._create_2(blobParts, bag));
     }
     static _create_1(parts) {
-      return new Blob(parts);
+      return new window.Blob(parts);
     }
     static _create_2(parts, bag) {
-      return new Blob(parts, bag);
+      return new window.Blob(parts, bag);
     }
     static _create_bag() {
       return {};
diff --git a/pkg/dev_compiler/lib/js/es6/dart_sdk.js b/pkg/dev_compiler/lib/js/es6/dart_sdk.js
index a575b51..993d4b0 100644
--- a/pkg/dev_compiler/lib/js/es6/dart_sdk.js
+++ b/pkg/dev_compiler/lib/js/es6/dart_sdk.js
@@ -34094,6 +34094,17 @@
     return result;
   }
 };
+core.Function.is = function is_Function(o) {
+  return typeof o == "function";
+};
+core.Function.as = function as_Function(o) {
+  if (typeof o == "function" || o == null) return o;
+  return dart.as(o, core.Function);
+};
+core.Function._check = function check_String(o) {
+  if (typeof o == "function" || o == null) return o;
+  return dart.check(o, core.Function);
+};
 dart.setSignature(core.Function, {
   statics: () => ({
     apply: dart.definiteFunctionType(dart.dynamic, [core.Function, core.List], [MapOfSymbol$dynamic()]),
@@ -52684,7 +52695,7 @@
     }
     if (args != null) args = core.List.from(args[dartx.map](dart.dynamic)(js._convertToJS));
     let fn = this[_jsObject][method];
-    if (!(fn instanceof Function)) {
+    if (typeof fn !== "function") {
       dart.throw(new core.NoSuchMethodError(this[_jsObject], core.Symbol.new(core.String._check(method)), args, dart.map({}, core.Symbol, dart.dynamic)));
     }
     return js._convertToDart(fn.apply(this[_jsObject], args));
@@ -52886,7 +52897,7 @@
 });
 js.JsArray = JsArray();
 js._isBrowserType = function(o) {
-  return o instanceof Blob || o instanceof Event || window.KeyRange && o instanceof KeyRange || o instanceof ImageData || o instanceof Node || window.TypedData && o instanceof TypedData || o instanceof Window;
+  return o instanceof Blob || o instanceof Event || window.KeyRange && o instanceof KeyRange || window.IDBKeyRange && o instanceof IDBKeyRange || o instanceof ImageData || o instanceof Node || window.Int8Array && o instanceof Int8Array.__proto__ || o instanceof Window;
 };
 dart.fn(js._isBrowserType, dynamicTobool());
 const _dartObj = Symbol('_dartObj');
@@ -52931,11 +52942,15 @@
   } else if (js._DartObject.is(o) && dart.jsobject != dart.getReifiedType(o)) {
     return o[_dartObj];
   } else {
-    return js._putIfAbsent(js._dartProxies, o, js._wrapToDart);
+    return js._wrapToDart(o);
   }
 };
 dart.fn(js._convertToDart, dynamicToObject());
 js._wrapToDart = function(o) {
+  return js.JsObject._check(js._putIfAbsent(js._dartProxies, o, js._wrapToDartHelper));
+};
+dart.fn(js._wrapToDart, dynamicToJsObject());
+js._wrapToDartHelper = function(o) {
   if (typeof o == "function") {
     return new js.JsFunction._fromJs(o);
   }
@@ -52944,7 +52959,7 @@
   }
   return new js.JsObject._fromJs(o);
 };
-dart.fn(js._wrapToDart, dynamicToJsObject());
+dart.fn(js._wrapToDartHelper, dynamicToJsObject());
 dart.defineLazy(js, {
   get _dartProxies() {
     return new WeakMap();
@@ -59489,10 +59504,10 @@
     return html.Blob._check(html.Blob._create_2(blobParts, bag));
   }
   static _create_1(parts) {
-    return new Blob(parts);
+    return new window.Blob(parts);
   }
   static _create_2(parts, bag) {
-    return new Blob(parts, bag);
+    return new window.Blob(parts, bag);
   }
   static _create_bag() {
     return {};
diff --git a/pkg/dev_compiler/lib/js/legacy/dart_sdk.js b/pkg/dev_compiler/lib/js/legacy/dart_sdk.js
index b5a3e61..d960ce5 100644
--- a/pkg/dev_compiler/lib/js/legacy/dart_sdk.js
+++ b/pkg/dev_compiler/lib/js/legacy/dart_sdk.js
@@ -34097,6 +34097,17 @@
       return result;
     }
   };
+  core.Function.is = function is_Function(o) {
+    return typeof o == "function";
+  };
+  core.Function.as = function as_Function(o) {
+    if (typeof o == "function" || o == null) return o;
+    return dart.as(o, core.Function);
+  };
+  core.Function._check = function check_String(o) {
+    if (typeof o == "function" || o == null) return o;
+    return dart.check(o, core.Function);
+  };
   dart.setSignature(core.Function, {
     statics: () => ({
       apply: dart.definiteFunctionType(dart.dynamic, [core.Function, core.List], [MapOfSymbol$dynamic()]),
@@ -52687,7 +52698,7 @@
       }
       if (args != null) args = core.List.from(args[dartx.map](dart.dynamic)(js._convertToJS));
       let fn = this[_jsObject][method];
-      if (!(fn instanceof Function)) {
+      if (typeof fn !== "function") {
         dart.throw(new core.NoSuchMethodError(this[_jsObject], core.Symbol.new(core.String._check(method)), args, dart.map({}, core.Symbol, dart.dynamic)));
       }
       return js._convertToDart(fn.apply(this[_jsObject], args));
@@ -52889,7 +52900,7 @@
   });
   js.JsArray = JsArray();
   js._isBrowserType = function(o) {
-    return o instanceof Blob || o instanceof Event || window.KeyRange && o instanceof KeyRange || o instanceof ImageData || o instanceof Node || window.TypedData && o instanceof TypedData || o instanceof Window;
+    return o instanceof Blob || o instanceof Event || window.KeyRange && o instanceof KeyRange || window.IDBKeyRange && o instanceof IDBKeyRange || o instanceof ImageData || o instanceof Node || window.Int8Array && o instanceof Int8Array.__proto__ || o instanceof Window;
   };
   dart.fn(js._isBrowserType, dynamicTobool$());
   const _dartObj = Symbol('_dartObj');
@@ -52934,11 +52945,15 @@
     } else if (js._DartObject.is(o) && dart.jsobject != dart.getReifiedType(o)) {
       return o[_dartObj];
     } else {
-      return js._putIfAbsent(js._dartProxies, o, js._wrapToDart);
+      return js._wrapToDart(o);
     }
   };
   dart.fn(js._convertToDart, dynamicToObject());
   js._wrapToDart = function(o) {
+    return js.JsObject._check(js._putIfAbsent(js._dartProxies, o, js._wrapToDartHelper));
+  };
+  dart.fn(js._wrapToDart, dynamicToJsObject());
+  js._wrapToDartHelper = function(o) {
     if (typeof o == "function") {
       return new js.JsFunction._fromJs(o);
     }
@@ -52947,7 +52962,7 @@
     }
     return new js.JsObject._fromJs(o);
   };
-  dart.fn(js._wrapToDart, dynamicToJsObject());
+  dart.fn(js._wrapToDartHelper, dynamicToJsObject());
   dart.defineLazy(js, {
     get _dartProxies() {
       return new WeakMap();
@@ -59492,10 +59507,10 @@
       return html$.Blob._check(html$.Blob._create_2(blobParts, bag));
     }
     static _create_1(parts) {
-      return new Blob(parts);
+      return new window.Blob(parts);
     }
     static _create_2(parts, bag) {
-      return new Blob(parts, bag);
+      return new window.Blob(parts, bag);
     }
     static _create_bag() {
       return {};
diff --git a/pkg/dev_compiler/lib/sdk/ddc_sdk.sum b/pkg/dev_compiler/lib/sdk/ddc_sdk.sum
index 1e77413..9ba0e1c 100644
--- a/pkg/dev_compiler/lib/sdk/ddc_sdk.sum
+++ b/pkg/dev_compiler/lib/sdk/ddc_sdk.sum
Binary files differ
diff --git a/pkg/dev_compiler/lib/src/analyzer/context.dart b/pkg/dev_compiler/lib/src/analyzer/context.dart
index 007a582..bdf5d16 100644
--- a/pkg/dev_compiler/lib/src/analyzer/context.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/context.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:args/args.dart' show ArgParser, ArgResults;
+import 'package:analyzer/src/command_line/arguments.dart';
 import 'package:analyzer/file_system/file_system.dart'
     show ResourceProvider, ResourceUriResolver;
 import 'package:analyzer/file_system/physical_file_system.dart'
@@ -24,11 +25,13 @@
 
 /// Options used to set up Source URI resolution in the analysis context.
 class AnalyzerOptions {
+  final ContextBuilderOptions contextBuilderOptions;
+
   /// Custom URI mappings, such as "dart:foo" -> "path/to/foo.dart"
   final Map<String, String> customUrlMappings;
 
   /// Package root when resolving 'package:' urls the standard way.
-  final String packageRoot;
+  String get packageRoot => contextBuilderOptions.defaultPackagesDirectoryPath;
 
   /// List of summary file paths.
   final List<String> summaryPaths;
@@ -39,39 +42,52 @@
 
   /// Path to the dart-sdk summary.  If this is set, it will be used in favor
   /// of the unsummarized one.
-  final String dartSdkSummaryPath;
+  String get dartSdkSummaryPath => contextBuilderOptions.dartSdkSummaryPath;
 
   /// Defined variables used by `bool.fromEnvironment` etc.
-  final Map<String, String> declaredVariables;
+  Map<String, String> get declaredVariables =>
+      contextBuilderOptions.declaredVariables;
 
-  AnalyzerOptions(
-      {this.summaryPaths: const [],
+  AnalyzerOptions._(
+      {this.contextBuilderOptions,
+      this.summaryPaths: const [],
       String dartSdkPath,
-      this.dartSdkSummaryPath,
-      this.customUrlMappings: const {},
-      this.packageRoot: null,
-      this.declaredVariables: const {}})
-      : dartSdkPath = dartSdkPath ?? getSdkDir().path;
+      this.customUrlMappings: const {}})
+      : dartSdkPath = dartSdkPath ?? getSdkDir().path {
+    contextBuilderOptions.declaredVariables ??= const {};
+  }
 
-  factory AnalyzerOptions.fromArguments(
-      ArgResults args, Map<String, String> declaredVariables) {
-    var sdkPath = args['dart-sdk'] ?? getSdkDir().path;
-    var sdkSummaryPath = args['dart-sdk-summary'];
+  factory AnalyzerOptions.basic(
+      {String dartSdkPath,
+      String dartSdkSummaryPath,
+      List<String> summaryPaths}) {
+    var contextBuilderOptions = new ContextBuilderOptions();
+    contextBuilderOptions.dartSdkSummaryPath = dartSdkSummaryPath;
 
-    if (sdkSummaryPath == null) {
-      sdkSummaryPath = path.join(sdkPath, 'lib', '_internal', 'ddc_sdk.sum');
-    } else if (sdkSummaryPath == 'build') {
+    return new AnalyzerOptions._(
+        contextBuilderOptions: contextBuilderOptions,
+        dartSdkPath: dartSdkPath,
+        summaryPaths: summaryPaths);
+  }
+
+  factory AnalyzerOptions.fromArguments(ArgResults args,
+      {String dartSdkSummaryPath, List<String> summaryPaths}) {
+    var contextBuilderOptions = createContextBuilderOptions(args);
+
+    if (dartSdkSummaryPath != null)
+      contextBuilderOptions.dartSdkSummaryPath = dartSdkSummaryPath;
+    contextBuilderOptions.dartSdkSummaryPath ??=
+        path.join(args['dart-sdk'], 'lib', '_internal', 'ddc_sdk.sum');
+    if (contextBuilderOptions.dartSdkSummaryPath == 'build') {
       // For building the SDK, we explicitly set the path to none.
-      sdkSummaryPath = null;
+      contextBuilderOptions.dartSdkSummaryPath = null;
     }
 
-    return new AnalyzerOptions(
-        summaryPaths: args['summary'] as List<String>,
-        dartSdkPath: sdkPath,
-        dartSdkSummaryPath: sdkSummaryPath,
-        customUrlMappings: _parseUrlMappings(args['url-mapping']),
-        packageRoot: args['package-root'],
-        declaredVariables: declaredVariables);
+    return new AnalyzerOptions._(
+        contextBuilderOptions: contextBuilderOptions,
+        summaryPaths: summaryPaths ?? args['summary'] as List<String>,
+        dartSdkPath: args['dart-sdk'],
+        customUrlMappings: _parseUrlMappings(args['url-mapping']));
   }
 
   static void addArguments(ArgParser parser, {bool hide: true}) {
diff --git a/pkg/dev_compiler/lib/src/compiler/code_generator.dart b/pkg/dev_compiler/lib/src/compiler/code_generator.dart
index 137c16e..46ddce3 100644
--- a/pkg/dev_compiler/lib/src/compiler/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/compiler/code_generator.dart
@@ -126,6 +126,7 @@
   final ClassElement numClass;
   final ClassElement objectClass;
   final ClassElement stringClass;
+  final ClassElement functionClass;
   final ClassElement symbolClass;
 
   ConstFieldVisitor _constants;
@@ -171,6 +172,7 @@
         nullClass = _getLibrary(c, 'dart:core').getType('Null'),
         objectClass = _getLibrary(c, 'dart:core').getType('Object'),
         stringClass = _getLibrary(c, 'dart:core').getType('String'),
+        functionClass = _getLibrary(c, 'dart:core').getType('Function'),
         symbolClass = _getLibrary(c, 'dart:_internal').getType('Symbol'),
         dartJSLibrary = _getLibrary(c, 'dart:js');
 
@@ -930,6 +932,25 @@
           [className, _runtimeModule, className]));
       return;
     }
+    if (classElem == functionClass) {
+      body.add(js.statement(
+          '#.is = function is_Function(o) { return typeof o == "function"; }',
+          className));
+      body.add(js.statement(
+          '#.as = function as_Function(o) {'
+          '  if (typeof o == "function" || o == null) return o;'
+          '  return #.as(o, #);'
+          '}',
+          [className, _runtimeModule, className]));
+      body.add(js.statement(
+          '#._check = function check_String(o) {'
+          '  if (typeof o == "function" || o == null) return o;'
+          '  return #.check(o, #);'
+          '}',
+          [className, _runtimeModule, className]));
+      return;
+    }
+
     if (classElem == intClass) {
       body.add(js.statement(
           '#.is = function is_int(o) {'
diff --git a/pkg/dev_compiler/lib/src/compiler/command.dart b/pkg/dev_compiler/lib/src/compiler/command.dart
index 7ee4c5c..102f33a 100644
--- a/pkg/dev_compiler/lib/src/compiler/command.dart
+++ b/pkg/dev_compiler/lib/src/compiler/command.dart
@@ -5,8 +5,7 @@
 import 'dart:io';
 import 'package:analyzer/src/command_line/arguments.dart'
     show
-        defineDDCAnalysisArguments,
-        extractDefinedVariables,
+        defineAnalysisArguments,
         filterUnknownArguments,
         ignoreUnrecognizedFlagsFlag;
 import 'package:analyzer/src/generated/source.dart' show Source;
@@ -29,22 +28,29 @@
 /// worker support.
 int compile(List<String> args, {void printFn(Object obj)}) {
   printFn ??= print;
+
   ArgResults argResults;
-  var declaredVars = <String, String>{};
+  AnalyzerOptions analyzerOptions;
   try {
-    args = extractDefinedVariables(args, declaredVars);
     var parser = _argParser();
     if (args.contains('--$ignoreUnrecognizedFlagsFlag')) {
       args = filterUnknownArguments(args, parser);
     }
     argResults = parser.parse(args);
-    _verbose = argResults['verbose'];
+    analyzerOptions = new AnalyzerOptions.fromArguments(argResults);
   } on FormatException catch (error) {
     printFn('$error\n\n$_usageMessage');
     return 64;
   }
+
+  _verbose = argResults['verbose'];
+  if (argResults['help']) {
+    printFn(_usageMessage);
+    return 0;
+  }
+
   try {
-    _compile(argResults, declaredVars, printFn);
+    _compile(argResults, analyzerOptions, printFn);
     return 0;
   } on UsageException catch (error) {
     // Incorrect usage, input file not found, etc.
@@ -97,7 +103,7 @@
     ..addOption('library-root',
         help: 'Root of source files.\n'
             'Generated library names are relative to this root.');
-  defineDDCAnalysisArguments(argParser, hide: hide);
+  defineAnalysisArguments(argParser, hide: hide, ddc: true);
   addModuleFormatOptions(argParser, allowMultiple: true, hide: hide);
   AnalyzerOptions.addArguments(argParser, hide: hide);
   CompilerOptions.addArguments(argParser, hide: hide);
@@ -113,14 +119,9 @@
   return false;
 }
 
-void _compile(ArgResults argResults, Map<String, String> declaredVars,
+void _compile(ArgResults argResults, AnalyzerOptions analyzerOptions,
     void printFn(Object obj)) {
-  if (argResults['help']) {
-    printFn(_usageMessage);
-    return;
-  }
-  var compiler = new ModuleCompiler(
-      new AnalyzerOptions.fromArguments(argResults, declaredVars));
+  var compiler = new ModuleCompiler(analyzerOptions);
   var compilerOpts = new CompilerOptions.fromArguments(argResults);
   var outPaths = argResults['out'] as List<String>;
   var moduleFormats = parseModuleFormatOption(argResults);
diff --git a/pkg/dev_compiler/test/browser/language_tests.js b/pkg/dev_compiler/test/browser/language_tests.js
index 2e2c6d4..56f7196 100644
--- a/pkg/dev_compiler/test/browser/language_tests.js
+++ b/pkg/dev_compiler/test/browser/language_tests.js
@@ -471,8 +471,6 @@
       'interactive_test': async_unittest,
       'isolates_test': async_unittest,
 
-      // Failing on "identical JS objects should have identical proxies".
-      'js_test': 'fail',
       'js_interop_1_test': async_unittest,
 
       // Failing because accessing "zSomeInvalidName" does not throw.
diff --git a/pkg/dev_compiler/test/codegen_test.dart b/pkg/dev_compiler/test/codegen_test.dart
index 66ee94e..4c4446c 100644
--- a/pkg/dev_compiler/test/codegen_test.dart
+++ b/pkg/dev_compiler/test/codegen_test.dart
@@ -21,7 +21,7 @@
         UriBasedDirective,
         parseDirectives;
 import 'package:analyzer/src/command_line/arguments.dart'
-    show extractDefinedVariables;
+    show defineAnalysisArguments;
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/generated/source.dart' show Source;
 import 'package:args/args.dart' show ArgParser, ArgResults;
@@ -79,7 +79,7 @@
       .where((p) => p.endsWith('.sum'))
       .toList();
 
-  var sharedCompiler = new ModuleCompiler(new AnalyzerOptions(
+  var sharedCompiler = new ModuleCompiler(new AnalyzerOptions.basic(
       dartSdkSummaryPath: sdkSummaryFile, summaryPaths: summaryPaths));
 
   var testDirs = [
@@ -104,6 +104,8 @@
   // Our default compiler options. Individual tests can override these.
   var defaultOptions = ['--no-source-map', '--no-summarize'];
   var compileArgParser = new ArgParser();
+  defineAnalysisArguments(compileArgParser, ddc: true);
+  AnalyzerOptions.addArguments(compileArgParser);
   CompilerOptions.addArguments(compileArgParser);
   addModuleFormatOptions(compileArgParser);
 
@@ -138,16 +140,12 @@
         args.addAll(matchedArgs.where((s) => !ignoreOptions.contains(s)));
       }
 
-      var declaredVars = <String, String>{};
-      args = extractDefinedVariables(args, declaredVars);
-      ArgResults argResults;
-      try {
-        argResults = compileArgParser.parse(args);
-      } catch (e) {
-        print('Failed to parse $args');
-        rethrow;
-      }
+      ArgResults argResults = compileArgParser.parse(args);
+      var analyzerOptions = new AnalyzerOptions.fromArguments(argResults,
+          dartSdkSummaryPath: sdkSummaryFile, summaryPaths: summaryPaths);
+
       var options = new CompilerOptions.fromArguments(argResults);
+
       var moduleFormat = parseModuleFormatOption(argResults).first;
 
       // Collect any other files we've imported.
@@ -157,11 +155,8 @@
           name, path.dirname(testFile), files.toList(), _moduleForLibrary);
 
       var compiler = sharedCompiler;
-      if (declaredVars.isNotEmpty) {
-        compiler = new ModuleCompiler(new AnalyzerOptions(
-            dartSdkSummaryPath: sdkSummaryFile,
-            summaryPaths: summaryPaths,
-            declaredVariables: declaredVars));
+      if (analyzerOptions.declaredVariables.isNotEmpty) {
+        compiler = new ModuleCompiler(analyzerOptions);
       }
       var module = compiler.compile(unit, options);
 
diff --git a/pkg/dev_compiler/tool/input_sdk/lib/html/dart2js/html_dart2js.dart b/pkg/dev_compiler/tool/input_sdk/lib/html/dart2js/html_dart2js.dart
index e103c7d..d24f6da 100644
--- a/pkg/dev_compiler/tool/input_sdk/lib/html/dart2js/html_dart2js.dart
+++ b/pkg/dev_compiler/tool/input_sdk/lib/html/dart2js/html_dart2js.dart
@@ -1214,8 +1214,8 @@
     return _create_2(blobParts, bag);
   }
 
-  static _create_1(parts) => JS('Blob', 'new Blob(#)', parts);
-  static _create_2(parts, bag) => JS('Blob', 'new Blob(#, #)', parts, bag);
+  static _create_1(parts) => JS('Blob', 'new window.Blob(#)', parts);
+  static _create_2(parts, bag) => JS('Blob', 'new window.Blob(#, #)', parts, bag);
 
   static _create_bag() => JS('var', '{}');
   static _bag_set(bag, key, value) { JS('void', '#[#] = #', bag, key, value); }
diff --git a/pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dart b/pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dart
index 34636a7..3fc25ad 100644
--- a/pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dart
+++ b/pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dart
@@ -273,7 +273,7 @@
     }
     if (args != null) args = new List.from(args.map(_convertToJS));
     var fn = JS('', '#[#]', _jsObject, method);
-    if (!JS('bool', '# instanceof Function', fn)) {
+    if (JS('bool', 'typeof(#) !== "function"', fn)) {
       throw new NoSuchMethodError(_jsObject, new Symbol(method), args, {});
     }
     return _convertToDart(JS('', '#.apply(#, #)', fn, _jsObject, args));
@@ -435,10 +435,12 @@
     '# instanceof Blob || '
     '# instanceof Event || '
     '(window.KeyRange && # instanceof KeyRange) || '
+    '(window.IDBKeyRange && # instanceof IDBKeyRange) || '
     '# instanceof ImageData || '
     '# instanceof Node || '
-    '(window.TypedData && # instanceof TypedData) || '
-    '# instanceof Window', o, o, o, o, o, o, o);
+    // Int8Array.__proto__ is TypedArray.
+    '(window.Int8Array && # instanceof Int8Array.__proto__) || '
+    '# instanceof Window', o, o, o, o, o, o, o, o);
 
 class _DartObject {
   final _dartObj;
@@ -491,11 +493,13 @@
              JS('bool', 'dart.jsobject != dart.getReifiedType(#)', o)) {
     return o._dartObj;
   } else {
-    return _putIfAbsent(_dartProxies, o, _wrapToDart);
+    return _wrapToDart(o);
   }
 }
 
-JsObject _wrapToDart(o) {
+JsObject _wrapToDart(o) => _putIfAbsent(_dartProxies, o, _wrapToDartHelper);
+
+JsObject _wrapToDartHelper(o) {
   if (JS('bool', 'typeof # == "function"', o)) {
     return new JsFunction._fromJs(o);
   }
diff --git a/pkg/dev_compiler/web/web_command.dart b/pkg/dev_compiler/web/web_command.dart
index bc4c1ad..3462633 100644
--- a/pkg/dev_compiler/web/web_command.dart
+++ b/pkg/dev_compiler/web/web_command.dart
@@ -116,7 +116,7 @@
     var fileResolvers = [summaryResolver, resourceUriResolver];
 
     var compiler = new ModuleCompiler(
-        new AnalyzerOptions(dartSdkPath: '/dart-sdk'),
+        new AnalyzerOptions.basic(dartSdkPath: '/dart-sdk'),
         sdkResolver: sdkResolver,
         fileResolvers: fileResolvers,
         resourceProvider: resourceProvider);
diff --git a/pkg/front_end/lib/compiler_options.dart b/pkg/front_end/lib/compiler_options.dart
index fdebf67..5230f4e 100644
--- a/pkg/front_end/lib/compiler_options.dart
+++ b/pkg/front_end/lib/compiler_options.dart
@@ -36,6 +36,8 @@
   ///
   /// If `null`, the ".packages" file will be found via the standard
   /// package_config search algorithm.
+  ///
+  /// If the empty string, no packages file will be used.
   String packagesFilePath;
 
   /// Paths to the input summary files (excluding the SDK summary).  These files
diff --git a/pkg/front_end/lib/dependency_grapher.dart b/pkg/front_end/lib/dependency_grapher.dart
index 7f9fbc8..a743168 100644
--- a/pkg/front_end/lib/dependency_grapher.dart
+++ b/pkg/front_end/lib/dependency_grapher.dart
@@ -12,6 +12,7 @@
 import 'package:front_end/src/async_dependency_walker.dart';
 import 'package:front_end/src/base/uri_resolver.dart';
 import 'package:front_end/src/scanner/scanner.dart';
+import 'package:package_config/packages_file.dart' as package_config;
 
 import 'compiler_options.dart';
 
@@ -22,11 +23,23 @@
 /// in the program.
 Future<Graph> graphForProgram(
     List<Uri> sources, CompilerOptions options) async {
-  var packages = <String, Uri>{}; // TODO(paulberry): support packages
+  Map<String, Uri> packages;
+  if (options.packagesFilePath == null) {
+    throw new UnimplementedError(); // TODO(paulberry): search for .packages
+  } else if (options.packagesFilePath.isEmpty) {
+    packages = {};
+  } else {
+    var contents = await options.fileSystem
+        .entityForPath(options.packagesFilePath)
+        .readAsBytes();
+    var baseLocation =
+        options.fileSystem.context.toUri(options.packagesFilePath);
+    packages = package_config.parse(contents, baseLocation);
+  }
   var sdkLibraries = <String, Uri>{}; // TODO(paulberry): support SDK libraries
   var uriResolver =
       new UriResolver(packages, sdkLibraries, options.fileSystem.context);
-  var walker = new _Walker(options.fileSystem, uriResolver);
+  var walker = new _Walker(options.fileSystem, uriResolver, options.compileSdk);
   var startingPoint = new _StartingPoint(walker, sources);
   await walker.walk(startingPoint);
   return walker.graph;
@@ -97,8 +110,9 @@
   final UriResolver uriResolver;
   final _nodesByUri = <Uri, _WalkerNode>{};
   final graph = new Graph._();
+  final bool compileSdk;
 
-  _Walker(this.fileSystem, this.uriResolver);
+  _Walker(this.fileSystem, this.uriResolver, this.compileSdk);
 
   @override
   Future<Null> evaluate(_WalkerNode v) {
@@ -124,6 +138,7 @@
 }
 
 class _WalkerNode extends Node<_WalkerNode> {
+  static final dartCoreUri = Uri.parse('dart:core');
   final _Walker walker;
   final Uri uri;
   final LibraryNode library;
@@ -136,14 +151,30 @@
   Future<List<_WalkerNode>> computeDependencies() async {
     var dependencies = <_WalkerNode>[];
     // TODO(paulberry): add error recovery if the file can't be read.
-    var contents = await walker.fileSystem
-        .entityForPath(walker.uriResolver.resolve(uri))
-        .readAsString();
+    var path = walker.uriResolver.resolve(uri);
+    if (path == null) {
+      // TODO(paulberry): If an error reporter was provided, report the error
+      // in the proper way and continue.
+      throw new StateError('Invalid URI: $uri');
+    }
+    var contents = await walker.fileSystem.entityForPath(path).readAsString();
     var scanner = new _Scanner(contents);
     var token = scanner.tokenize();
     // TODO(paulberry): report errors.
     var parser = new Parser(null, AnalysisErrorListener.NULL_LISTENER);
     var unit = parser.parseDirectives(token);
+    bool coreUriFound = false;
+    void handleDependency(Uri referencedUri) {
+      _WalkerNode dependencyNode = walker.nodeForUri(referencedUri);
+      library.dependencies.add(dependencyNode.library);
+      if (referencedUri.scheme != 'dart' || walker.compileSdk) {
+        dependencies.add(dependencyNode);
+      }
+      if (referencedUri == dartCoreUri) {
+        coreUriFound = true;
+      }
+    }
+
     for (var directive in unit.directives) {
       if (directive is UriBasedDirective) {
         // TODO(paulberry): when we support SDK libraries, we'll need more
@@ -152,12 +183,13 @@
         if (directive is PartDirective) {
           library.parts.add(referencedUri);
         } else {
-          _WalkerNode dependencyNode = walker.nodeForUri(referencedUri);
-          dependencies.add(dependencyNode);
-          library.dependencies.add(dependencyNode.library);
+          handleDependency(referencedUri);
         }
       }
     }
+    if (!coreUriFound) {
+      handleDependency(dartCoreUri);
+    }
     return dependencies;
   }
 }
diff --git a/pkg/front_end/test/dependency_grapher_test.dart b/pkg/front_end/test/dependency_grapher_test.dart
index 34640c6..bcfca56 100644
--- a/pkg/front_end/test/dependency_grapher_test.dart
+++ b/pkg/front_end/test/dependency_grapher_test.dart
@@ -20,7 +20,8 @@
 @reflectiveTest
 class DependencyGrapherTest {
   LibraryNode checkLibrary(LibraryCycleNode cycle, String uri,
-      {List<String> dependencies: const [], List<String> parts: const []}) {
+      {List<String> dependencies: const ['dart:core'],
+      List<String> parts: const []}) {
     var library = cycle.libraries[Uri.parse(uri)];
     expect('${library.uri}', uri);
     expect(library.dependencies.map((dep) => '${dep.uri}'),
@@ -30,7 +31,7 @@
   }
 
   Future<List<LibraryCycleNode>> getCycles(Map<String, String> contents,
-      [List<String> startingPoints]) async {
+      {List<String> startingPoints, String packagesFilePath = ''}) async {
     // If no starting points given, assume the first entry in [contents] is the
     // single starting point.
     startingPoints ??= [contents.keys.first];
@@ -41,7 +42,8 @@
     // TODO(paulberry): implement and test other option possibilities.
     var options = new CompilerOptions()
       ..fileSystem = fileSystem
-      ..chaseDependencies = true;
+      ..chaseDependencies = true
+      ..packagesFilePath = packagesFilePath;
     var graph = await graphForProgram(
         startingPoints.map(pathos.posix.toUri).toList(), options);
     return graph.topologicallySortedCycles;
@@ -56,6 +58,15 @@
     return result;
   }
 
+  test_explicitCoreDependency() async {
+    // If "dart:core" is explicitly imported, there shouldn't be two imports of
+    // "dart:core", just one.
+    var cycles = await getCycles({'/foo.dart': 'import "dart:core";'});
+    expect(cycles, hasLength(1));
+    expect(cycles[0].libraries, hasLength(1));
+    checkLibrary(cycles[0], 'file:///foo.dart');
+  }
+
   test_exportDependency() async {
     var cycles =
         await getCycles({'/foo.dart': 'export "bar.dart";', '/bar.dart': ''});
@@ -64,7 +75,7 @@
     checkLibrary(cycles[0], 'file:///bar.dart');
     expect(cycles[1].libraries, hasLength(1));
     checkLibrary(cycles[1], 'file:///foo.dart',
-        dependencies: ['file:///bar.dart']);
+        dependencies: ['file:///bar.dart', 'dart:core']);
   }
 
   test_importDependency() async {
@@ -75,7 +86,7 @@
     checkLibrary(cycles[0], 'file:///bar.dart');
     expect(cycles[1].libraries, hasLength(1));
     checkLibrary(cycles[1], 'file:///foo.dart',
-        dependencies: ['file:///bar.dart']);
+        dependencies: ['file:///bar.dart', 'dart:core']);
   }
 
   test_multipleStartingPoints() async {
@@ -83,7 +94,7 @@
       '/a.dart': 'import "c.dart";',
       '/b.dart': 'import "c.dart";',
       '/c.dart': ''
-    }, [
+    }, startingPoints: [
       '/a.dart',
       '/b.dart'
     ]);
@@ -94,9 +105,27 @@
     // reproducibility.
     List<LibraryCycleNode> otherCycles = sortCycles(cycles.sublist(1));
     checkLibrary(otherCycles[0], 'file:///a.dart',
-        dependencies: ['file:///c.dart']);
+        dependencies: ['file:///c.dart', 'dart:core']);
     checkLibrary(otherCycles[1], 'file:///b.dart',
-        dependencies: ['file:///c.dart']);
+        dependencies: ['file:///c.dart', 'dart:core']);
+  }
+
+  test_packages() async {
+    var cycles = await getCycles({
+      '/foo.dart': 'import "package:foo/bar.dart";',
+      '/.packages': 'foo:pkg/foo/lib\nbar:pkg/bar/lib\n',
+      '/pkg/foo/lib/bar.dart': 'import "package:bar/baz.dart";',
+      '/pkg/bar/lib/baz.dart': ''
+    }, packagesFilePath: '/.packages');
+    expect(cycles, hasLength(3));
+    expect(cycles[0].libraries, hasLength(1));
+    checkLibrary(cycles[0], 'package:bar/baz.dart');
+    expect(cycles[1].libraries, hasLength(1));
+    checkLibrary(cycles[1], 'package:foo/bar.dart',
+        dependencies: ['package:bar/baz.dart', 'dart:core']);
+    expect(cycles[2].libraries, hasLength(1));
+    checkLibrary(cycles[2], 'file:///foo.dart',
+        dependencies: ['package:foo/bar.dart', 'dart:core']);
   }
 
   test_parts() async {
@@ -123,13 +152,23 @@
     checkLibrary(cycles[0], 'file:///b/f.dart');
     expect(cycles[1].libraries, hasLength(1));
     checkLibrary(cycles[1], 'file:///b/d/e.dart',
-        dependencies: ['file:///b/f.dart']);
+        dependencies: ['file:///b/f.dart', 'dart:core']);
     expect(cycles[2].libraries, hasLength(1));
     checkLibrary(cycles[2], 'file:///b/c.dart',
-        dependencies: ['file:///b/d/e.dart']);
+        dependencies: ['file:///b/d/e.dart', 'dart:core']);
     expect(cycles[3].libraries, hasLength(1));
     checkLibrary(cycles[3], 'file:///a.dart',
-        dependencies: ['file:///b/c.dart']);
+        dependencies: ['file:///b/c.dart', 'dart:core']);
+  }
+
+  test_sdkDependency() async {
+    // Dependencies on the SDK should be recorded even if SDK libraries aren't
+    // being included in the graph.
+    var cycles = await getCycles({'/foo.dart': 'import "dart:async";'});
+    expect(cycles, hasLength(1));
+    expect(cycles[0].libraries, hasLength(1));
+    checkLibrary(cycles[0], 'file:///foo.dart',
+        dependencies: ['dart:core', 'dart:async']);
   }
 
   test_simpleCycle() async {
@@ -138,9 +177,9 @@
     expect(cycles, hasLength(1));
     expect(cycles[0].libraries, hasLength(2));
     var foo = checkLibrary(cycles[0], 'file:///foo.dart',
-        dependencies: ['file:///bar.dart']);
+        dependencies: ['file:///bar.dart', 'dart:core']);
     var bar = checkLibrary(cycles[0], 'file:///bar.dart',
-        dependencies: ['file:///foo.dart']);
+        dependencies: ['file:///foo.dart', 'dart:core']);
     expect(foo.dependencies[0], same(bar));
     expect(bar.dependencies[0], same(foo));
   }
diff --git a/runtime/bin/directory_android.cc b/runtime/bin/directory_android.cc
index 49077a3..b4ad7c0 100644
--- a/runtime/bin/directory_android.cc
+++ b/runtime/bin/directory_android.cc
@@ -351,6 +351,9 @@
     if (S_ISDIR(entry_info.st_mode)) {
       return EXISTS;
     } else {
+      // An OSError may be constructed based on the return value of this
+      // function, so set errno to something that makes sense.
+      errno = ENOTDIR;
       return DOES_NOT_EXIST;
     }
   } else {
diff --git a/runtime/bin/directory_fuchsia.cc b/runtime/bin/directory_fuchsia.cc
index 94a86d1..9259bd0 100644
--- a/runtime/bin/directory_fuchsia.cc
+++ b/runtime/bin/directory_fuchsia.cc
@@ -249,6 +249,9 @@
     if (S_ISDIR(entry_info.st_mode)) {
       return EXISTS;
     } else {
+      // An OSError may be constructed based on the return value of this
+      // function, so set errno to something that makes sense.
+      errno = ENOTDIR;
       return DOES_NOT_EXIST;
     }
   } else {
@@ -352,6 +355,8 @@
     }
     return NO_RETRY_EXPECTED(rmdir(dir_name)) == 0;
   } else {
+    // TODO(MG-416): After the issue is addressed, this can use the same code
+    // as on Linux, etc.
     UNIMPLEMENTED();
     return false;
   }
diff --git a/runtime/bin/directory_linux.cc b/runtime/bin/directory_linux.cc
index 357a580..f2a064a 100644
--- a/runtime/bin/directory_linux.cc
+++ b/runtime/bin/directory_linux.cc
@@ -360,6 +360,9 @@
     if (S_ISDIR(entry_info.st_mode)) {
       return EXISTS;
     } else {
+      // An OSError may be constructed based on the return value of this
+      // function, so set errno to something that makes sense.
+      errno = ENOTDIR;
       return DOES_NOT_EXIST;
     }
   } else {
diff --git a/runtime/bin/directory_macos.cc b/runtime/bin/directory_macos.cc
index b24b9c8..ca0d41b 100644
--- a/runtime/bin/directory_macos.cc
+++ b/runtime/bin/directory_macos.cc
@@ -351,6 +351,9 @@
     if (S_ISDIR(entry_info.st_mode)) {
       return EXISTS;
     } else {
+      // An OSError may be constructed based on the return value of this
+      // function, so set errno to something that makes sense.
+      errno = ENOTDIR;
       return DOES_NOT_EXIST;
     }
   } else {
diff --git a/runtime/bin/file_fuchsia.cc b/runtime/bin/file_fuchsia.cc
index bda6113..ff08043 100644
--- a/runtime/bin/file_fuchsia.cc
+++ b/runtime/bin/file_fuchsia.cc
@@ -16,6 +16,7 @@
 #include <unistd.h>     // NOLINT
 
 #include "bin/builtin.h"
+#include "bin/fdutils.h"
 #include "bin/log.h"
 #include "platform/signal_blocker.h"
 #include "platform/utils.h"
@@ -280,7 +281,48 @@
 
 
 bool File::Copy(const char* old_path, const char* new_path) {
-  UNIMPLEMENTED();
+  File::Type type = File::GetType(old_path, true);
+  if (type == kIsFile) {
+    struct stat64 st;
+    if (NO_RETRY_EXPECTED(stat64(old_path, &st)) != 0) {
+      return false;
+    }
+    int old_fd = NO_RETRY_EXPECTED(open64(old_path, O_RDONLY | O_CLOEXEC));
+    if (old_fd < 0) {
+      return false;
+    }
+    int new_fd = NO_RETRY_EXPECTED(
+        open64(new_path, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, st.st_mode));
+    if (new_fd < 0) {
+      VOID_TEMP_FAILURE_RETRY(close(old_fd));
+      return false;
+    }
+    // TODO(MG-429): Use sendfile/copyfile or equivalent when there is one.
+    intptr_t result;
+    const intptr_t kBufferSize = 8 * KB;
+    uint8_t buffer[kBufferSize];
+    while ((result = NO_RETRY_EXPECTED(read(old_fd, buffer, kBufferSize))) >
+           0) {
+      int wrote = NO_RETRY_EXPECTED(write(new_fd, buffer, result));
+      if (wrote != result) {
+        result = -1;
+        break;
+      }
+    }
+    FDUtils::SaveErrorAndClose(old_fd);
+    FDUtils::SaveErrorAndClose(new_fd);
+    if (result < 0) {
+      int e = errno;
+      VOID_NO_RETRY_EXPECTED(unlink(new_path));
+      errno = e;
+      return false;
+    }
+    return true;
+  } else if (type == kIsDirectory) {
+    errno = EISDIR;
+  } else {
+    errno = ENOENT;
+  }
   return false;
 }
 
@@ -353,6 +395,8 @@
 
 
 const char* File::GetCanonicalPath(const char* pathname) {
+  // TODO(MG-425): realpath() is not implemented.
+#if 0
   char* abs_path = NULL;
   if (pathname != NULL) {
     char* resolved_path = DartUtils::ScopedCString(PATH_MAX + 1);
@@ -364,6 +408,9 @@
     ASSERT((abs_path == NULL) || (abs_path == resolved_path));
   }
   return abs_path;
+#else
+  return pathname;
+#endif
 }
 
 
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index e18f2f5..05b3842 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -1055,7 +1055,7 @@
   Dart_Handle result;
 
   // Precompile with specified embedder entry points
-  result = Dart_Precompile(standalone_entry_points, true);
+  result = Dart_Precompile(standalone_entry_points, true, NULL, 0);
   CHECK_RESULT(result);
 
   // Create a precompiled snapshot.
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 28804f4..f64e4a8 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -65,6 +65,16 @@
 
 static const char* frontend_filename = NULL;
 
+// Value of the --save-feedback flag.
+// (This pointer points into an argv buffer and does not need to be
+// free'd.)
+static const char* save_feedback_filename = NULL;
+
+// Value of the --load-feedback flag.
+// (This pointer points into an argv buffer and does not need to be
+// free'd.)
+static const char* load_feedback_filename = NULL;
+
 // Value of the --package-root flag.
 // (This pointer points into an argv buffer and does not need to be
 // free'd.)
@@ -221,6 +231,28 @@
 }
 
 
+static bool ProcessSaveFeedbackOption(const char* arg,
+                                      CommandLineOptions* vm_options) {
+  ASSERT(arg != NULL);
+  if (*arg == '-') {
+    return false;
+  }
+  save_feedback_filename = arg;
+  return true;
+}
+
+
+static bool ProcessLoadFeedbackOption(const char* arg,
+                                      CommandLineOptions* vm_options) {
+  ASSERT(arg != NULL);
+  if (*arg == '-') {
+    return false;
+  }
+  load_feedback_filename = arg;
+  return true;
+}
+
+
 static void* GetHashmapKeyFromString(char* key) {
   return reinterpret_cast<void*>(key);
 }
@@ -564,6 +596,8 @@
     {"--snapshot=", ProcessSnapshotFilenameOption},
     {"--snapshot-kind=", ProcessSnapshotKindOption},
     {"--use-blobs", ProcessUseBlobsOption},
+    {"--save-feedback=", ProcessSaveFeedbackOption},
+    {"--load-feedback=", ProcessLoadFeedbackOption},
     {"--trace-loading", ProcessTraceLoadingOption},
     {"--hot-reload-test-mode", ProcessHotReloadTestModeOption},
     {"--hot-reload-rollback-test-mode", ProcessHotReloadRollbackTestModeOption},
@@ -1297,8 +1331,10 @@
     Platform::Exit(kErrorExitCode);
   }
 
-  *vmisolate_buffer = reinterpret_cast<const uint8_t*>(read_only_buffer) +
-                      (vmisolate_position - vmisolate_position);
+  if (vmisolate_size != 0) {
+    *vmisolate_buffer = reinterpret_cast<const uint8_t*>(read_only_buffer) +
+                        (vmisolate_position - vmisolate_position);
+  }
   *isolate_buffer = reinterpret_cast<const uint8_t*>(read_only_buffer) +
                     (isolate_position - vmisolate_position);
   if (rodata_size == 0) {
@@ -1497,7 +1533,7 @@
 
 
 #if defined(TARGET_ARCH_X64)
-static void GeneratePrecompiledJITSnapshot() {
+static void GenerateAppJITSnapshot() {
   uint8_t* vm_isolate_buffer = NULL;
   intptr_t vm_isolate_size = 0;
   uint8_t* isolate_buffer = NULL;
@@ -1507,9 +1543,8 @@
   uint8_t* rodata_blob_buffer = NULL;
   intptr_t rodata_blob_size = 0;
   Dart_Handle result = Dart_CreateAppJITSnapshot(
-      &vm_isolate_buffer, &vm_isolate_size, &isolate_buffer, &isolate_size,
-      &instructions_blob_buffer, &instructions_blob_size, &rodata_blob_buffer,
-      &rodata_blob_size);
+      &isolate_buffer, &isolate_size, &instructions_blob_buffer,
+      &instructions_blob_size, &rodata_blob_buffer, &rodata_blob_size);
   if (Dart_IsError(result)) {
     ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result));
   }
@@ -1528,7 +1563,7 @@
   if (Dart_IsError(result)) {
     ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result));
   }
-  GeneratePrecompiledJITSnapshot();
+  GenerateAppJITSnapshot();
 #else
   // Create an application snapshot of the script.
   uint8_t* vm_isolate_buffer = NULL;
@@ -1687,8 +1722,27 @@
           {NULL, NULL, NULL}  // Must be terminated with NULL entries.
       };
 
+      uint8_t* feedback_buffer = NULL;
+      intptr_t feedback_length = 0;
+      if (load_feedback_filename != NULL) {
+        File* file = File::Open(load_feedback_filename, File::kRead);
+        if (file == NULL) {
+          ErrorExit(kErrorExitCode, "Failed to read JIT feedback.\n");
+        }
+        feedback_length = file->Length();
+        feedback_buffer = reinterpret_cast<uint8_t*>(malloc(feedback_length));
+        if (!file->ReadFully(feedback_buffer, feedback_length)) {
+          ErrorExit(kErrorExitCode, "Failed to read JIT feedback.\n");
+        }
+        file->Release();
+      }
+
       const bool reset_fields = gen_snapshot_kind == kAppAOT;
-      result = Dart_Precompile(standalone_entry_points, reset_fields);
+      result = Dart_Precompile(standalone_entry_points, reset_fields,
+                               feedback_buffer, feedback_length);
+      if (feedback_buffer != NULL) {
+        free(feedback_buffer);
+      }
       CHECK_RESULT(result);
     }
 
@@ -1732,6 +1786,16 @@
         }
       }
       CHECK_RESULT(result);
+
+      if (save_feedback_filename != NULL) {
+        uint8_t* buffer = NULL;
+        intptr_t size = 0;
+        result = Dart_SaveJITFeedback(&buffer, &size);
+        if (Dart_IsError(result)) {
+          ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result));
+        }
+        WriteSnapshotFile(save_feedback_filename, false, buffer, size);
+      }
     }
   }
 
diff --git a/runtime/bin/platform_fuchsia.cc b/runtime/bin/platform_fuchsia.cc
index caa5aef..53f07ac 100644
--- a/runtime/bin/platform_fuchsia.cc
+++ b/runtime/bin/platform_fuchsia.cc
@@ -10,6 +10,7 @@
 #include <string.h>  // NOLINT
 #include <unistd.h>  // NOLINT
 
+#include "bin/dartutils.h"
 #include "bin/fdutils.h"
 #include "bin/file.h"
 
@@ -52,15 +53,59 @@
 
 
 char** Platform::Environment(intptr_t* count) {
-  char** result =
-      reinterpret_cast<char**>(Dart_ScopeAllocate(1 * sizeof(*result)));
-  result[0] = NULL;
+  // Using environ directly is only safe as long as we do not
+  // provide access to modifying environment variables.
+  intptr_t i = 0;
+  char** tmp = environ;
+  while (*(tmp++) != NULL) {
+    i++;
+  }
+  *count = i;
+  char** result;
+  result = reinterpret_cast<char**>(Dart_ScopeAllocate(i * sizeof(*result)));
+  for (intptr_t current = 0; current < i; current++) {
+    result[current] = environ[current];
+  }
   return result;
 }
 
 
 const char* Platform::ResolveExecutablePath() {
-  return "dart";
+  // The string used on the command line to spawn the executable is in argv_[0].
+  // If that string is a relative or absolute path, i.e. it contains a '/', then
+  // we make the path absolute if it is not already and return it. If argv_[0]
+  // does not contain a '/', we assume it is a program whose location is
+  // resolved via the PATH environment variable, and search for it using the
+  // paths found there.
+  const char* path = getenv("PATH");
+  if ((strchr(argv_[0], '/') != NULL) || (path == NULL)) {
+    if (argv_[0][0] == '/') {
+      return File::GetCanonicalPath(argv_[0]);
+    } else {
+      char* result = DartUtils::ScopedCString(PATH_MAX + 1);
+      char* cwd = DartUtils::ScopedCString(PATH_MAX + 1);
+      getcwd(cwd, PATH_MAX);
+      snprintf(result, PATH_MAX, "%s/%s", cwd, argv_[0]);
+      result[PATH_MAX] = '\0';
+      ASSERT(File::Exists(result));
+      return File::GetCanonicalPath(result);
+    }
+  } else {
+    char* pathcopy = DartUtils::ScopedCopyCString(path);
+    char* result = DartUtils::ScopedCString(PATH_MAX + 1);
+    char* save = NULL;
+    while ((pathcopy = strtok_r(pathcopy, ":", &save)) != NULL) {
+      snprintf(result, PATH_MAX, "%s/%s", pathcopy, argv_[0]);
+      result[PATH_MAX] = '\0';
+      if (File::Exists(result)) {
+        return File::GetCanonicalPath(result);
+      }
+      pathcopy = NULL;
+    }
+    // Couldn't find it. This causes null to be returned for
+    // Platform.resovledExecutable.
+    return NULL;
+  }
 }
 
 
diff --git a/runtime/bin/process_fuchsia.cc b/runtime/bin/process_fuchsia.cc
index 2bcef56..9eb4d74 100644
--- a/runtime/bin/process_fuchsia.cc
+++ b/runtime/bin/process_fuchsia.cc
@@ -22,6 +22,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/epoll.h>
 #include <unistd.h>
 
 #include "bin/dartutils.h"
@@ -29,6 +30,7 @@
 #include "bin/lockers.h"
 #include "bin/log.h"
 #include "platform/signal_blocker.h"
+#include "platform/utils.h"
 
 // #define PROCESS_LOGGING 1
 #if defined(PROCESS_LOGGING)
@@ -425,19 +427,164 @@
 }
 
 
+static bool ProcessWaitCleanup(intptr_t out,
+                               intptr_t err,
+                               intptr_t exit_event,
+                               intptr_t epoll_fd) {
+  int e = errno;
+  VOID_NO_RETRY_EXPECTED(close(out));
+  VOID_NO_RETRY_EXPECTED(close(err));
+  VOID_NO_RETRY_EXPECTED(close(exit_event));
+  VOID_NO_RETRY_EXPECTED(close(epoll_fd));
+  errno = e;
+  return false;
+}
+
+
+class BufferList : public BufferListBase {
+ public:
+  BufferList() {}
+
+  bool Read(int fd, intptr_t available) {
+    // Read all available bytes.
+    while (available > 0) {
+      if (free_size_ == 0) {
+        Allocate();
+      }
+      ASSERT(free_size_ > 0);
+      ASSERT(free_size_ <= kBufferSize);
+      intptr_t block_size = dart::Utils::Minimum(free_size_, available);
+      intptr_t bytes = NO_RETRY_EXPECTED(
+          read(fd, reinterpret_cast<void*>(FreeSpaceAddress()), block_size));
+      if (bytes < 0) {
+        return false;
+      }
+      data_size_ += bytes;
+      free_size_ -= bytes;
+      available -= bytes;
+    }
+    return true;
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BufferList);
+};
+
+
 bool Process::Wait(intptr_t pid,
                    intptr_t in,
                    intptr_t out,
                    intptr_t err,
                    intptr_t exit_event,
                    ProcessResult* result) {
-  UNIMPLEMENTED();
-  return false;
+  VOID_NO_RETRY_EXPECTED(close(in));
+
+  // There is no return from this function using Dart_PropagateError
+  // as memory used by the buffer lists is freed through their
+  // destructors.
+  BufferList out_data;
+  BufferList err_data;
+  union {
+    uint8_t bytes[8];
+    int32_t ints[2];
+  } exit_code_data;
+
+  // The initial size passed to epoll_create is ignore on newer (>=
+  // 2.6.8) Linux versions
+  static const int kEpollInitialSize = 64;
+  int epoll_fd = NO_RETRY_EXPECTED(epoll_create(kEpollInitialSize));
+  if (epoll_fd == -1) {
+    return ProcessWaitCleanup(out, err, exit_event, epoll_fd);
+  }
+  if (!FDUtils::SetCloseOnExec(epoll_fd)) {
+    return ProcessWaitCleanup(out, err, exit_event, epoll_fd);
+  }
+
+  struct epoll_event event;
+  event.events = EPOLLRDHUP | EPOLLIN;
+  event.data.fd = out;
+  int status = NO_RETRY_EXPECTED(
+      epoll_ctl(epoll_fd, EPOLL_CTL_ADD, out, &event));
+  if (status == -1) {
+    return ProcessWaitCleanup(out, err, exit_event, epoll_fd);
+  }
+  event.data.fd = err;
+  status = NO_RETRY_EXPECTED(
+      epoll_ctl(epoll_fd, EPOLL_CTL_ADD, err, &event));
+  if (status == -1) {
+    return ProcessWaitCleanup(out, err, exit_event, epoll_fd);
+  }
+  event.data.fd = exit_event;
+  status = NO_RETRY_EXPECTED(
+      epoll_ctl(epoll_fd, EPOLL_CTL_ADD, exit_event, &event));
+  if (status == -1) {
+    return ProcessWaitCleanup(out, err, exit_event, epoll_fd);
+  }
+  intptr_t active = 3;
+
+  static const intptr_t kMaxEvents = 16;
+  struct epoll_event events[kMaxEvents];
+  while (active > 0) {
+    // TODO(US-109): When the epoll implementation is properly edge-triggered,
+    // remove this sleep, which prevents the message queue from being
+    // overwhelmed and leading to memory exhaustion.
+    usleep(5000);
+    intptr_t result = NO_RETRY_EXPECTED(
+        epoll_wait(epoll_fd, events, kMaxEvents, -1));
+    if ((result < 0) && (errno != EWOULDBLOCK)) {
+      return ProcessWaitCleanup(out, err, exit_event, epoll_fd);
+    }
+    for (intptr_t i = 0; i < result; i++) {
+      if ((events[i].events & EPOLLIN) != 0) {
+        const intptr_t avail = FDUtils::AvailableBytes(events[i].data.fd);
+        if (events[i].data.fd == out) {
+          if (!out_data.Read(out, avail)) {
+            return ProcessWaitCleanup(out, err, exit_event, epoll_fd);
+          }
+        } else if (events[i].data.fd == err) {
+          if (!err_data.Read(err, avail)) {
+            return ProcessWaitCleanup(out, err, exit_event, epoll_fd);
+          }
+        } else if (events[i].data.fd == exit_event) {
+          if (avail == 8) {
+            intptr_t b =
+                NO_RETRY_EXPECTED(read(exit_event, exit_code_data.bytes, 8));
+            if (b != 8) {
+              return ProcessWaitCleanup(out, err, exit_event, epoll_fd);
+            }
+          }
+        } else {
+          UNREACHABLE();
+        }
+      }
+      if ((events[i].events & (EPOLLHUP | EPOLLRDHUP)) != 0) {
+        NO_RETRY_EXPECTED(close(events[i].data.fd));
+        active--;
+        VOID_NO_RETRY_EXPECTED(
+            epoll_ctl(epoll_fd, EPOLL_CTL_DEL, events[i].data.fd, NULL));
+      }
+    }
+  }
+  VOID_NO_RETRY_EXPECTED(close(epoll_fd));
+
+  // All handles closed and all data read.
+  result->set_stdout_data(out_data.GetData());
+  result->set_stderr_data(err_data.GetData());
+
+  // Calculate the exit code.
+  intptr_t exit_code = exit_code_data.ints[0];
+  intptr_t negative = exit_code_data.ints[1];
+  if (negative != 0) {
+    exit_code = -exit_code;
+  }
+  result->set_exit_code(exit_code);
+
+  return true;
 }
 
 
 bool Process::Kill(intptr_t id, int signal) {
-  UNIMPLEMENTED();
+  errno = ENOSYS;
   return false;
 }
 
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index e1092cc..800b837 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -1034,27 +1034,6 @@
                                                   intptr_t* size);
 
 /**
- * Creates a snapshot of the specified library loaded in the isolate.
- *
- * A library snapshot can be used for implementing fast startup of applications
- * (skips tokenizing and parsing process). A Snapshot of the library
- * can only be created before any dart code has executed.
- *
- * Requires there to be a current isolate which already has loaded the library.
- *
- * \param library A library for which the snapshot needs to be created.
- * \param buffer Returns a pointer to a buffer containing
- *   the snapshot. This buffer is scope allocated and is only valid
- *   until the next call to Dart_ExitScope.
- * \param size Returns the size of the buffer.
- *
- * \return A valid handle if no error occurs during the operation.
- */
-DART_EXPORT Dart_Handle Dart_CreateLibrarySnapshot(Dart_Handle library,
-                                                   uint8_t** buffer,
-                                                   intptr_t* size);
-
-/**
  * Schedules an interrupt for the specified isolate.
  *
  * When the isolate is interrupted, the isolate interrupt callback
@@ -3185,6 +3164,22 @@
  * ==============
  */
 
+/**
+ * Saves a serialized version of the information collected for use by the
+ * optimizing compiler, such as type feedback and usage counters. When this
+ * information is passed to Dart_Precompile, the AOT compiler may use it to
+ * produce faster and smaller code. The feedback is only used if the JIT that
+ * created it and the AOT compiler consuming it
+ *   - are running the same Dart program
+ *   - are built from the same version of the VM
+ *   - agree on whether type checks and assertions are enabled
+ *
+ * \return Returns an error handler if the VM was built in a mode that does not
+ * support saving JIT feedback.
+ */
+DART_EXPORT Dart_Handle Dart_SaveJITFeedback(uint8_t** buffer,
+                                             intptr_t* buffer_length);
+
 
 typedef struct {
   const char* library_uri;
@@ -3214,7 +3209,10 @@
  * constructors was encountered.
  */
 DART_EXPORT Dart_Handle
-Dart_Precompile(Dart_QualifiedFunctionName entry_points[], bool reset_fields);
+Dart_Precompile(Dart_QualifiedFunctionName entry_points[],
+                bool reset_fields,
+                uint8_t* jit_feedback,
+                intptr_t jit_feedback_length);
 
 
 /**
@@ -3285,9 +3283,7 @@
  * \return A valid handle if no error occurs during the operation.
  */
 DART_EXPORT Dart_Handle
-Dart_CreateAppJITSnapshot(uint8_t** vm_isolate_snapshot_buffer,
-                          intptr_t* vm_isolate_snapshot_size,
-                          uint8_t** isolate_snapshot_buffer,
+Dart_CreateAppJITSnapshot(uint8_t** isolate_snapshot_buffer,
                           intptr_t* isolate_snapshot_size,
                           uint8_t** instructions_blob_buffer,
                           intptr_t* instructions_blob_size,
diff --git a/runtime/observatory/lib/models.dart b/runtime/observatory/lib/models.dart
index a196975..71619ca 100644
--- a/runtime/observatory/lib/models.dart
+++ b/runtime/observatory/lib/models.dart
@@ -45,11 +45,13 @@
 part 'src/models/objects/sentinel.dart';
 part 'src/models/objects/source_location.dart';
 part 'src/models/objects/target.dart';
+part 'src/models/objects/thread.dart';
 part 'src/models/objects/token_stream.dart';
 part 'src/models/objects/timeline_event.dart';
 part 'src/models/objects/type_arguments.dart';
 part 'src/models/objects/unknown.dart';
 part 'src/models/objects/vm.dart';
+part 'src/models/objects/zone.dart';
 
 part 'src/models/repositories/allocation_profile.dart';
 part 'src/models/repositories/breakpoint.dart';
diff --git a/runtime/observatory/lib/src/models/objects/isolate.dart b/runtime/observatory/lib/src/models/objects/isolate.dart
index f114941..8cc5c79 100644
--- a/runtime/observatory/lib/src/models/objects/isolate.dart
+++ b/runtime/observatory/lib/src/models/objects/isolate.dart
@@ -51,6 +51,9 @@
   /// [optional] The error that is causing this isolate to exit, if applicable.
   Error get error;
 
+  /// The list of threads associated with this isolate.
+  Iterable<Thread> get threads;
+
   /// The current pause on exception mode for this isolate.
   //ExceptionPauseMode get exceptionPauseMode;
 
diff --git a/runtime/observatory/lib/src/models/objects/thread.dart b/runtime/observatory/lib/src/models/objects/thread.dart
new file mode 100644
index 0000000..a62353f
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/thread.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+enum ThreadKind {
+  unknownTask,
+  mutatorTask,
+  compilerTask,
+  sweeperTask,
+  markerTask,
+  finalizerTask
+}
+
+abstract class Thread {
+  /// The id associated with the thread on creation.
+  String get id;
+
+  /// The task type associated with the thread.
+  ThreadKind get kind;
+
+  /// A list of all the zones held by the thread.
+  Iterable<Zone> get zones;
+}
diff --git a/runtime/observatory/lib/src/models/objects/zone.dart b/runtime/observatory/lib/src/models/objects/zone.dart
new file mode 100644
index 0000000..51840cb
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/zone.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class Zone {
+  /// The total amount of memory in bytes allocated in the zone, including
+  /// memory that is not actually being used.
+  int get capacity;
+
+  /// The total amount of memory in bytes actually used in the zone.
+  int get used;
+}
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index 58ef53f..3611ef8 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -238,6 +238,9 @@
       case 'SourceLocation':
         obj = new SourceLocation._empty(owner);
         break;
+      case '_Thread':
+        obj = new Thread._empty(owner);
+        break;
       case 'UnresolvedSourceLocation':
         obj = new UnresolvedSourceLocation._empty(owner);
         break;
@@ -1501,6 +1504,9 @@
 
   List<ByteData> _chunksInProgress;
 
+  List<Thread> get threads => _threads;
+  final List<Thread> _threads = new List<Thread>();
+
   void _loadHeapSnapshot(ServiceEvent event) {
     if (_snapshotFetch == null || _snapshotFetch.isClosed) {
       // No outstanding snapshot request. Presumably another client asked for a
@@ -1624,6 +1630,11 @@
     if (map['extensionRPCs'] != null) {
       extensionRPCs.addAll(map['extensionRPCs']);
     }
+
+    threads.clear();
+    if(map['threads'] != null) {
+      threads.addAll(map['threads']);
+    }
   }
 
   Future<TagProfile> updateTagProfile() {
@@ -3056,6 +3067,58 @@
   String get shortName => valueAsString;
 }
 
+class Thread extends ServiceObject implements M.Thread {
+  M.ThreadKind get kind => _kind;
+  M.ThreadKind _kind;
+  List<Zone> get zones => _zones;
+  final List<Zone> _zones = new List<Zone>();
+
+  Thread._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    String kindString = map['kind'];
+    List<Map> zoneList = map['zones'];
+
+    switch(kindString) {
+      case "kUnknownTask":
+        _kind = M.ThreadKind.unknownTask;
+        break;
+      case "kMutatorTask":
+        _kind = M.ThreadKind.mutatorTask;
+        break;
+      case "kCompilerTask":
+        _kind = M.ThreadKind.compilerTask;
+        break;
+      case "kSweeperTask":
+        _kind = M.ThreadKind.sweeperTask;
+        break;
+      case "kMarkerTask":
+        _kind = M.ThreadKind.markerTask;
+        break;
+      case "kFinalizerTask":
+        _kind = M.ThreadKind.finalizerTask;
+        break;
+      default:
+        assert(false);
+    }
+    zones.clear();
+    zoneList.forEach((zone) {
+      int capacity = zone['capacity'];
+      int used = zone['used'];
+      zones.add(new Zone(capacity, used));
+    });
+  }
+}
+
+class Zone implements M.Zone {
+  int get capacity => _capacity;
+  int _capacity;
+  int get used => _used;
+  int _used;
+
+  Zone(this._capacity, this._used);
+}
+
 class Field extends HeapObject implements M.Field {
   // Library or Class.
   HeapObject dartOwner;
diff --git a/runtime/observatory/observatory_sources.gypi b/runtime/observatory/observatory_sources.gypi
index c139cd3..a83a34c 100644
--- a/runtime/observatory/observatory_sources.gypi
+++ b/runtime/observatory/observatory_sources.gypi
@@ -173,11 +173,13 @@
     'lib/src/models/objects/sentinel.dart',
     'lib/src/models/objects/source_location.dart',
     'lib/src/models/objects/target.dart',
+    'lib/src/models/objects/thread.dart',
     'lib/src/models/objects/timeline_event.dart',
     'lib/src/models/objects/token_stream.dart',
     'lib/src/models/objects/type_arguments.dart',
     'lib/src/models/objects/unknown.dart',
     'lib/src/models/objects/vm.dart',
+    'lib/src/models/objects/zone.dart',
     'lib/src/models/repositories/allocation_profile.dart',
     'lib/src/models/repositories/breakpoint.dart',
     'lib/src/models/repositories/class.dart',
diff --git a/runtime/observatory/tests/service/get_zone_memory_info_rpc_test.dart b/runtime/observatory/tests/service/get_zone_memory_info_rpc_test.dart
new file mode 100644
index 0000000..7d5f004
--- /dev/null
+++ b/runtime/observatory/tests/service/get_zone_memory_info_rpc_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--error_on_bad_type --error_on_bad_override
+
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+
+import 'test_helper.dart';
+
+var tests = [
+  (VM vm) async {
+    isInstanceOf<int> isInt = new isInstanceOf<int>();
+    // Just iterate over all the isolates to confirm they have
+    // the correct fields needed to examine zone memory usage.
+    for (Isolate isolate in vm.isolates) {
+      await isolate.reload();
+
+      expect(isolate.threads, isNotNull);
+      List<Thread> threads = isolate.threads;
+
+      for (Thread thread in threads) {
+        expect(thread.type, equals('_Thread'));
+        expect(thread.id, isNotNull);
+        expect(thread.kind, isNotNull);
+        expect(thread.zones, isNotNull);
+        List<Zone> zones = thread.zones;
+
+        for (Zone zone in zones) {
+          expect(zone.capacity, isInt);
+          expect(zone.used, isInt);
+        }
+      }
+    }
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/tests/vm/dart/hello_fuchsia_test.dart b/runtime/tests/vm/dart/hello_fuchsia_test.dart
index bcda2bf..8053b85 100644
--- a/runtime/tests/vm/dart/hello_fuchsia_test.dart
+++ b/runtime/tests/vm/dart/hello_fuchsia_test.dart
@@ -380,10 +380,21 @@
 }
 
 Future testProcess() async {
-  Process p = await Process.start(Platform.executable, ["--version"]);
+  String exe = Platform.resolvedExecutable;
+  print("Running $exe --version");
+  Process p = await Process.start(exe, ["--version"]);
   p.stderr.transform(UTF8.decoder).listen(print);
   int code = await p.exitCode;
-  print("dart --version exited with code $code");
+  print("$exe --version exited with code $code");
+}
+
+void testProcessRunSync() {
+  String exe = Platform.resolvedExecutable;
+  print("Running $exe --version");
+  var result = Process.runSync(exe, ["--version"]);
+  print("$exe --version exited with code ${result.exitCode}");
+  print("$exe --version had stdout = '${result.stdout}'");
+  print("$exe --version had stderr = '${result.stderr}'");
 }
 
 Future testLs(String path) async {
@@ -393,6 +404,33 @@
   }
 }
 
+void testPlatformEnvironment() {
+  Map<String, String> env = Platform.environment;
+  for (String k in env.keys) {
+    String v = env[k];
+    print("$k = '$v'");
+  }
+}
+
+Future testCopy() async {
+  final String sourceName = "foo";
+  final String destName = "bar";
+  Directory tmp = await Directory.systemTemp.createTemp("testCopy");
+  File sourceFile = new File("${tmp.path}/$sourceName");
+  File destFile = new File("${tmp.path}/$destName");
+  List<int> data = new List<int>.generate(10 * 1024, (int i) => i & 0xff);
+  await sourceFile.writeAsBytes(data);
+  await sourceFile.copy(destFile.path);
+  List<int> resultData = await destFile.readAsBytes();
+  assert(data.length == resultData.length);
+  for (int i = 0; i < data.length; i++) {
+    assert(data[i] == resultData[i]);
+  }
+  await sourceFile.delete();
+  await destFile.delete();
+  await tmp.delete();
+}
+
 main() async {
   print("Hello, Fuchsia!");
 
@@ -428,9 +466,21 @@
   await testLs("/");
   print("lsTest done");
 
+  print("testPlatformEnvironment");
+  testPlatformEnvironment();
+  print("testPlatformEnvironment done");
+
   print("testProcess");
   await testProcess();
   print("testProcess done");
 
+  print("testProcessRunSync");
+  testProcessRunSync();
+  print("testProcessRunSync done");
+
+  print("testCopy");
+  await testCopy();
+  print("testCopy done");
+
   print("Goodbyte, Fuchsia!");
 }
diff --git a/runtime/vm/aot_optimizer.cc b/runtime/vm/aot_optimizer.cc
index 0013157..93501ec 100644
--- a/runtime/vm/aot_optimizer.cc
+++ b/runtime/vm/aot_optimizer.cc
@@ -100,32 +100,6 @@
 }
 
 
-void AotOptimizer::PopulateWithICData() {
-  ASSERT(current_iterator_ == NULL);
-  for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
-       !block_it.Done(); block_it.Advance()) {
-    ForwardInstructionIterator it(block_it.Current());
-    for (; !it.Done(); it.Advance()) {
-      Instruction* instr = it.Current();
-      if (instr->IsInstanceCall()) {
-        InstanceCallInstr* call = instr->AsInstanceCall();
-        if (!call->HasICData()) {
-          const Array& arguments_descriptor = Array::Handle(
-              zone(), ArgumentsDescriptor::New(call->ArgumentCount(),
-                                               call->argument_names()));
-          const ICData& ic_data = ICData::ZoneHandle(
-              zone(), ICData::New(function(), call->function_name(),
-                                  arguments_descriptor, call->deopt_id(),
-                                  call->checked_argument_count(), false));
-          call->set_ic_data(&ic_data);
-        }
-      }
-    }
-    current_iterator_ = NULL;
-  }
-}
-
-
 bool AotOptimizer::RecognizeRuntimeTypeGetter(InstanceCallInstr* call) {
   if ((precompiler_ == NULL) || !precompiler_->get_runtime_type_is_unique()) {
     return false;
@@ -1550,47 +1524,51 @@
     return;
   }
 
-  TypeRangeCache* cache = thread()->type_range_cache();
-  intptr_t lower_limit, upper_limit;
-  if (cache != NULL &&
-      cache->InstanceOfHasClassRange(type, &lower_limit, &upper_limit)) {
-    // left.instanceof(type) =>
-    //     _classRangeCheck(left.cid, lower_limit, upper_limit)
+  if (precompiler_ != NULL) {
+    TypeRangeCache* cache = precompiler_->type_range_cache();
+    intptr_t lower_limit, upper_limit;
+    if (cache != NULL &&
+        cache->InstanceOfHasClassRange(type, &lower_limit, &upper_limit)) {
+      // left.instanceof(type) =>
+      //     _classRangeCheck(left.cid, lower_limit, upper_limit)
 
-    LoadClassIdInstr* left_cid = new (Z) LoadClassIdInstr(new (Z) Value(left));
-    InsertBefore(call, left_cid, NULL, FlowGraph::kValue);
-    ConstantInstr* lower_cid =
-        flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(lower_limit)));
-    ConstantInstr* upper_cid =
-        flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(upper_limit)));
+      LoadClassIdInstr* left_cid =
+          new (Z) LoadClassIdInstr(new (Z) Value(left));
+      InsertBefore(call, left_cid, NULL, FlowGraph::kValue);
+      ConstantInstr* lower_cid =
+          flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(lower_limit)));
+      ConstantInstr* upper_cid =
+          flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(upper_limit)));
 
-    ZoneGrowableArray<PushArgumentInstr*>* args =
-        new (Z) ZoneGrowableArray<PushArgumentInstr*>(3);
-    PushArgumentInstr* arg = new (Z) PushArgumentInstr(new (Z) Value(left_cid));
-    InsertBefore(call, arg, NULL, FlowGraph::kEffect);
-    args->Add(arg);
-    arg = new (Z) PushArgumentInstr(new (Z) Value(lower_cid));
-    InsertBefore(call, arg, NULL, FlowGraph::kEffect);
-    args->Add(arg);
-    arg = new (Z) PushArgumentInstr(new (Z) Value(upper_cid));
-    InsertBefore(call, arg, NULL, FlowGraph::kEffect);
-    args->Add(arg);
+      ZoneGrowableArray<PushArgumentInstr*>* args =
+          new (Z) ZoneGrowableArray<PushArgumentInstr*>(3);
+      PushArgumentInstr* arg =
+          new (Z) PushArgumentInstr(new (Z) Value(left_cid));
+      InsertBefore(call, arg, NULL, FlowGraph::kEffect);
+      args->Add(arg);
+      arg = new (Z) PushArgumentInstr(new (Z) Value(lower_cid));
+      InsertBefore(call, arg, NULL, FlowGraph::kEffect);
+      args->Add(arg);
+      arg = new (Z) PushArgumentInstr(new (Z) Value(upper_cid));
+      InsertBefore(call, arg, NULL, FlowGraph::kEffect);
+      args->Add(arg);
 
-    const Library& dart_internal =
-        Library::Handle(Z, Library::InternalLibrary());
-    const String& target_name = negate ? Symbols::_classRangeCheckNegative()
-                                       : Symbols::_classRangeCheck();
-    const Function& target = Function::ZoneHandle(
-        Z, dart_internal.LookupFunctionAllowPrivate(target_name));
-    ASSERT(!target.IsNull());
-    ASSERT(target.IsRecognized() && target.always_inline());
+      const Library& dart_internal =
+          Library::Handle(Z, Library::InternalLibrary());
+      const String& target_name = negate ? Symbols::_classRangeCheckNegative()
+                                         : Symbols::_classRangeCheck();
+      const Function& target = Function::ZoneHandle(
+          Z, dart_internal.LookupFunctionAllowPrivate(target_name));
+      ASSERT(!target.IsNull());
+      ASSERT(target.IsRecognized() && target.always_inline());
 
-    StaticCallInstr* new_call =
-        new (Z) StaticCallInstr(call->token_pos(), target,
-                                Object::null_array(),  // argument_names
-                                args, call->deopt_id());
-    ReplaceCall(call, new_call);
-    return;
+      StaticCallInstr* new_call =
+          new (Z) StaticCallInstr(call->token_pos(), target,
+                                  Object::null_array(),  // argument_names
+                                  args, call->deopt_id());
+      ReplaceCall(call, new_call);
+      return;
+    }
   }
 
   const ICData& unary_checks =
diff --git a/runtime/vm/aot_optimizer.h b/runtime/vm/aot_optimizer.h
index 16e879e..2b8938d 100644
--- a/runtime/vm/aot_optimizer.h
+++ b/runtime/vm/aot_optimizer.h
@@ -28,10 +28,6 @@
 
   FlowGraph* flow_graph() const { return flow_graph_; }
 
-  // Add ICData to InstanceCalls, so that optimizations can be run on them.
-  // TODO(srdjan): StaticCals as well?
-  void PopulateWithICData();
-
   // Use ICData to optimize, replace or eliminate instructions.
   void ApplyICData();
 
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 65a001d..89f3be7 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -4666,6 +4666,12 @@
   }
   AddBaseObject(table->At(kDynamicCid));
   AddBaseObject(table->At(kVoidCid));
+
+  if (kind_ != Snapshot::kAppAOT) {
+    for (intptr_t i = 0; i < StubCode::NumEntries(); i++) {
+      AddBaseObject(StubCode::EntryAt(i)->code());
+    }
+  }
 }
 
 
@@ -4679,7 +4685,9 @@
   Push(symbols.raw());
   Push(scripts.raw());
   if (Snapshot::IncludesCode(kind_)) {
-    StubCode::Push(this);
+    for (intptr_t i = 0; i < StubCode::NumEntries(); i++) {
+      Push(StubCode::EntryAt(i)->code());
+    }
   }
 
   Serialize();
@@ -4688,7 +4696,9 @@
   WriteRef(symbols.raw());
   WriteRef(scripts.raw());
   if (Snapshot::IncludesCode(kind_)) {
-    StubCode::WriteRef(this);
+    for (intptr_t i = 0; i < StubCode::NumEntries(); i++) {
+      WriteRef(StubCode::EntryAt(i)->code());
+    }
   }
 
 #if defined(DEBUG)
@@ -5050,6 +5060,12 @@
   }
   AddBaseObject(table->At(kDynamicCid));
   AddBaseObject(table->At(kVoidCid));
+
+  if (kind_ != Snapshot::kAppAOT) {
+    for (intptr_t i = 0; i < StubCode::NumEntries(); i++) {
+      AddBaseObject(StubCode::EntryAt(i)->code());
+    }
+  }
 }
 
 
@@ -5071,7 +5087,11 @@
     isolate()->object_store()->set_symbol_table(symbol_table);
     ReadRef();  // Script list.
     if (Snapshot::IncludesCode(kind_)) {
-      StubCode::ReadRef(this);
+      Code& code = Code::Handle(zone_);
+      for (intptr_t i = 0; i < StubCode::NumEntries(); i++) {
+        code ^= ReadRef();
+        StubCode::EntryAtPut(i, new StubEntry(code));
+      }
     }
 
 #if defined(DEBUG)
@@ -5316,8 +5336,10 @@
 
   if (Snapshot::IncludesCode(kind_)) {
     instructions_writer_->Write(
-        *vm_isolate_snapshot_buffer_, vm_isolate_snapshot_size_,
-        *isolate_snapshot_buffer_, isolate_snapshot_size_);
+        vm_isolate_snapshot_buffer_ == NULL ? NULL
+                                            : *vm_isolate_snapshot_buffer_,
+        vm_isolate_snapshot_size_, *isolate_snapshot_buffer_,
+        isolate_snapshot_size_);
 
     if (FLAG_print_snapshot_sizes) {
       OS::Print("ReadOnlyData(CodeSize): %" Pd "\n",
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 568975c..2f9e6d7 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -224,23 +224,21 @@
         if (data_snapshot == NULL) {
           return strdup("Missing rodata snapshot");
         }
-        vm_isolate_->SetupInstructionsSnapshotPage(instructions_snapshot);
-        vm_isolate_->SetupDataSnapshotPage(data_snapshot);
       } else if (Snapshot::IsFull(snapshot_kind_)) {
 #if defined(DART_PRECOMPILED_RUNTIME)
         return strdup("Precompiled runtime requires a precompiled snapshot");
 #else
-        if (instructions_snapshot != NULL) {
-          return strdup("Unexpected instructions snapshot");
-        }
-        if (data_snapshot != NULL) {
-          return strdup("Unexpected rodata snapshot");
-        }
         StubCode::InitOnce();
 #endif
       } else {
         return strdup("Invalid vm isolate snapshot seen");
       }
+      if (instructions_snapshot != NULL) {
+        vm_isolate_->SetupInstructionsSnapshotPage(instructions_snapshot);
+      }
+      if (instructions_snapshot != NULL) {
+        vm_isolate_->SetupDataSnapshotPage(data_snapshot);
+      }
       VmIsolateSnapshotReader reader(snapshot->kind(), snapshot->content(),
                                      snapshot->length(), instructions_snapshot,
                                      data_snapshot, T);
@@ -533,7 +531,9 @@
       const String& message = String::Handle(String::New("Invalid snapshot"));
       return ApiError::New(message);
     }
-    if (snapshot->kind() != snapshot_kind_) {
+    if (snapshot->kind() != snapshot_kind_ &&
+        !((snapshot->kind() == Snapshot::kAppJIT) &&
+          (snapshot_kind_ == Snapshot::kCore))) {
       const String& message = String::Handle(
           String::NewFormatted("Invalid snapshot kind: got '%s', expected '%s'",
                                Snapshot::KindToCString(snapshot->kind()),
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 61daa77..a68cfbf 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -36,6 +36,7 @@
 #include "vm/port.h"
 #include "vm/precompiler.h"
 #include "vm/profiler.h"
+#include "vm/program_visitor.h"
 #include "vm/resolver.h"
 #include "vm/reusable_handles.h"
 #include "vm/service_event.h"
@@ -112,9 +113,9 @@
 // An object visitor which will iterate over all the function objects in the
 // heap and check if the result type and parameter types are canonicalized
 // or not. An assertion is raised if a type is not canonicalized.
-class FunctionVisitor : public ObjectVisitor {
+class CheckFunctionTypesVisitor : public ObjectVisitor {
  public:
-  explicit FunctionVisitor(Thread* thread)
+  explicit CheckFunctionTypesVisitor(Thread* thread)
       : classHandle_(Class::Handle(thread->zone())),
         funcHandle_(Function::Handle(thread->zone())),
         typeHandle_(AbstractType::Handle(thread->zone())) {}
@@ -1572,7 +1573,7 @@
 
 #if defined(DEBUG)
   I->heap()->CollectAllGarbage();
-  FunctionVisitor check_canonical(T);
+  CheckFunctionTypesVisitor check_canonical(T);
   I->heap()->IterateObjects(&check_canonical);
 #endif  // #if defined(DEBUG)
 
@@ -1586,9 +1587,9 @@
 }
 
 
-static Dart_Handle createLibrarySnapshot(Dart_Handle library,
-                                         uint8_t** buffer,
-                                         intptr_t* size) {
+DART_EXPORT Dart_Handle Dart_CreateScriptSnapshot(uint8_t** buffer,
+                                                  intptr_t* size) {
+  API_TIMELINE_DURATION;
   DARTSCOPE(Thread::Current());
   Isolate* I = T->isolate();
   if (buffer == NULL) {
@@ -1602,16 +1603,11 @@
   if (::Dart_IsError(state)) {
     return state;
   }
-  Library& lib = Library::Handle(Z);
-  if (library == Dart_Null()) {
-    lib ^= I->object_store()->root_library();
-  } else {
-    lib ^= Api::UnwrapHandle(library);
-  }
+  Library& lib = Library::Handle(Z, I->object_store()->root_library());
 
 #if defined(DEBUG)
   I->heap()->CollectAllGarbage();
-  FunctionVisitor check_canonical(T);
+  CheckFunctionTypesVisitor check_canonical(T);
   I->heap()->IterateObjects(&check_canonical);
 #endif  // #if defined(DEBUG)
 
@@ -1622,21 +1618,6 @@
 }
 
 
-DART_EXPORT Dart_Handle Dart_CreateScriptSnapshot(uint8_t** buffer,
-                                                  intptr_t* size) {
-  API_TIMELINE_DURATION;
-  return createLibrarySnapshot(Dart_Null(), buffer, size);
-}
-
-
-DART_EXPORT Dart_Handle Dart_CreateLibrarySnapshot(Dart_Handle library,
-                                                   uint8_t** buffer,
-                                                   intptr_t* size) {
-  API_TIMELINE_DURATION;
-  return createLibrarySnapshot(library, buffer, size);
-}
-
-
 DART_EXPORT void Dart_InterruptIsolate(Dart_Isolate isolate) {
   if (isolate == NULL) {
     FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);
@@ -6426,47 +6407,175 @@
 }
 
 
-// The precompiler is included in dart_bootstrap and dart_noopt, and
-// excluded from dart and dart_precompiled_runtime.
-#if !defined(DART_PRECOMPILER)
+DART_EXPORT
+Dart_Handle Dart_SaveJITFeedback(uint8_t** buffer, intptr_t* buffer_length) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  return Api::NewError("No JIT feedback to save on an AOT runtime.");
+#elif defined(PRODUCT)
+  // TOOD(rmacnak): We'd need to include the JSON printing code again.
+  return Api::NewError("Dart_SaveJITFeedback not supported in PRODUCT mode.");
+#else
+  Thread* thread = Thread::Current();
+  DARTSCOPE(thread);
+  Isolate* isolate = thread->isolate();
+  Zone* zone = thread->zone();
 
-DART_EXPORT Dart_Handle
-Dart_Precompile(Dart_QualifiedFunctionName entry_points[], bool reset_fields) {
-  return Api::NewError(
-      "This VM was built without support for AOT compilation.");
+  if (buffer == NULL) {
+    RETURN_NULL_ERROR(buffer);
+  }
+  if (buffer_length == NULL) {
+    RETURN_NULL_ERROR(buffer_length);
+  }
+
+  JSONStream js_stream;
+  {
+    JSONObject js_profile(&js_stream);
+    js_profile.AddProperty("vmVersion", Version::CommitString());
+    js_profile.AddProperty("asserts", FLAG_enable_asserts);
+    js_profile.AddProperty("typeChecks", FLAG_enable_type_checks);
+
+    {
+      JSONArray js_scripts(&js_profile, "scripts");
+
+      const GrowableObjectArray& libraries = GrowableObjectArray::Handle(
+          zone, isolate->object_store()->libraries());
+      Library& library = Library::Handle(zone);
+      Array& scripts = Array::Handle(zone);
+      Script& script = Script::Handle(zone);
+      String& uri = String::Handle(zone);
+      for (intptr_t i = 0; i < libraries.Length(); i++) {
+        library ^= libraries.At(i);
+        scripts = library.LoadedScripts();
+        for (intptr_t j = 0; j < scripts.Length(); j++) {
+          script ^= scripts.At(j);
+          JSONObject js_script(&js_scripts);
+          uri = script.url();
+          js_script.AddProperty("uri", uri.ToCString());
+          int64_t fp = script.SourceFingerprint();
+          js_script.AddProperty64("checksum", fp);
+        }
+      }
+    }
+
+    {
+      JSONArray js_classes(&js_profile, "classes");
+
+      ClassTable* classes = isolate->class_table();
+      Class& cls = Class::Handle(zone);
+      Library& library = Library::Handle(zone);
+      String& uri = String::Handle(zone);
+      String& name = String::Handle(zone);
+      for (intptr_t cid = kNumPredefinedCids; cid < classes->NumCids(); cid++) {
+        if (!classes->HasValidClassAt(cid)) continue;
+        cls ^= classes->At(cid);
+        library = cls.library();
+        JSONObject js_class(&js_classes);
+        js_class.AddProperty("cid", cid);
+        uri = library.url();
+        js_class.AddProperty("uri", uri.ToCString());
+        name = cls.Name();
+        name = String::RemovePrivateKey(name);
+        js_class.AddProperty("name", name.ToCString());
+      }
+    }
+
+    {
+      JSONArray js_functions(&js_profile, "functions");
+
+      class JITFeedbackFunctionVisitor : public FunctionVisitor {
+       public:
+        JITFeedbackFunctionVisitor(JSONArray* js_functions, Zone* zone)
+            : js_functions_(js_functions),
+              function_(Function::Handle(zone)),
+              owner_(Class::Handle(zone)),
+              name_(String::Handle(zone)),
+              ic_datas_(Array::Handle(zone)),
+              ic_data_(ICData::Handle(zone)),
+              entry_(Object::Handle(zone)) {}
+
+        void Visit(const Function& function) {
+          if (function.usage_counter() == 0) return;
+
+          JSONObject js_function(js_functions_);
+          name_ = function.name();
+          name_ = String::RemovePrivateKey(name_);
+          js_function.AddProperty("name", name_.ToCString());
+          owner_ ^= function.Owner();
+          js_function.AddProperty("class", owner_.id());
+          js_function.AddProperty("tokenPos", function.token_pos().value());
+          js_function.AddProperty("kind",
+                                  static_cast<intptr_t>(function.kind()));
+          intptr_t usage = function.usage_counter();
+          if (usage < 0) {
+            // Function was in the background compiler's queue.
+            usage = FLAG_optimization_counter_threshold;
+          }
+          js_function.AddProperty("usageCounter", usage);
+
+          ic_datas_ = function.ic_data_array();
+          JSONArray js_icdatas(&js_function, "ics");
+          if (ic_datas_.IsNull()) return;
+
+          for (intptr_t j = 0; j < ic_datas_.Length(); j++) {
+            entry_ = ic_datas_.At(j);
+            if (!entry_.IsICData()) continue;  // Skip edge counters.
+            ic_data_ ^= entry_.raw();
+
+            JSONObject js_icdata(&js_icdatas);
+            js_icdata.AddProperty("deoptId", ic_data_.deopt_id());
+            name_ = ic_data_.target_name();
+            name_ = String::RemovePrivateKey(name_);
+            js_icdata.AddProperty("selector", name_.ToCString());
+            js_icdata.AddProperty("isStaticCall", ic_data_.is_static_call());
+            intptr_t num_args_checked = ic_data_.NumArgsTested();
+            js_icdata.AddProperty("argsTested", num_args_checked);
+            JSONArray js_entries(&js_icdata, "entries");
+            for (intptr_t check = 0; check < ic_data_.NumberOfChecks();
+                 check++) {
+              GrowableArray<intptr_t> class_ids(num_args_checked);
+              ic_data_.GetClassIdsAt(check, &class_ids);
+              for (intptr_t k = 0; k < num_args_checked; k++) {
+                ASSERT(class_ids[k] != kIllegalCid);
+                js_entries.AddValue(class_ids[k]);
+              }
+              js_entries.AddValue(ic_data_.GetCountAt(check));
+            }
+          }
+        }
+
+       private:
+        JSONArray* js_functions_;
+        Function& function_;
+        Class& owner_;
+        String& name_;
+        Array& ic_datas_;
+        ICData& ic_data_;
+        Object& entry_;
+      };
+
+      JITFeedbackFunctionVisitor visitor(&js_functions, zone);
+      ProgramVisitor::VisitFunctions(&visitor);
+    }
+  }
+
+  js_stream.Steal(reinterpret_cast<char**>(buffer), buffer_length);
+  return Api::Success();
+#endif
 }
 
 
 DART_EXPORT Dart_Handle
-Dart_CreatePrecompiledSnapshotAssembly(uint8_t** assembly_buffer,
-                                       intptr_t* assembly_size) {
-  return Api::NewError(
-      "This VM was built without support for AOT compilation.");
-  return 0;
-}
-
-
-DART_EXPORT Dart_Handle
-Dart_CreatePrecompiledSnapshotBlob(uint8_t** vm_isolate_snapshot_buffer,
-                                   intptr_t* vm_isolate_snapshot_size,
-                                   uint8_t** isolate_snapshot_buffer,
-                                   intptr_t* isolate_snapshot_size,
-                                   uint8_t** instructions_blob_buffer,
-                                   intptr_t* instructions_blob_size,
-                                   uint8_t** rodata_blob_buffer,
-                                   intptr_t* rodata_blob_size) {
-  return Api::NewError(
-      "This VM was built without support for AOT compilation.");
-}
-
-#else  // DART_PRECOMPILER
-
-DART_EXPORT Dart_Handle
-Dart_Precompile(Dart_QualifiedFunctionName entry_points[], bool reset_fields) {
+Dart_Precompile(Dart_QualifiedFunctionName entry_points[],
+                bool reset_fields,
+                uint8_t* jit_feedback,
+                intptr_t jit_feedback_length) {
 #if defined(TARGET_ARCH_IA32)
-  return Api::NewError("Precompilation is not supported on IA32.");
+  return Api::NewError("AOT compilation is not supported on IA32.");
 #elif defined(TARGET_ARCH_DBC)
-  return Api::NewError("Precompilation is not supported on DBC.");
+  return Api::NewError("AOT compilation is not supported on DBC.");
+#elif !defined(DART_PRECOMPILER)
+  return Api::NewError(
+      "This VM was built without support for AOT compilation.");
 #else
   API_TIMELINE_BEGIN_END;
   DARTSCOPE(Thread::Current());
@@ -6478,8 +6587,8 @@
     return result;
   }
   CHECK_CALLBACK_STATE(T);
-  const Error& error =
-      Error::Handle(Precompiler::CompileAll(entry_points, reset_fields));
+  const Error& error = Error::Handle(Precompiler::CompileAll(
+      entry_points, reset_fields, jit_feedback, jit_feedback_length));
   if (!error.IsNull()) {
     return Api::NewHandle(T, error.raw());
   }
@@ -6492,9 +6601,12 @@
 Dart_CreatePrecompiledSnapshotAssembly(uint8_t** assembly_buffer,
                                        intptr_t* assembly_size) {
 #if defined(TARGET_ARCH_IA32)
-  return Api::NewError("Precompilation is not supported on IA32.");
+  return Api::NewError("AOT compilation is not supported on IA32.");
 #elif defined(TARGET_ARCH_DBC)
-  return Api::NewError("Precompilation is not supported on DBC.");
+  return Api::NewError("AOT compilation is not supported on DBC.");
+#elif !defined(DART_PRECOMPILER)
+  return Api::NewError(
+      "This VM was built without support for AOT compilation.");
 #else
   API_TIMELINE_DURATION;
   DARTSCOPE(Thread::Current());
@@ -6540,9 +6652,12 @@
                                    uint8_t** rodata_blob_buffer,
                                    intptr_t* rodata_blob_size) {
 #if defined(TARGET_ARCH_IA32)
-  return Api::NewError("Precompilation is not supported on IA32.");
+  return Api::NewError("AOT compilation is not supported on IA32.");
 #elif defined(TARGET_ARCH_DBC)
-  return Api::NewError("Precompilation is not supported on DBC.");
+  return Api::NewError("AOT compilation is not supported on DBC.");
+#elif !defined(DART_PRECOMPILER)
+  return Api::NewError(
+      "This VM was built without support for AOT compilation.");
 #else
   API_TIMELINE_DURATION;
   DARTSCOPE(Thread::Current());
@@ -6596,7 +6711,6 @@
   return Api::Success();
 #endif
 }
-#endif  // DART_PRECOMPILER
 
 
 DART_EXPORT Dart_Handle Dart_PrecompileJIT() {
@@ -6632,9 +6746,7 @@
 
 
 DART_EXPORT Dart_Handle
-Dart_CreateAppJITSnapshot(uint8_t** vm_isolate_snapshot_buffer,
-                          intptr_t* vm_isolate_snapshot_size,
-                          uint8_t** isolate_snapshot_buffer,
+Dart_CreateAppJITSnapshot(uint8_t** isolate_snapshot_buffer,
                           intptr_t* isolate_snapshot_size,
                           uint8_t** instructions_blob_buffer,
                           intptr_t* instructions_blob_size,
@@ -6652,12 +6764,6 @@
     return Api::NewError(
         "Creating full snapshots requires --load_deferred_eagerly");
   }
-  if (vm_isolate_snapshot_buffer == NULL) {
-    RETURN_NULL_ERROR(vm_isolate_snapshot_buffer);
-  }
-  if (vm_isolate_snapshot_size == NULL) {
-    RETURN_NULL_ERROR(vm_isolate_snapshot_size);
-  }
   if (isolate_snapshot_buffer == NULL) {
     RETURN_NULL_ERROR(isolate_snapshot_buffer);
   }
@@ -6688,11 +6794,9 @@
   BlobInstructionsWriter instructions_writer(instructions_blob_buffer,
                                              rodata_blob_buffer, ApiReallocate,
                                              2 * MB /* initial_size */);
-  FullSnapshotWriter writer(Snapshot::kAppJIT, vm_isolate_snapshot_buffer,
-                            isolate_snapshot_buffer, ApiReallocate,
-                            &instructions_writer);
+  FullSnapshotWriter writer(Snapshot::kAppJIT, NULL, isolate_snapshot_buffer,
+                            ApiReallocate, &instructions_writer);
   writer.WriteFullSnapshot();
-  *vm_isolate_snapshot_size = writer.VmIsolateSnapshotSize();
   *isolate_snapshot_size = writer.IsolateSnapshotSize();
   *instructions_blob_size = instructions_writer.InstructionsBlobSize();
   *rodata_blob_size = instructions_writer.RodataBlobSize();
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 31f08cd..345db49 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -1077,7 +1077,13 @@
     deopt_instr = new (zone()) DeoptMaterializedObjectRefInstr(index);
   } else {
     ASSERT(!source_loc.IsInvalid());
-    switch (value->definition()->representation()) {
+#if defined(TARGET_ARCH_DBC)
+    Representation rep =
+        (value == NULL) ? kTagged : value->definition()->representation();
+#else
+    Representation rep = value->definition()->representation();
+#endif
+    switch (rep) {
       case kTagged:
         deopt_instr =
             new (zone()) DeoptWordInstr(ToCpuRegisterSource(source_loc));
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 6d103b8..d0a2cb1 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -67,14 +67,6 @@
 DECLARE_FLAG(int, stacktrace_every);
 DECLARE_FLAG(charp, stacktrace_filter);
 DECLARE_FLAG(bool, trace_compiler);
-DECLARE_FLAG(int, inlining_hotness);
-DECLARE_FLAG(int, inlining_size_threshold);
-DECLARE_FLAG(int, inlining_callee_size_threshold);
-DECLARE_FLAG(int, inline_getters_setters_smaller_than);
-DECLARE_FLAG(int, inlining_depth_threshold);
-DECLARE_FLAG(int, inlining_caller_size_threshold);
-DECLARE_FLAG(int, inlining_constant_arguments_max_size_threshold);
-DECLARE_FLAG(int, inlining_constant_arguments_min_size_threshold);
 DECLARE_FLAG(int, reload_every);
 DECLARE_FLAG(bool, unbox_numeric_fields);
 
@@ -84,22 +76,6 @@
     FATAL("Precompilation not supported on IA32");
 #endif
 
-#if !defined(DART_PRECOMPILED_RUNTIME)
-    // Flags affecting compilation only:
-    // There is no counter feedback in precompilation, so ignore the counter
-    // when making inlining decisions.
-    FLAG_inlining_hotness = 0;
-    // Use smaller thresholds in precompilation as we are compiling everything
-    // with the optimizing compiler instead of only hot functions.
-    FLAG_inlining_size_threshold = 5;
-    FLAG_inline_getters_setters_smaller_than = 5;
-    FLAG_inlining_callee_size_threshold = 20;
-    FLAG_inlining_depth_threshold = 4;
-    FLAG_inlining_caller_size_threshold = 1000;
-    FLAG_inlining_constant_arguments_max_size_threshold = 100;
-    FLAG_inlining_constant_arguments_min_size_threshold = 30;
-#endif
-
     FLAG_background_compilation = false;
     FLAG_fields_may_be_reset = true;
     FLAG_interpret_irregexp = true;
@@ -815,7 +791,7 @@
 }
 
 
-void FlowGraphCompiler::AddDeoptIndexAtCall(intptr_t deopt_id) {
+CompilerDeoptInfo* FlowGraphCompiler::AddDeoptIndexAtCall(intptr_t deopt_id) {
   ASSERT(is_optimizing());
   ASSERT(!intrinsic_mode());
   CompilerDeoptInfo* info =
@@ -824,6 +800,7 @@
                                      pending_deoptimization_env_);
   info->set_pc_offset(assembler()->CodeSize());
   deopt_infos_.Add(info);
+  return info;
 }
 
 
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index e8b013f..8d8606b 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -122,6 +122,9 @@
         deopt_id_(deopt_id),
         reason_(reason),
         flags_(flags),
+#if defined(TARGET_ARCH_DBC)
+        lazy_deopt_with_result_(false),
+#endif
         deopt_env_(deopt_env) {
     ASSERT(deopt_env != NULL);
   }
@@ -143,6 +146,18 @@
   uint32_t flags() const { return flags_; }
   const Environment* deopt_env() const { return deopt_env_; }
 
+#if defined(TARGET_ARCH_DBC)
+  // On DBC calls return results on the stack but not all calls have a result.
+  // This needs to be taken into account when constructing lazy deoptimization
+  // environment.
+  // For calls with results we add a deopt instruction that would copy top
+  // of the stack from optimized frame to unoptimized frame effectively
+  // preserving the result of the call.
+  // For calls with no results we don't emit such instruction - because there
+  // is no result pushed by the return sequence.
+  void mark_lazy_deopt_with_result() { lazy_deopt_with_result_ = true; }
+#endif
+
  private:
   void EmitMaterializations(Environment* env, DeoptInfoBuilder* builder);
 
@@ -153,6 +168,9 @@
   const intptr_t deopt_id_;
   const ICData::DeoptReasonId reason_;
   const uint32_t flags_;
+#if defined(TARGET_ARCH_DBC)
+  bool lazy_deopt_with_result_;
+#endif
   Environment* deopt_env_;
 
   DISALLOW_COPY_AND_ASSIGN(CompilerDeoptInfo);
@@ -499,7 +517,7 @@
   uint16_t ToEmbeddableCid(intptr_t cid, Instruction* instruction);
 #endif  // defined(TARGET_ARCH_DBC)
 
-  void AddDeoptIndexAtCall(intptr_t deopt_id);
+  CompilerDeoptInfo* AddDeoptIndexAtCall(intptr_t deopt_id);
 
   void AddSlowPathCode(SlowPathCode* slow_path);
 
@@ -583,11 +601,16 @@
   bool EndCodeSourceRange(TokenPosition token_pos);
 
 #if defined(TARGET_ARCH_DBC)
+  enum CallResult {
+    kHasResult,
+    kNoResult,
+  };
   void RecordAfterCallHelper(TokenPosition token_pos,
                              intptr_t deopt_id,
                              intptr_t argument_count,
+                             CallResult result,
                              LocationSummary* locs);
-  void RecordAfterCall(Instruction* instr);
+  void RecordAfterCall(Instruction* instr, CallResult result);
 #endif
 
  private:
diff --git a/runtime/vm/flow_graph_compiler_dbc.cc b/runtime/vm/flow_graph_compiler_dbc.cc
index 745fcf9..eb3660a 100644
--- a/runtime/vm/flow_graph_compiler_dbc.cc
+++ b/runtime/vm/flow_graph_compiler_dbc.cc
@@ -118,6 +118,11 @@
   // will be able to find them during materialization.
   slot_ix = builder->EmitMaterializationArguments(slot_ix);
 
+  if (lazy_deopt_with_result_) {
+    ASSERT(reason() == ICData::kDeoptAtCall);
+    builder->AddCopy(NULL, Location::StackSlot(stack_height), slot_ix++);
+  }
+
   // For the innermost environment, set outgoing arguments and the locals.
   for (intptr_t i = current->Length() - 1;
        i >= current->fixed_parameter_count(); i--) {
@@ -179,6 +184,7 @@
 void FlowGraphCompiler::RecordAfterCallHelper(TokenPosition token_pos,
                                               intptr_t deopt_id,
                                               intptr_t argument_count,
+                                              CallResult result,
                                               LocationSummary* locs) {
   RecordSafepoint(locs);
   // Marks either the continuation point in unoptimized code or the
@@ -190,7 +196,10 @@
     // On all other architectures caller drops outgoing arguments itself
     // hence the difference.
     pending_deoptimization_env_->DropArguments(argument_count);
-    AddDeoptIndexAtCall(deopt_id_after);
+    CompilerDeoptInfo* info = AddDeoptIndexAtCall(deopt_id_after);
+    if (result == kHasResult) {
+      info->mark_lazy_deopt_with_result();
+    }
     // This descriptor is needed for exception handling in optimized code.
     AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id_after, token_pos);
   } else {
@@ -201,9 +210,9 @@
 }
 
 
-void FlowGraphCompiler::RecordAfterCall(Instruction* instr) {
+void FlowGraphCompiler::RecordAfterCall(Instruction* instr, CallResult result) {
   RecordAfterCallHelper(instr->token_pos(), instr->deopt_id(),
-                        instr->ArgumentCount(), instr->locs());
+                        instr->ArgumentCount(), result, instr->locs());
 }
 
 
@@ -263,7 +272,9 @@
     locs->SetStackBit(locs->out(0).reg());
   }
   AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id, token_pos);
-  RecordAfterCallHelper(token_pos, deopt_id, 0, locs);
+  const intptr_t kArgCount = 0;
+  RecordAfterCallHelper(token_pos, deopt_id, kArgCount,
+                        FlowGraphCompiler::kHasResult, locs);
   if (is_optimizing()) {
     // Assert assignable keeps the instance on the stack as the result,
     // all other arguments are popped.
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index 0621961..6cf0684 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -5,6 +5,7 @@
 #include "vm/flow_graph_inliner.h"
 
 #include "vm/aot_optimizer.h"
+#include "vm/precompiler.h"
 #include "vm/block_scheduler.h"
 #include "vm/branch_optimizer.h"
 #include "vm/compiler.h"
@@ -213,8 +214,11 @@
 // A collection of call sites to consider for inlining.
 class CallSites : public ValueObject {
  public:
-  explicit CallSites(FlowGraph* flow_graph)
-      : static_calls_(), closure_calls_(), instance_calls_() {}
+  explicit CallSites(FlowGraph* flow_graph, intptr_t threshold)
+      : inlining_depth_threshold_(threshold),
+        static_calls_(),
+        closure_calls_(),
+        instance_calls_() {}
 
   struct InstanceCallInfo {
     PolymorphicInstanceCallInstr* call;
@@ -357,7 +361,7 @@
                      intptr_t depth,
                      GrowableArray<InlinedInfo>* inlined_info) {
     ASSERT(graph != NULL);
-    if (depth > FLAG_inlining_depth_threshold) {
+    if (depth > inlining_depth_threshold_) {
       if (FLAG_print_inlining_tree) {
         RecordAllNotInlinedFunction(graph, depth, inlined_info);
       }
@@ -367,7 +371,7 @@
     // Recognized methods are not treated as normal calls. They don't have
     // calls in themselves, so we keep adding those even when at the threshold.
     const bool inline_only_recognized_methods =
-        (depth == FLAG_inlining_depth_threshold);
+        (depth == inlining_depth_threshold_);
 
     const intptr_t instance_call_start_ix = instance_calls_.length();
     const intptr_t static_call_start_ix = static_calls_.length();
@@ -423,6 +427,7 @@
   }
 
  private:
+  intptr_t inlining_depth_threshold_;
   GrowableArray<StaticCallInfo> static_calls_;
   GrowableArray<ClosureCallInfo> closure_calls_;
   GrowableArray<InstanceCallInfo> instance_calls_;
@@ -513,7 +518,7 @@
 
 class CallSiteInliner : public ValueObject {
  public:
-  explicit CallSiteInliner(FlowGraphInliner* inliner)
+  explicit CallSiteInliner(FlowGraphInliner* inliner, intptr_t threshold)
       : inliner_(inliner),
         caller_graph_(inliner->flow_graph()),
         inlined_(false),
@@ -522,6 +527,7 @@
         inlined_recursive_call_(false),
         inlining_depth_(1),
         inlining_recursion_depth_(0),
+        inlining_depth_threshold_(threshold),
         collected_call_sites_(NULL),
         inlining_call_sites_(NULL),
         function_cache_(),
@@ -570,14 +576,14 @@
 
   void InlineCalls() {
     // If inlining depth is less then one abort.
-    if (FLAG_inlining_depth_threshold < 1) return;
+    if (inlining_depth_threshold_ < 1) return;
     if (caller_graph_->function().deoptimization_counter() >=
         FLAG_deoptimization_counter_inlining_threshold) {
       return;
     }
     // Create two call site collections to swap between.
-    CallSites sites1(caller_graph_);
-    CallSites sites2(caller_graph_);
+    CallSites sites1(caller_graph_, inlining_depth_threshold_);
+    CallSites sites2(caller_graph_, inlining_depth_threshold_);
     CallSites* call_sites_temp = NULL;
     collected_call_sites_ = &sites1;
     inlining_call_sites_ = &sites2;
@@ -669,6 +675,15 @@
       return false;
     }
 
+    if ((inliner_->precompiler_ != NULL) &&
+        inliner_->precompiler_->HasFeedback() &&
+        (function.usage_counter() <= 0) && !inliner_->AlwaysInline(function)) {
+      TRACE_INLINING(THR_Print("     Bailout: not compiled yet\n"));
+      PRINT_INLINING_TREE("Not compiled", &call_data->caller, &function,
+                          call_data->call);
+      return false;
+    }
+
     // Type feedback may have been cleared for this function (ClearICDataArray),
     // but we need it for inlining.
     if (!FLAG_precompiled_mode && (function.ic_data_array() == Array::null())) {
@@ -791,6 +806,16 @@
             callee_graph = builder.BuildGraph();
           }
         }
+#ifdef DART_PRECOMPILER
+        if (FLAG_precompiled_mode) {
+          Precompiler::PopulateWithICData(parsed_function->function(),
+                                          callee_graph);
+          if (inliner_->precompiler_ != NULL) {
+            inliner_->precompiler_->TryApplyFeedback(
+                parsed_function->function(), callee_graph);
+          }
+        }
+#endif
 
         // The parameter stubs are a copy of the actual arguments providing
         // concrete information about the values, for example constant values,
@@ -857,7 +882,6 @@
             AotOptimizer optimizer(inliner_->precompiler_, callee_graph,
                                    inliner_->use_speculative_inlining_,
                                    inliner_->inlining_black_list_);
-            optimizer.PopulateWithICData();
 
             optimizer.ApplyClassIds();
             DEBUG_ASSERT(callee_graph->VerifyUseLists());
@@ -1375,6 +1399,7 @@
   bool inlined_recursive_call_;
   intptr_t inlining_depth_;
   intptr_t inlining_recursion_depth_;
+  intptr_t inlining_depth_threshold_;
   CallSites* collected_call_sites_;
   CallSites* inlining_call_sites_;
   GrowableArray<ParsedFunction*> function_cache_;
@@ -1929,6 +1954,11 @@
     return true;
   }
 
+  if (function.is_const()) {
+    // Inlined const fields are smaller than a call.
+    return true;
+  }
+
   if (function.IsGetterFunction() || function.IsSetterFunction() ||
       IsInlineableOperator(function) ||
       (function.kind() == RawFunction::kConstructor)) {
@@ -1962,7 +1992,13 @@
     printer.PrintBlocks();
   }
 
-  CallSiteInliner inliner(this);
+  intptr_t inlining_depth_threshold = FLAG_inlining_depth_threshold;
+  if ((precompiler_ != NULL) && precompiler_->HasFeedback() &&
+      (top.usage_counter() <= 0)) {
+    inlining_depth_threshold = 1;
+  }
+
+  CallSiteInliner inliner(this, inlining_depth_threshold);
   inliner.InlineCalls();
   if (FLAG_print_inlining_tree) {
     inliner.PrintInlinedInfo(top);
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 373aa48..78675d9 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -3125,7 +3125,7 @@
   }
   compiler->AddCurrentDescriptor(RawPcDescriptors::kIcCall, deopt_id(),
                                  token_pos());
-  compiler->RecordAfterCall(this);
+  compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
 
   if (compiler->is_optimizing()) {
     __ PopLocal(locs()->out(0).reg());
@@ -3273,7 +3273,7 @@
     __ StaticCall(ArgumentCount(), argdesc_kidx);
     compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
                                    token_pos());
-    compiler->RecordAfterCall(this);
+    compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
     __ PopLocal(locs()->out(0).reg());
   } else {
     const intptr_t ic_data_kidx = __ AddConstant(*call_ic_data);
@@ -3281,7 +3281,7 @@
     __ IndirectStaticCall(ArgumentCount(), argdesc_kidx);
     compiler->AddCurrentDescriptor(RawPcDescriptors::kUnoptStaticCall,
                                    deopt_id(), token_pos());
-    compiler->RecordAfterCall(this);
+    compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
   }
 #endif  // !defined(TARGET_ARCH_DBC)
 }
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 0aa3af3..8b843c9 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -3221,6 +3221,8 @@
   const ICData* ic_data() const { return ic_data_; }
   bool HasICData() const { return (ic_data() != NULL) && !ic_data()->IsNull(); }
 
+  void set_ic_data(const ICData* value) { ic_data_ = value; }
+
   DECLARE_INSTRUCTION(StaticCall)
   virtual CompileType ComputeType() const;
   virtual Definition* Canonicalize(FlowGraph* flow_graph);
diff --git a/runtime/vm/intermediate_language_dbc.cc b/runtime/vm/intermediate_language_dbc.cc
index efe48b1..e15e4fa 100644
--- a/runtime/vm/intermediate_language_dbc.cc
+++ b/runtime/vm/intermediate_language_dbc.cc
@@ -204,7 +204,7 @@
   __ InstanceOf(negate_result() ? 1 : 0);
   compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
                                  token_pos());
-  compiler->RecordAfterCall(this);
+  compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
   if (compiler->is_optimizing()) {
     __ PopLocal(locs()->out(0).reg());
   }
@@ -227,7 +227,7 @@
   __ AssertBoolean(Isolate::Current()->type_checks() ? 1 : 0);
   compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
                                  token_pos());
-  compiler->RecordAfterCall(this);
+  compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
   if (compiler->is_optimizing()) {
     __ Drop1();
   }
@@ -280,7 +280,7 @@
   __ StaticCall(instance_call()->ArgumentCount(), argdesc_kidx);
   compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
                                  instance_call()->token_pos());
-  compiler->RecordAfterCall(this);
+  compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
   __ PopLocal(locs()->out(0).reg());
 }
 
@@ -301,7 +301,7 @@
   }
   compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
                                  token_pos());
-  compiler->RecordAfterCall(this);
+  compiler->RecordAfterCall(this, FlowGraphCompiler::kNoResult);
 }
 
 
@@ -431,7 +431,7 @@
   } else {
     __ InitStaticTOS();
   }
-  compiler->RecordAfterCall(this);
+  compiler->RecordAfterCall(this, FlowGraphCompiler::kNoResult);
 }
 
 
@@ -449,7 +449,7 @@
   const intptr_t argdesc_kidx =
       compiler->assembler()->AddConstant(arguments_descriptor);
   __ StaticCall(argument_count, argdesc_kidx);
-  compiler->RecordAfterCall(this);
+  compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
   if (compiler->is_optimizing()) {
     __ PopLocal(locs()->out(0).reg());
   }
@@ -699,11 +699,11 @@
     __ Push(type_arguments);
     __ Push(length);
     __ CreateArrayTOS();
-    compiler->RecordAfterCall(this);
+    compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
     __ PopLocal(out);
   } else {
     __ CreateArrayTOS();
-    compiler->RecordAfterCall(this);
+    compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
   }
 }
 
@@ -917,7 +917,12 @@
   __ PushConstant(CallFunction());
   const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor);
   __ StaticCall(kArgumentCount, argdesc_kidx);
-  compiler->RecordAfterCall(this);
+  // Note: can't use RecordAfterCall here because
+  // StringInterpolateInstr::ArgumentCount() is 0. However
+  // internally it does a call with 1 argument which needs to
+  // be reflected in the lazy deoptimization environment.
+  compiler->RecordAfterCallHelper(token_pos(), deopt_id(), kArgumentCount,
+                                  FlowGraphCompiler::kHasResult, locs());
   if (compiler->is_optimizing()) {
     __ PopLocal(locs()->out(0).reg());
   }
@@ -1145,7 +1150,15 @@
   compiler->AddExceptionHandler(catch_try_index(), try_index(),
                                 compiler->assembler()->CodeSize(),
                                 catch_handler_types_, needs_stacktrace());
-
+  // On lazy deoptimization we patch the optimized code here to enter the
+  // deoptimization stub.
+  const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId());
+  if (compiler->is_optimizing()) {
+    compiler->AddDeoptIndexAtCall(deopt_id);
+  } else {
+    compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id,
+                                   TokenPosition::kNoSource);
+  }
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
   }
@@ -1176,7 +1189,7 @@
   __ Throw(0);
   compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
                                  token_pos());
-  compiler->RecordAfterCall(this);
+  compiler->RecordAfterCall(this, FlowGraphCompiler::kNoResult);
   __ Trap();
 }
 
@@ -1186,7 +1199,7 @@
   __ Throw(1);
   compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
                                  token_pos());
-  compiler->RecordAfterCall(this);
+  compiler->RecordAfterCall(this, FlowGraphCompiler::kNoResult);
   __ Trap();
 }
 
diff --git a/runtime/vm/json_parser.h b/runtime/vm/json_parser.h
new file mode 100644
index 0000000..83b9d6b
--- /dev/null
+++ b/runtime/vm/json_parser.h
@@ -0,0 +1,331 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_VM_JSON_PARSER_H_
+#define RUNTIME_VM_JSON_PARSER_H_
+
+#include "vm/allocation.h"
+#include "vm/zone.h"
+#include "vm/growable_array.h"
+
+namespace dart {
+
+class ParsedJSONArray;
+
+class ParsedJSONValue : public ZoneAllocated {
+ public:
+  virtual ~ParsedJSONValue() {}
+
+  virtual bool IsObject() const { return false; }
+  virtual bool IsArray() const { return false; }
+  virtual bool IsString() const { return false; }
+  virtual bool IsNumber() const { return false; }
+  virtual bool IsBoolean() const { return false; }
+  virtual bool IsError() const { return false; }
+};
+
+class ParsedJSONString : public ParsedJSONValue {
+ public:
+  explicit ParsedJSONString(const char* value) : value_(value) {}
+  bool Equals(const char* other) { return strcmp(value_, other) == 0; }
+  const char* value() { return value_; }
+  virtual bool IsString() const { return true; }
+
+ private:
+  const char* value_;
+};
+
+class ParsedJSONNumber : public ParsedJSONValue {
+ public:
+  explicit ParsedJSONNumber(int64_t value) : value_(value) {}
+
+  int64_t value() { return value_; }
+  virtual bool IsNumber() const { return true; }
+
+ private:
+  int64_t value_;
+};
+
+class ParsedJSONBoolean : public ParsedJSONValue {
+ public:
+  explicit ParsedJSONBoolean(bool value) : value_(value) {}
+
+  bool value() { return value_; }
+  virtual bool IsBoolean() const { return true; }
+
+ private:
+  bool value_;
+};
+
+class ParsedJSONNull : public ParsedJSONValue {
+ public:
+  virtual bool IsNull() const { return true; }
+};
+
+class ParsedJSONObject : public ParsedJSONValue {
+ public:
+  ParsedJSONObject(intptr_t length, ParsedJSONValue** keys_and_values)
+      : length_(length), keys_and_values_(keys_and_values) {}
+
+  ParsedJSONValue* At(const char* key) const {
+    for (intptr_t i = 0; i < length_; i += 2) {
+      ASSERT(keys_and_values_[i]->IsString());
+      ParsedJSONString* jskey =
+          static_cast<ParsedJSONString*>(keys_and_values_[i]);
+      if (jskey->Equals(key)) {
+        return keys_and_values_[i + 1];
+      }
+    }
+    return NULL;
+  }
+
+  virtual bool IsObject() const { return true; }
+
+  ParsedJSONNumber* NumberAt(const char* key) {
+    ParsedJSONValue* member = At(key);
+    if ((member == NULL) || !member->IsNumber()) {
+      return NULL;
+    }
+    return static_cast<ParsedJSONNumber*>(member);
+  }
+
+  ParsedJSONString* StringAt(const char* key) {
+    ParsedJSONValue* member = At(key);
+    if ((member == NULL) || !member->IsString()) {
+      return NULL;
+    }
+    return static_cast<ParsedJSONString*>(member);
+  }
+
+  ParsedJSONBoolean* BooleanAt(const char* key) {
+    ParsedJSONValue* member = At(key);
+    if ((member == NULL) || !member->IsBoolean()) {
+      return NULL;
+    }
+    return static_cast<ParsedJSONBoolean*>(member);
+  }
+
+  inline ParsedJSONArray* ArrayAt(const char* key);
+
+ private:
+  intptr_t length_;
+  ParsedJSONValue** keys_and_values_;
+};
+
+class ParsedJSONArray : public ParsedJSONValue {
+ public:
+  ParsedJSONArray(intptr_t length, ParsedJSONValue** elements)
+      : length_(length), elements_(elements) {}
+
+  ParsedJSONValue* At(intptr_t index) const {
+    ASSERT(index < length_);
+    return elements_[index];
+  }
+
+  intptr_t Length() const { return length_; }
+
+  virtual bool IsArray() const { return true; }
+
+  ParsedJSONObject* ObjectAt(intptr_t index) {
+    ParsedJSONValue* element = At(index);
+    if ((element == NULL) || !element->IsObject()) {
+      return NULL;
+    }
+    return static_cast<ParsedJSONObject*>(element);
+  }
+
+  ParsedJSONNumber* NumberAt(intptr_t index) {
+    ParsedJSONValue* element = At(index);
+    if ((element == NULL) || !element->IsNumber()) {
+      return NULL;
+    }
+    return static_cast<ParsedJSONNumber*>(element);
+  }
+
+ private:
+  intptr_t length_;
+  ParsedJSONValue** elements_;
+};
+
+class ParsedJSONError : public ParsedJSONValue {
+ public:
+  explicit ParsedJSONError(const char* message, intptr_t position)
+      : message_(message), position_(position) {}
+
+  virtual bool IsError() const { return true; }
+
+  const char* message() const { return message_; }
+  intptr_t position() const { return position_; }
+
+ private:
+  const char* message_;
+  intptr_t position_;
+};
+
+class JSONParser {
+ public:
+  JSONParser(const char* buffer, intptr_t length, Zone* zone)
+      : buffer_(buffer), position_(0), length_(length), zone_(zone) {}
+
+  ParsedJSONValue* ParseValue() {
+    ConsumeWhitespace();
+    if (Peek() == '\"') return ParseString();
+    if (IsDigitOrMinus(Peek())) return ParseNumber();
+    if (Peek() == '{') return ParseObject();
+    if (Peek() == '[') return ParseArray();
+    if (PeekAndConsume("true")) return new (zone_) ParsedJSONBoolean(true);
+    if (PeekAndConsume("false")) return new (zone_) ParsedJSONBoolean(false);
+    if (PeekAndConsume("null")) return new (zone_) ParsedJSONNull();
+    return Error("value expected");
+  }
+
+ private:
+  intptr_t Available() const { return length_ - position_; }
+  char Peek() const {
+    if (position_ < length_) return buffer_[position_];
+    return 0;
+  }
+  char Consume() {
+    ASSERT(position_ < length_);
+    return buffer_[position_++];
+  }
+  bool PeekAndConsume(const char* expected) {
+    intptr_t n = strlen(expected);
+    if (Available() < n) return false;
+    if (strncmp(&buffer_[position_], expected, n) != 0) return false;
+    position_ += n;
+    return true;
+  }
+  void ConsumeWhitespace() {
+    while ((Available() > 0) && (buffer_[position_] < ' '))
+      position_++;
+  }
+  bool IsDigit(char c) { return c >= '0' && c <= '9'; }
+  bool IsDigitOrMinus(char c) { return (c == '-') || (c >= '0' && c <= '9'); }
+
+  ParsedJSONValue* ParseString() {
+    ConsumeWhitespace();
+    if (Peek() != '\"') return Error("string expected");
+    Consume();
+    intptr_t start = position_;
+    for (;;) {
+      if (Available() == 0) return Error("unterminated string");
+      if (Consume() == '\"') break;
+    }
+    intptr_t end = position_ - 1;
+
+    char* cstr = zone_->Alloc<char>(end - start + 1);
+    intptr_t dst_pos = 0;
+    for (intptr_t src_pos = start; src_pos < end; src_pos++) {
+      if (buffer_[src_pos] == '\\') {
+        src_pos++;
+      }
+      cstr[dst_pos++] = buffer_[src_pos];
+    }
+    cstr[dst_pos] = '\0';
+
+    return new (zone_) ParsedJSONString(cstr);
+  }
+
+  ParsedJSONValue* ParseNumber() {
+    ConsumeWhitespace();
+    bool negate = false;
+    if (Peek() == '-') {
+      Consume();
+      negate = true;
+    }
+    if (!IsDigit(Peek())) return Error("number expected");
+    int64_t value = 0;
+    for (;;) {
+      if (!IsDigit(Peek())) break;
+      char c = Consume();
+      value *= 10;
+      value += (c - '0');
+    }
+    if (negate) {
+      value = -value;
+    }
+    return new (zone_) ParsedJSONNumber(value);
+  }
+
+  ParsedJSONValue* ParseObject() {
+    ConsumeWhitespace();
+    if (Peek() != '{') return Error("object expected");
+    Consume();
+    ConsumeWhitespace();
+    if (Peek() == '}') return new (zone_) ParsedJSONObject(0, NULL);
+    ZoneGrowableArray<ParsedJSONValue*>* keys_and_values =
+        new (zone_) ZoneGrowableArray<ParsedJSONValue*>(zone_, 6);
+    for (;;) {
+      ParsedJSONValue* key = ParseString();
+      if (key->IsError()) return key;
+      ConsumeWhitespace();
+      if (Consume() != ':') return Error(": expected");
+      ConsumeWhitespace();
+      ParsedJSONValue* value = ParseValue();
+      if (value->IsError()) return value;
+      ConsumeWhitespace();
+
+      keys_and_values->Add(key);
+      keys_and_values->Add(value);
+
+      char c = Consume();
+      if (c == '}') break;
+      if (c != ',') return Error(", expected (object)");
+      ConsumeWhitespace();
+    }
+
+    return new (zone_)
+        ParsedJSONObject(keys_and_values->length(), keys_and_values->data());
+  }
+
+  ParsedJSONValue* ParseArray() {
+    ConsumeWhitespace();
+    if (Peek() != '[') return Error("array expected");
+    Consume();
+    ConsumeWhitespace();
+    if (Peek() == ']') {
+      Consume();
+      return new (zone_) ParsedJSONArray(0, NULL);
+    }
+    ZoneGrowableArray<ParsedJSONValue*>* elements =
+        new (zone_) ZoneGrowableArray<ParsedJSONValue*>(zone_, 6);
+    for (;;) {
+      ParsedJSONValue* element = ParseValue();
+      if (element->IsError()) return element;
+      ConsumeWhitespace();
+
+      elements->Add(element);
+
+      char c = Consume();
+      if (c == ']') break;
+      if (c != ',') return Error(", expected (array)");
+      ConsumeWhitespace();
+    }
+
+    return new (zone_) ParsedJSONArray(elements->length(), elements->data());
+  }
+
+ private:
+  ParsedJSONError* Error(const char* message) {
+    return new (zone_) ParsedJSONError(message, position_);
+  }
+
+  const char* const buffer_;
+  intptr_t position_;
+  intptr_t length_;
+  Zone* zone_;
+};
+
+ParsedJSONArray* ParsedJSONObject::ArrayAt(const char* key) {
+  ParsedJSONValue* member = At(key);
+  if ((member == NULL) || !member->IsArray()) {
+    return NULL;
+  }
+  return static_cast<ParsedJSONArray*>(member);
+}
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_JSON_PARSER_H_
diff --git a/runtime/vm/method_recognizer.h b/runtime/vm/method_recognizer.h
index 5ab5eac..043dd70 100644
--- a/runtime/vm/method_recognizer.h
+++ b/runtime/vm/method_recognizer.h
@@ -17,39 +17,39 @@
   V(::, identical, ObjectIdentical, Bool, 0x49c6e96a)                          \
   V(ClassID, getID, ClassIDgetID, Smi, 0x528fd455)                             \
   V(Object, Object., ObjectConstructor, Dynamic, 0x681617fe)                   \
-  V(_List, ., ObjectArrayAllocate, Array, 0x63078b15)                          \
-  V(_TypedList, _getInt8, ByteArrayBaseGetInt8, Smi, 0x59e7291d)               \
-  V(_TypedList, _getUint8, ByteArrayBaseGetUint8, Smi, 0x38d3e5bf)             \
-  V(_TypedList, _getInt16, ByteArrayBaseGetInt16, Smi, 0x19dde22c)             \
-  V(_TypedList, _getUint16, ByteArrayBaseGetUint16, Smi, 0x4f3dbe58)           \
-  V(_TypedList, _getInt32, ByteArrayBaseGetInt32, Dynamic, 0x082db131)         \
-  V(_TypedList, _getUint32, ByteArrayBaseGetUint32, Dynamic, 0x1dcbfb98)       \
-  V(_TypedList, _getInt64, ByteArrayBaseGetInt64, Dynamic, 0x61b71474)         \
-  V(_TypedList, _getFloat32, ByteArrayBaseGetFloat32, Double, 0x63b56e15)      \
-  V(_TypedList, _getFloat64, ByteArrayBaseGetFloat64, Double, 0x399dacf8)      \
+  V(_List, ., ObjectArrayAllocate, Array, 0x375519ad)                          \
+  V(_TypedList, _getInt8, ByteArrayBaseGetInt8, Smi, 0x7041895a)               \
+  V(_TypedList, _getUint8, ByteArrayBaseGetUint8, Smi, 0x336fa3ea)             \
+  V(_TypedList, _getInt16, ByteArrayBaseGetInt16, Smi, 0x231bbe2e)             \
+  V(_TypedList, _getUint16, ByteArrayBaseGetUint16, Smi, 0x0371785f)           \
+  V(_TypedList, _getInt32, ByteArrayBaseGetInt32, Dynamic, 0x65ab3a20)         \
+  V(_TypedList, _getUint32, ByteArrayBaseGetUint32, Dynamic, 0x0cb0fcf6)       \
+  V(_TypedList, _getInt64, ByteArrayBaseGetInt64, Dynamic, 0x7db75d78)         \
+  V(_TypedList, _getFloat32, ByteArrayBaseGetFloat32, Double, 0x6674ea6f)      \
+  V(_TypedList, _getFloat64, ByteArrayBaseGetFloat64, Double, 0x236c6e7a)      \
   V(_TypedList, _getFloat32x4, ByteArrayBaseGetFloat32x4, Float32x4,           \
-    0x4761a5be)                                                                \
-  V(_TypedList, _getInt32x4, ByteArrayBaseGetInt32x4, Int32x4, 0x3053e92c)     \
-  V(_TypedList, _setInt8, ByteArrayBaseSetInt8, Dynamic, 0x4e82d1e9)           \
-  V(_TypedList, _setUint8, ByteArrayBaseSetUint8, Dynamic, 0x4f3587fc)         \
-  V(_TypedList, _setInt16, ByteArrayBaseSetInt16, Dynamic, 0x6cef30ee)         \
-  V(_TypedList, _setUint16, ByteArrayBaseSetUint16, Dynamic, 0x64f938ac)       \
-  V(_TypedList, _setInt32, ByteArrayBaseSetInt32, Dynamic, 0x3693c029)         \
-  V(_TypedList, _setUint32, ByteArrayBaseSetUint32, Dynamic, 0x74bbf260)       \
-  V(_TypedList, _setInt64, ByteArrayBaseSetInt64, Dynamic, 0x75764edb)         \
-  V(_TypedList, _setFloat32, ByteArrayBaseSetFloat32, Dynamic, 0x6e72f2a4)     \
-  V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, Dynamic, 0x4765edda)     \
-  V(_TypedList, _setFloat32x4, ByteArrayBaseSetFloat32x4, Dynamic, 0x7cca4533) \
-  V(_TypedList, _setInt32x4, ByteArrayBaseSetInt32x4, Dynamic, 0x7631bdbc)     \
-  V(_StringBase, _interpolate, StringBaseInterpolate, Dynamic, 0x6f98eb49)     \
-  V(_IntegerImplementation, toDouble, IntegerToDouble, Double, 0x2f409861)     \
-  V(_Double, _add, DoubleAdd, Double, 0x0021c560)                              \
-  V(_Double, _sub, DoubleSub, Double, 0x419b3c66)                              \
-  V(_Double, _mul, DoubleMul, Double, 0x1a08cbe1)                              \
-  V(_Double, _div, DoubleDiv, Double, 0x38d2770f)                              \
+    0x5c367ffb)                                                                \
+  V(_TypedList, _getInt32x4, ByteArrayBaseGetInt32x4, Int32x4, 0x772d1c0f)     \
+  V(_TypedList, _setInt8, ByteArrayBaseSetInt8, Dynamic, 0x68f17de8)           \
+  V(_TypedList, _setUint8, ByteArrayBaseSetUint8, Dynamic, 0x6bb8b747)         \
+  V(_TypedList, _setInt16, ByteArrayBaseSetInt16, Dynamic, 0x75b8d278)         \
+  V(_TypedList, _setUint16, ByteArrayBaseSetUint16, Dynamic, 0x6e54f794)       \
+  V(_TypedList, _setInt32, ByteArrayBaseSetInt32, Dynamic, 0x54123a05)         \
+  V(_TypedList, _setUint32, ByteArrayBaseSetUint32, Dynamic, 0x4a3fea0b)       \
+  V(_TypedList, _setInt64, ByteArrayBaseSetInt64, Dynamic, 0x1d77d3ec)         \
+  V(_TypedList, _setFloat32, ByteArrayBaseSetFloat32, Dynamic, 0x5a11a2f9)     \
+  V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, Dynamic, 0x0edea58b)     \
+  V(_TypedList, _setFloat32x4, ByteArrayBaseSetFloat32x4, Dynamic, 0x163bc6cc) \
+  V(_TypedList, _setInt32x4, ByteArrayBaseSetInt32x4, Dynamic, 0x5def39d2)     \
+  V(_StringBase, _interpolate, StringBaseInterpolate, Dynamic, 0x084d9f1a)     \
+  V(_IntegerImplementation, toDouble, IntegerToDouble, Double, 0x0d8f57ab)     \
+  V(_Double, _add, DoubleAdd, Double, 0x2a38277b)                              \
+  V(_Double, _sub, DoubleSub, Double, 0x4f466391)                              \
+  V(_Double, _mul, DoubleMul, Double, 0x175e4f66)                              \
+  V(_Double, _div, DoubleDiv, Double, 0x0854181b)                              \
   V(::, min, MathMin, Dynamic, 0x4276561c)                                     \
   V(::, max, MathMax, Dynamic, 0x54121d6a)                                     \
-  V(::, _doublePow, MathDoublePow, Double, 0x698eb78d)                         \
+  V(::, _doublePow, MathDoublePow, Double, 0x01d7b09e)                         \
   V(Float32x4, Float32x4., Float32x4Constructor, Float32x4, 0x05968999)        \
   V(Float32x4, Float32x4.zero, Float32x4Zero, Float32x4, 0x472a4c46)           \
   V(Float32x4, Float32x4.splat, Float32x4Splat, Float32x4, 0x00bba1a5)         \
@@ -60,22 +60,22 @@
   V(Float32x4, shuffle, Float32x4Shuffle, Float32x4, 0x7829101f)               \
   V(Float32x4, shuffleMix, Float32x4ShuffleMix, Float32x4, 0x4182c06b)         \
   V(Float32x4, get:signMask, Float32x4GetSignMask, Dynamic, 0x1d07ca93)        \
-  V(Float32x4, _cmpequal, Float32x4Equal, Int32x4, 0x079804cb)                 \
-  V(Float32x4, _cmpgt, Float32x4GreaterThan, Int32x4, 0x7e441585)              \
-  V(Float32x4, _cmpgte, Float32x4GreaterThanOrEqual, Int32x4, 0x213f782d)      \
-  V(Float32x4, _cmplt, Float32x4LessThan, Int32x4, 0x3f481f31)                 \
-  V(Float32x4, _cmplte, Float32x4LessThanOrEqual, Int32x4, 0x061db061)         \
-  V(Float32x4, _cmpnequal, Float32x4NotEqual, Int32x4, 0x6fada13e)             \
-  V(Float32x4, _min, Float32x4Min, Float32x4, 0x4505ee78)                      \
-  V(Float32x4, _max, Float32x4Max, Float32x4, 0x071681c6)                      \
-  V(Float32x4, _scale, Float32x4Scale, Float32x4, 0x18c7f49d)                  \
-  V(Float32x4, _sqrt, Float32x4Sqrt, Float32x4, 0x734e6ad0)                    \
+  V(Float32x4, _cmpequal, Float32x4Equal, Int32x4, 0x16ad0fea)                 \
+  V(Float32x4, _cmpgt, Float32x4GreaterThan, Int32x4, 0x0641f613)              \
+  V(Float32x4, _cmpgte, Float32x4GreaterThanOrEqual, Int32x4, 0x464b8ffc)      \
+  V(Float32x4, _cmplt, Float32x4LessThan, Int32x4, 0x3eecd0de)                 \
+  V(Float32x4, _cmplte, Float32x4LessThanOrEqual, Int32x4, 0x06384754)         \
+  V(Float32x4, _cmpnequal, Float32x4NotEqual, Int32x4, 0x2f25ef10)             \
+  V(Float32x4, _min, Float32x4Min, Float32x4, 0x1ee6c750)                      \
+  V(Float32x4, _max, Float32x4Max, Float32x4, 0x4db6bbb4)                      \
+  V(Float32x4, _scale, Float32x4Scale, Float32x4, 0x52052a66)                  \
+  V(Float32x4, _sqrt, Float32x4Sqrt, Float32x4, 0x479f6b4a)                    \
   V(Float32x4, _reciprocalSqrt, Float32x4ReciprocalSqrt, Float32x4,            \
-    0x5e8a97f6)                                                                \
-  V(Float32x4, _reciprocal, Float32x4Reciprocal, Float32x4, 0x626f6106)        \
-  V(Float32x4, _negate, Float32x4Negate, Float32x4, 0x7fb3a154)                \
-  V(Float32x4, _abs, Float32x4Absolute, Float32x4, 0x1420f447)                 \
-  V(Float32x4, _clamp, Float32x4Clamp, Float32x4, 0x4200222d)                  \
+    0x6d35bfcf)                                                                \
+  V(Float32x4, _reciprocal, Float32x4Reciprocal, Float32x4, 0x21a56839)        \
+  V(Float32x4, _negate, Float32x4Negate, Float32x4, 0x6cfd5db7)                \
+  V(Float32x4, _abs, Float32x4Absolute, Float32x4, 0x249b8078)                 \
+  V(Float32x4, _clamp, Float32x4Clamp, Float32x4, 0x28b06c7a)                  \
   V(Float32x4, withX, Float32x4WithX, Float32x4, 0x4e336aff)                   \
   V(Float32x4, withY, Float32x4WithY, Float32x4, 0x0a72b910)                   \
   V(Float32x4, withZ, Float32x4WithZ, Float32x4, 0x31e93658)                   \
@@ -87,7 +87,7 @@
     0x2f43d3a6)                                                                \
   V(Float64x2, get:x, Float64x2GetX, Double, 0x58bfb39a)                       \
   V(Float64x2, get:y, Float64x2GetY, Double, 0x3cf4fcfa)                       \
-  V(Float64x2, _negate, Float64x2Negate, Float64x2, 0x64ef7b77)                \
+  V(Float64x2, _negate, Float64x2Negate, Float64x2, 0x523937da)                \
   V(Float64x2, abs, Float64x2Abs, Float64x2, 0x031f9e47)                       \
   V(Float64x2, sqrt, Float64x2Sqrt, Float64x2, 0x77f711dd)                     \
   V(Float64x2, get:signMask, Float64x2GetSignMask, Dynamic, 0x27ddf18d)        \
@@ -107,30 +107,30 @@
   V(Int32x4, get:signMask, Int32x4GetSignMask, Dynamic, 0x2c1ec9e5)            \
   V(Int32x4, shuffle, Int32x4Shuffle, Int32x4, 0x20bc0b16)                     \
   V(Int32x4, shuffleMix, Int32x4ShuffleMix, Int32x4, 0x5c7056e1)               \
-  V(Int32x4, select, Int32x4Select, Float32x4, 0x518ee337)                     \
+  V(Int32x4, select, Int32x4Select, Float32x4, 0x5c254e86)                     \
   V(Int32x4, withFlagX, Int32x4WithFlagX, Int32x4, 0x0ef58fcf)                 \
   V(Int32x4, withFlagY, Int32x4WithFlagY, Int32x4, 0x6485a9c4)                 \
   V(Int32x4, withFlagZ, Int32x4WithFlagZ, Int32x4, 0x267acdfa)                 \
   V(Int32x4, withFlagW, Int32x4WithFlagW, Int32x4, 0x345ac675)                 \
-  V(Int64List, [], Int64ArrayGetIndexed, Dynamic, 0x0c0c939a)                  \
-  V(Int64List, []=, Int64ArraySetIndexed, Dynamic, 0x3714d004)                 \
-  V(_Bigint, get:_neg, Bigint_getNeg, Bool, 0x7bf17a57)                        \
-  V(_Bigint, get:_used, Bigint_getUsed, Smi, 0x55041013)                       \
-  V(_Bigint, get:_digits, Bigint_getDigits, TypedDataUint32Array, 0x46a6c1b3)  \
-  V(_HashVMBase, get:_index, LinkedHashMap_getIndex, Dynamic, 0x7d6bb76b)      \
-  V(_HashVMBase, set:_index, LinkedHashMap_setIndex, Dynamic, 0x4beb13f2)      \
-  V(_HashVMBase, get:_data, LinkedHashMap_getData, Array, 0x4bf5ccb3)          \
-  V(_HashVMBase, set:_data, LinkedHashMap_setData, Dynamic, 0x6007556d)        \
-  V(_HashVMBase, get:_usedData, LinkedHashMap_getUsedData, Smi, 0x15e70845)    \
-  V(_HashVMBase, set:_usedData, LinkedHashMap_setUsedData, Dynamic, 0x3e8c6edc)\
-  V(_HashVMBase, get:_hashMask, LinkedHashMap_getHashMask, Smi, 0x35c5ac00)    \
-  V(_HashVMBase, set:_hashMask, LinkedHashMap_setHashMask, Dynamic, 0x49adf69e)\
+  V(Int64List, [], Int64ArrayGetIndexed, Dynamic, 0x680ec59b)                  \
+  V(Int64List, []=, Int64ArraySetIndexed, Dynamic, 0x0872fc15)                 \
+  V(_Bigint, get:_neg, Bigint_getNeg, Bool, 0x355fa565)                        \
+  V(_Bigint, get:_used, Bigint_getUsed, Smi, 0x33b9dcd2)                       \
+  V(_Bigint, get:_digits, Bigint_getDigits, TypedDataUint32Array, 0x68de883a)  \
+  V(_HashVMBase, get:_index, LinkedHashMap_getIndex, Dynamic, 0x02468899)      \
+  V(_HashVMBase, set:_index, LinkedHashMap_setIndex, Dynamic, 0x577d9e20)      \
+  V(_HashVMBase, get:_data, LinkedHashMap_getData, Array, 0x2d7987ee)          \
+  V(_HashVMBase, set:_data, LinkedHashMap_setData, Dynamic, 0x1674fb28)        \
+  V(_HashVMBase, get:_usedData, LinkedHashMap_getUsedData, Smi, 0x0884b12f)    \
+  V(_HashVMBase, set:_usedData, LinkedHashMap_setUsedData, Dynamic, 0x66f792c6)\
+  V(_HashVMBase, get:_hashMask, LinkedHashMap_getHashMask, Smi, 0x32f2c87d)    \
+  V(_HashVMBase, set:_hashMask, LinkedHashMap_setHashMask, Dynamic, 0x79ce8c9b)\
   V(_HashVMBase, get:_deletedKeys, LinkedHashMap_getDeletedKeys, Smi,          \
-    0x306e6a79)                                                                \
+    0x55839904)                                                                \
   V(_HashVMBase, set:_deletedKeys, LinkedHashMap_setDeletedKeys, Dynamic,      \
-    0x3fe95fc2)                                                                \
-  V(::, _classRangeCheck, ClassRangeCheck, Bool, 0x6279a7b3)                   \
-  V(::, _classRangeCheckNegative, ClassRangeCheckNegated, Bool, 0x4799dac1)    \
+    0x625e50cd)                                                                \
+  V(::, _classRangeCheck, ClassRangeCheck, Bool, 0x025e8d82)                   \
+  V(::, _classRangeCheckNegative, ClassRangeCheckNegated, Bool, 0x32451d73)    \
 
 
 // List of intrinsics:
@@ -138,103 +138,103 @@
 #define CORE_LIB_INTRINSIC_LIST(V)                                             \
   V(_Smi, ~, Smi_bitNegate, Smi, 0x63bfee11)                                   \
   V(_Smi, get:bitLength, Smi_bitLength, Smi, 0x25b2e24c)                       \
-  V(_Smi, _bitAndFromSmi, Smi_bitAndFromSmi, Smi, 0x0df806ed)                  \
-  V(_Bigint, _lsh, Bigint_lsh, Dynamic, 0x5cd95513)                            \
-  V(_Bigint, _rsh, Bigint_rsh, Dynamic, 0x2d68d0e1)                            \
-  V(_Bigint, _absAdd, Bigint_absAdd, Dynamic, 0x492f4865)                      \
-  V(_Bigint, _absSub, Bigint_absSub, Dynamic, 0x174a3a34)                      \
-  V(_Bigint, _mulAdd, Bigint_mulAdd, Dynamic, 0x24ced3ee)                      \
-  V(_Bigint, _sqrAdd, Bigint_sqrAdd, Dynamic, 0x60c6b633)                      \
-  V(_Bigint, _estQuotientDigit, Bigint_estQuotientDigit, Dynamic, 0x2f867482)  \
-  V(_Montgomery, _mulMod, Montgomery_mulMod, Dynamic, 0x741bed13)              \
-  V(_Double, >, Double_greaterThan, Bool, 0x569b0a81)                          \
+  V(_Smi, _bitAndFromSmi, Smi_bitAndFromSmi, Smi, 0x490a4da1)                  \
+  V(_Bigint, _lsh, Bigint_lsh, Dynamic, 0x0619eb8a)                            \
+  V(_Bigint, _rsh, Bigint_rsh, Dynamic, 0x0e1b80df)                            \
+  V(_Bigint, _absAdd, Bigint_absAdd, Dynamic, 0x1a2b6326)                      \
+  V(_Bigint, _absSub, Bigint_absSub, Dynamic, 0x3bebab4e)                      \
+  V(_Bigint, _mulAdd, Bigint_mulAdd, Dynamic, 0x7d48a0b3)                      \
+  V(_Bigint, _sqrAdd, Bigint_sqrAdd, Dynamic, 0x638b5f5d)                      \
+  V(_Bigint, _estQuotientDigit, Bigint_estQuotientDigit, Dynamic, 0x467dee78)  \
+  V(_Montgomery, _mulMod, Montgomery_mulMod, Dynamic, 0x36065c30)              \
+  V(_Double, >, Double_greaterThan, Bool, 0x452cd763)                          \
   V(_Double, >=, Double_greaterEqualThan, Bool, 0x6c317340)                    \
   V(_Double, <, Double_lessThan, Bool, 0x26dda4bc)                             \
   V(_Double, <=, Double_lessEqualThan, Bool, 0x1e869d20)                       \
-  V(_Double, ==, Double_equal, Bool, 0x578a1a51)                               \
-  V(_Double, +, Double_add, Double, 0x4bac5dd5)                                \
-  V(_Double, -, Double_sub, Double, 0x62052dbb)                                \
-  V(_Double, *, Double_mul, Double, 0x23d068d8)                                \
-  V(_Double, /, Double_div, Double, 0x48bac1dc)                                \
+  V(_Double, ==, Double_equal, Bool, 0x5244dca3)                               \
+  V(_Double, +, Double_add, Double, 0x49b2a530)                                \
+  V(_Double, -, Double_sub, Double, 0x31833626)                                \
+  V(_Double, *, Double_mul, Double, 0x21d31f1d)                                \
+  V(_Double, /, Double_div, Double, 0x3e584fe8)                                \
   V(_Double, get:isNaN, Double_getIsNaN, Bool, 0x0af8ebeb)                     \
   V(_Double, get:isInfinite, Double_getIsInfinite, Bool, 0x0f79e289)           \
   V(_Double, get:isNegative, Double_getIsNegative, Bool, 0x3a58ff36)           \
-  V(_Double, _mulFromInteger, Double_mulFromInteger, Double, 0x330e9a36)       \
-  V(_Double, .fromInteger, DoubleFromInteger, Double, 0x7ef45843)              \
+  V(_Double, _mulFromInteger, Double_mulFromInteger, Double, 0x7f565534)       \
+  V(_Double, .fromInteger, DoubleFromInteger, Double, 0x04906d0d)              \
   V(_List, []=, ObjectArraySetIndexed, Dynamic, 0x34d2c72c)                    \
   V(_GrowableList, .withData, GrowableArray_Allocate, GrowableObjectArray,     \
-    0x25a786de)                                                                \
-  V(_GrowableList, add, GrowableArray_add, Dynamic, 0x0d1358ed)                \
-  V(_RegExp, _ExecuteMatch, RegExp_ExecuteMatch, Dynamic, 0x6036d7fa)          \
+    0x401f3150)                                                                \
+  V(_GrowableList, add, GrowableArray_add, Dynamic, 0x71f49ac8)                \
+  V(_RegExp, _ExecuteMatch, RegExp_ExecuteMatch, Dynamic, 0x380184b1)          \
   V(_RegExp, _ExecuteMatchSticky, RegExp_ExecuteMatchSticky, Dynamic,          \
-    0x71c67f7d)                                                                \
+    0x79b8f955)                                                                \
   V(Object, ==, ObjectEquals, Bool, 0x11662ed8)                                \
   V(Object, get:runtimeType, ObjectRuntimeType, Type, 0x00e7c26b)              \
-  V(Object, _haveSameRuntimeType, ObjectHaveSameRuntimeType, Bool, 0x72aad7e2) \
+  V(Object, _haveSameRuntimeType, ObjectHaveSameRuntimeType, Bool, 0x6532255b) \
   V(_StringBase, get:hashCode, String_getHashCode, Smi, 0x78c2eb88)            \
   V(_StringBase, get:isEmpty, StringBaseIsEmpty, Bool, 0x74c21fca)             \
   V(_StringBase, _substringMatches, StringBaseSubstringMatches, Bool,          \
-    0x2f851deb)                                                                \
+    0x025b2ece)                                                                \
   V(_StringBase, [], StringBaseCharAt, Dynamic, 0x2cf92c45)                    \
   V(_OneByteString, get:hashCode, OneByteString_getHashCode, Smi, 0x78c2eb88)  \
   V(_OneByteString, _substringUncheckedNative,                                 \
-    OneByteString_substringUnchecked, OneByteString, 0x638c3722)               \
-  V(_OneByteString, _setAt, OneByteStringSetAt, Dynamic, 0x452533ef)           \
+    OneByteString_substringUnchecked, OneByteString, 0x3538ad86)               \
+  V(_OneByteString, _setAt, OneByteStringSetAt, Dynamic, 0x6836784f)           \
   V(_OneByteString, _allocate, OneByteString_allocate, OneByteString,          \
-    0x3d4fad8a)                                                                \
+    0x4c0a5574)                                                                \
   V(_OneByteString, ==, OneByteString_equality, Bool, 0x3f59b700)              \
   V(_TwoByteString, ==, TwoByteString_equality, Bool, 0x3f59b700)              \
 
 
 #define CORE_INTEGER_LIB_INTRINSIC_LIST(V)                                     \
   V(_IntegerImplementation, _addFromInteger, Integer_addFromInteger,           \
-    Dynamic, 0x79bde54b)                                                       \
-  V(_IntegerImplementation, +, Integer_add, Dynamic, 0x0e4300c2)               \
+    Dynamic, 0x6a10c54a)                                                       \
+  V(_IntegerImplementation, +, Integer_add, Dynamic, 0x20192008)               \
   V(_IntegerImplementation, _subFromInteger, Integer_subFromInteger, Dynamic,  \
-    0x3918c1af)                                                                \
-  V(_IntegerImplementation, -, Integer_sub, Dynamic, 0x0ce294c3)               \
+    0x3fa4b1ed)                                                                \
+  V(_IntegerImplementation, -, Integer_sub, Dynamic, 0x5b877969)               \
   V(_IntegerImplementation, _mulFromInteger, Integer_mulFromInteger,           \
-    Dynamic, 0x791ecebc)                                                       \
-  V(_IntegerImplementation, *, Integer_mul, Dynamic, 0x4d8e01a4)               \
+    Dynamic, 0x3216e299)                                                       \
+  V(_IntegerImplementation, *, Integer_mul, Dynamic, 0x142887aa)               \
   V(_IntegerImplementation, _moduloFromInteger, Integer_moduloFromInteger,     \
-    Dynamic, 0x2e72f552)                                                       \
-  V(_IntegerImplementation, ~/, Integer_truncDivide, Dynamic, 0x3caf6780)      \
+    Dynamic, 0x6348b974)                                                       \
+  V(_IntegerImplementation, ~/, Integer_truncDivide, Dynamic, 0x5b740346)      \
   V(_IntegerImplementation, unary-, Integer_negate, Dynamic, 0x59dce57c)       \
   V(_IntegerImplementation, _bitAndFromInteger, Integer_bitAndFromInteger,     \
-    Dynamic, 0x1dfbe172)                                                       \
-  V(_IntegerImplementation, &, Integer_bitAnd, Dynamic, 0x596a453e)            \
+    Dynamic, 0x395b1678)                                                       \
+  V(_IntegerImplementation, &, Integer_bitAnd, Dynamic, 0x50aab6e4)            \
   V(_IntegerImplementation, _bitOrFromInteger, Integer_bitOrFromInteger,       \
-    Dynamic, 0x3d79aa1c)                                                       \
-  V(_IntegerImplementation, |, Integer_bitOr, Dynamic, 0x071e153c)             \
+    Dynamic, 0x6a36b395)                                                       \
+  V(_IntegerImplementation, |, Integer_bitOr, Dynamic, 0x40b9d4c2)             \
   V(_IntegerImplementation, _bitXorFromInteger, Integer_bitXorFromInteger,     \
-    Dynamic, 0x4fd73f45)                                                       \
-  V(_IntegerImplementation, ^, Integer_bitXor, Dynamic, 0x0c8aeb3d)            \
+    Dynamic, 0x72da93f0)                                                       \
+  V(_IntegerImplementation, ^, Integer_bitXor, Dynamic, 0x16edce03)            \
   V(_IntegerImplementation, _greaterThanFromInteger,                           \
-    Integer_greaterThanFromInt, Bool, 0x2e801bc8)                              \
-  V(_IntegerImplementation, >, Integer_greaterThan, Bool, 0x28287b8f)          \
-  V(_IntegerImplementation, ==, Integer_equal, Bool, 0x103da147)               \
+    Integer_greaterThanFromInt, Bool, 0x4a50ed58)                              \
+  V(_IntegerImplementation, >, Integer_greaterThan, Bool, 0x6220711f)          \
+  V(_IntegerImplementation, ==, Integer_equal, Bool, 0x0d4d7f2c)               \
   V(_IntegerImplementation, _equalToInteger, Integer_equalToInteger, Bool,     \
-    0x7773d51d)                                                                \
+    0x063be842)                                                                \
   V(_IntegerImplementation, <, Integer_lessThan, Bool, 0x26dda4bc)             \
   V(_IntegerImplementation, <=, Integer_lessEqualThan, Bool, 0x1e869d20)       \
   V(_IntegerImplementation, >=, Integer_greaterEqualThan, Bool, 0x6c317340)    \
-  V(_IntegerImplementation, <<, Integer_shl, Dynamic, 0x4334dfc0)              \
-  V(_IntegerImplementation, >>, Integer_sar, Dynamic, 0x4a2583a1)              \
+  V(_IntegerImplementation, <<, Integer_shl, Dynamic, 0x5f43ef06)              \
+  V(_IntegerImplementation, >>, Integer_sar, Dynamic, 0x08a241c7)              \
   V(_Double, toInt, DoubleToInteger, Dynamic, 0x26ef344b)
 
 
 #define MATH_LIB_INTRINSIC_LIST(V)                                             \
-  V(::, sqrt, MathSqrt, Double, 0x1afb83d4)                                    \
-  V(_Random, _nextState, Random_nextState, Dynamic, 0x1e4b0103)                \
+  V(::, sqrt, MathSqrt, Double, 0x0a683033)                                    \
+  V(_Random, _nextState, Random_nextState, Dynamic, 0x24d91397)                \
 
 #define GRAPH_MATH_LIB_INTRINSIC_LIST(V)                                       \
-  V(::, sin, MathSin, Double, 0x0213abe6)                                      \
-  V(::, cos, MathCos, Double, 0x79a7611c)                                      \
-  V(::, tan, MathTan, Double, 0x4e2e20db)                                      \
-  V(::, asin, MathAsin, Double, 0x661ff68b)                                    \
-  V(::, acos, MathAcos, Double, 0x44e71d5f)                                    \
-  V(::, atan, MathAtan, Double, 0x4436a657)                                    \
-  V(::, atan2, MathAtan2, Double, 0x60a40743)                                  \
+  V(::, sin, MathSin, Double, 0x595a044c)                                      \
+  V(::, cos, MathCos, Double, 0x337a20be)                                      \
+  V(::, tan, MathTan, Double, 0x29aba1ea)                                      \
+  V(::, asin, MathAsin, Double, 0x48ec330d)                                    \
+  V(::, acos, MathAcos, Double, 0x22ef2552)                                    \
+  V(::, atan, MathAtan, Double, 0x38473515)                                    \
+  V(::, atan2, MathAtan2, Double, 0x39f1fa41)                                  \
 
 #define TYPED_DATA_LIB_INTRINSIC_LIST(V)                                       \
   V(Int8List, ., TypedData_Int8Array_factory, TypedDataInt8Array, 0x2e7749e3)  \
@@ -266,45 +266,45 @@
     TypedDataFloat64x2Array, 0x18cbf4d9)                                       \
 
 #define GRAPH_TYPED_DATA_INTRINSICS_LIST(V)                                    \
-  V(Int8List, [], Int8ArrayGetIndexed, Smi, 0x069af8b3)                        \
-  V(Int8List, []=, Int8ArraySetIndexed, Dynamic, 0x33994cd7)                   \
-  V(Uint8List, [], Uint8ArrayGetIndexed, Smi, 0x027603ed)                      \
-  V(Uint8List, []=, Uint8ArraySetIndexed, Dynamic, 0x060d5256)                 \
-  V(_ExternalUint8Array, [], ExternalUint8ArrayGetIndexed, Smi, 0x027603ed)    \
+  V(Int8List, [], Int8ArrayGetIndexed, Smi, 0x5f9a4430)                        \
+  V(Int8List, []=, Int8ArraySetIndexed, Dynamic, 0x5f880110)                   \
+  V(Uint8List, [], Uint8ArrayGetIndexed, Smi, 0x1eb150d8)                      \
+  V(Uint8List, []=, Uint8ArraySetIndexed, Dynamic, 0x4cf76981)                 \
+  V(_ExternalUint8Array, [], ExternalUint8ArrayGetIndexed, Smi, 0x1eb150d8)    \
   V(_ExternalUint8Array, []=, ExternalUint8ArraySetIndexed, Dynamic,           \
-    0x060d5256)                                                                \
-  V(Uint8ClampedList, [], Uint8ClampedArrayGetIndexed, Smi, 0x027603ed)        \
-  V(Uint8ClampedList, []=, Uint8ClampedArraySetIndexed, Dynamic, 0x28f5f058)   \
+    0x4cf76981)                                                                \
+  V(Uint8ClampedList, [], Uint8ClampedArrayGetIndexed, Smi, 0x1eb150d8)        \
+  V(Uint8ClampedList, []=, Uint8ClampedArraySetIndexed, Dynamic, 0x2224afe1)   \
   V(_ExternalUint8ClampedArray, [], ExternalUint8ClampedArrayGetIndexed,       \
-    Smi, 0x027603ed)                                                           \
+    Smi, 0x1eb150d8)                                                           \
   V(_ExternalUint8ClampedArray, []=, ExternalUint8ClampedArraySetIndexed,      \
-    Dynamic, 0x28f5f058)                                                       \
-  V(Int16List, [], Int16ArrayGetIndexed, Smi, 0x173cd6a1)                      \
-  V(Int16List, []=, Int16ArraySetIndexed, Dynamic, 0x32f84e3c)                 \
-  V(Uint16List, [], Uint16ArrayGetIndexed, Smi, 0x3ececa2f)                    \
-  V(Uint16List, []=, Uint16ArraySetIndexed, Dynamic, 0x5c3a0bb9)               \
-  V(Int32List, [], Int32ArrayGetIndexed, Dynamic, 0x262eef09)                  \
-  V(Int32List, []=, Int32ArraySetIndexed, Dynamic, 0x1b05b471)                 \
-  V(Uint32List, [], Uint32ArrayGetIndexed, Dynamic, 0x6040f7fb)                \
-  V(Uint32List, []=, Uint32ArraySetIndexed, Dynamic, 0x3a4e1119)               \
-  V(Float64List, [], Float64ArrayGetIndexed, Double, 0x7a27098d)               \
-  V(Float64List, []=, Float64ArraySetIndexed, Dynamic, 0x139b2465)             \
-  V(Float32List, [], Float32ArrayGetIndexed, Double, 0x5686528f)               \
-  V(Float32List, []=, Float32ArraySetIndexed, Dynamic, 0x1b0d90df)             \
-  V(Float32x4List, [], Float32x4ArrayGetIndexed, Float32x4, 0x01c7017b)        \
-  V(Float32x4List, []=, Float32x4ArraySetIndexed, Dynamic, 0x56e843aa)         \
-  V(Int32x4List, [], Int32x4ArrayGetIndexed, Int32x4, 0x08353f8d)              \
-  V(Int32x4List, []=, Int32x4ArraySetIndexed, Dynamic, 0x1d9a47a5)             \
-  V(Float64x2List, [], Float64x2ArrayGetIndexed, Float64x2, 0x669b1498)        \
-  V(Float64x2List, []=, Float64x2ArraySetIndexed, Dynamic, 0x76da6ffe)         \
+    Dynamic, 0x2224afe1)                                                       \
+  V(Int16List, [], Int16ArrayGetIndexed, Smi, 0x74ea134c)                      \
+  V(Int16List, []=, Int16ArraySetIndexed, Dynamic, 0x48e25661)                 \
+  V(Uint16List, [], Uint16ArrayGetIndexed, Smi, 0x756d9a97)                    \
+  V(Uint16List, []=, Uint16ArraySetIndexed, Dynamic, 0x698f9d4f)               \
+  V(Int32List, [], Int32ArrayGetIndexed, Dynamic, 0x61e49de1)                  \
+  V(Int32List, []=, Int32ArraySetIndexed, Dynamic, 0x55736c63)                 \
+  V(Uint32List, [], Uint32ArrayGetIndexed, Dynamic, 0x2eaa22d2)                \
+  V(Uint32List, []=, Uint32ArraySetIndexed, Dynamic, 0x3c88eeb9)               \
+  V(Float64List, [], Float64ArrayGetIndexed, Double, 0x20950e8a)               \
+  V(Float64List, []=, Float64ArraySetIndexed, Dynamic, 0x556a0727)             \
+  V(Float32List, [], Float32ArrayGetIndexed, Double, 0x7101fa23)               \
+  V(Float32List, []=, Float32ArraySetIndexed, Dynamic, 0x5e32c1eb)             \
+  V(Float32x4List, [], Float32x4ArrayGetIndexed, Float32x4, 0x28b0a7ef)        \
+  V(Float32x4List, []=, Float32x4ArraySetIndexed, Dynamic, 0x4babf032)         \
+  V(Int32x4List, [], Int32x4ArrayGetIndexed, Int32x4, 0x619c79a0)              \
+  V(Int32x4List, []=, Int32x4ArraySetIndexed, Dynamic, 0x021bd16b)             \
+  V(Float64x2List, [], Float64x2ArrayGetIndexed, Float64x2, 0x7a6dd5e5)        \
+  V(Float64x2List, []=, Float64x2ArraySetIndexed, Dynamic, 0x3c59fecb)         \
   V(_TypedList, get:length, TypedDataLength, Smi, 0x2090dc1a)                  \
   V(Float32x4, get:x, Float32x4ShuffleX, Double, 0x63d0c13f)                   \
   V(Float32x4, get:y, Float32x4ShuffleY, Double, 0x20343b1b)                   \
   V(Float32x4, get:z, Float32x4ShuffleZ, Double, 0x13181dba)                   \
   V(Float32x4, get:w, Float32x4ShuffleW, Double, 0x69895020)                   \
-  V(Float32x4, _mul, Float32x4Mul, Float32x4, 0x028d3146)                      \
-  V(Float32x4, _sub, Float32x4Sub, Float32x4, 0x062f78f7)                      \
-  V(Float32x4, _add, Float32x4Add, Float32x4, 0x509f9006)                      \
+  V(Float32x4, _mul, Float32x4Mul, Float32x4, 0x6183ae12)                      \
+  V(Float32x4, _sub, Float32x4Sub, Float32x4, 0x22a8d3ea)                      \
+  V(Float32x4, _add, Float32x4Add, Float32x4, 0x613c30f4)                      \
 
 #define GRAPH_CORE_INTRINSICS_LIST(V)                                          \
   V(_List, get:length, ObjectArrayLength, Smi, 0x25943ad2)                     \
@@ -312,9 +312,9 @@
   V(_ImmutableList, get:length, ImmutableArrayLength, Smi, 0x25943ad2)         \
   V(_ImmutableList, [], ImmutableArrayGetIndexed, Dynamic, 0x157b4670)         \
   V(_GrowableList, get:length, GrowableArrayLength, Smi, 0x18dc9df6)           \
-  V(_GrowableList, get:_capacity, GrowableArrayCapacity, Smi, 0x02734d82)      \
-  V(_GrowableList, _setData, GrowableArraySetData, Dynamic, 0x0c854013)        \
-  V(_GrowableList, _setLength, GrowableArraySetLength, Dynamic, 0x1401a7d6)    \
+  V(_GrowableList, get:_capacity, GrowableArrayCapacity, Smi, 0x2e03d5a2)      \
+  V(_GrowableList, _setData, GrowableArraySetData, Dynamic, 0x6dfc498a)        \
+  V(_GrowableList, _setLength, GrowableArraySetLength, Dynamic, 0x257bfc1c)    \
   V(_GrowableList, [], GrowableArrayGetIndexed, Dynamic, 0x74ad8832)           \
   V(_GrowableList, []=, GrowableArraySetIndexed, Dynamic, 0x0d6cfe96)          \
   V(_StringBase, get:length, StringBaseLength, Smi, 0x2a2c1b13)                \
@@ -329,7 +329,7 @@
   V(_Double, roundToDouble, DoubleRound, Double, 0x2f89c512)                   \
   V(_Double, floorToDouble, DoubleFloor, Double, 0x6aa87a5f)                   \
   V(_Double, ceilToDouble, DoubleCeil, Double, 0x1b045e9e)                     \
-  V(_Double, _modulo, DoubleMod, Double, 0x2e41c4fc)
+  V(_Double, _modulo, DoubleMod, Double, 0x5b8ceed7)
 
 
 #define GRAPH_INTRINSICS_LIST(V)                                               \
@@ -339,10 +339,10 @@
 
 #define DEVELOPER_LIB_INTRINSIC_LIST(V)                                        \
   V(_UserTag, makeCurrent, UserTag_makeCurrent, Dynamic, 0x0b3066fd)           \
-  V(::, _getDefaultTag, UserTag_defaultTag, Dynamic, 0x14ddc3b7)               \
-  V(::, _getCurrentTag, Profiler_getCurrentTag, Dynamic, 0x486ee02d)           \
+  V(::, _getDefaultTag, UserTag_defaultTag, Dynamic, 0x69f3f1ad)               \
+  V(::, _getCurrentTag, Profiler_getCurrentTag, Dynamic, 0x05fa99d2)           \
   V(::, _isDartStreamEnabled, Timeline_isDartStreamEnabled, Dynamic,           \
-    0x1667ce76)                                                                \
+    0x72f13f7a)                                                                \
 
 #define ALL_INTRINSICS_NO_INTEGER_LIB_LIST(V)                                  \
   CORE_LIB_INTRINSIC_LIST(V)                                                   \
@@ -366,133 +366,133 @@
   V(_ImmutableList, get:length, ImmutableArrayLength, 0x25943ad2)              \
   V(_TypedList, get:length, TypedDataLength, 0x2090dc1a)                       \
   V(_GrowableList, get:length, GrowableArrayLength, 0x18dc9df6)                \
-  V(_GrowableList, get:_capacity, GrowableArrayCapacity, 0x02734d82)           \
-  V(_GrowableList, add, GrowableListAdd, 0x0d1358ed)                           \
+  V(_GrowableList, get:_capacity, GrowableArrayCapacity, 0x2e03d5a2)           \
+  V(_GrowableList, add, GrowableListAdd, 0x71f49ac8)                           \
   V(_GrowableList, removeLast, GrowableListRemoveLast, 0x7add0363)             \
   V(_StringBase, get:length, StringBaseLength, 0x2a2c1b13)                     \
-  V(ListIterator, moveNext, ListIteratorMoveNext, 0x3f892e71)                  \
-  V(_FixedSizeArrayIterator, moveNext, FixedListIteratorMoveNext, 0x5681c902)  \
+  V(ListIterator, moveNext, ListIteratorMoveNext, 0x4f8ff9cc)                  \
+  V(_FixedSizeArrayIterator, moveNext, FixedListIteratorMoveNext, 0x50e0604b)  \
   V(_GrowableList, get:iterator, GrowableArrayIterator, 0x6db11a73)            \
   V(_GrowableList, forEach, GrowableArrayForEach, 0x250036fe)                  \
-  V(_List, ., ObjectArrayAllocate, 0x63078b15)                                 \
+  V(_List, ., ObjectArrayAllocate, 0x375519ad)                                 \
   V(ListMixin, get:isEmpty, ListMixinIsEmpty, 0x787d9bc6)                      \
-  V(_List, get:iterator, ObjectArrayIterator, 0x119cf41a)                      \
+  V(_List, get:iterator, ObjectArrayIterator, 0x7e634791)                      \
   V(_List, forEach, ObjectArrayForEach, 0x0abce191)                            \
-  V(_List, _slice, ObjectArraySlice, 0x3219e715)                               \
-  V(_ImmutableList, get:iterator, ImmutableArrayIterator, 0x119cf41a)          \
+  V(_List, _slice, ObjectArraySlice, 0x01b71c13)                               \
+  V(_ImmutableList, get:iterator, ImmutableArrayIterator, 0x7e634791)          \
   V(_ImmutableList, forEach, ImmutableArrayForEach, 0x0abce191)                \
-  V(_Uint8ArrayView, [], Uint8ArrayViewGetIndexed, 0x4fc6b3d3)                 \
-  V(_Uint8ArrayView, []=, Uint8ArrayViewSetIndexed, 0x2032fdf0)                \
-  V(_Int8ArrayView, [], Int8ArrayViewGetIndexed, 0x12036952)                   \
-  V(_Int8ArrayView, []=, Int8ArrayViewSetIndexed, 0x6d881658)                  \
-  V(_ByteDataView, setInt8, ByteDataViewSetInt8, 0x275cbdca)                   \
-  V(_ByteDataView, setUint8, ByteDataViewSetUint8, 0x62774e77)                 \
-  V(_ByteDataView, setInt16, ByteDataViewSetInt16, 0x7a43c6c2)                 \
-  V(_ByteDataView, setUint16, ByteDataViewSetUint16, 0x64dd988f)               \
-  V(_ByteDataView, setInt32, ByteDataViewSetInt32, 0x3363264a)                 \
-  V(_ByteDataView, setUint32, ByteDataViewSetUint32, 0x158f9899)               \
-  V(_ByteDataView, setInt64, ByteDataViewSetInt64, 0x480f73a5)                 \
-  V(_ByteDataView, setUint64, ByteDataViewSetUint64, 0x5c23db8c)               \
-  V(_ByteDataView, setFloat32, ByteDataViewSetFloat32, 0x4f76c49a)             \
-  V(_ByteDataView, setFloat64, ByteDataViewSetFloat64, 0x5e1ddd4f)             \
-  V(_ByteDataView, getInt8, ByteDataViewGetInt8, 0x01bac87d)                   \
-  V(_ByteDataView, getUint8, ByteDataViewGetUint8, 0x129dab34)                 \
-  V(_ByteDataView, getInt16, ByteDataViewGetInt16, 0x60282377)                 \
-  V(_ByteDataView, getUint16, ByteDataViewGetUint16, 0x10edcd89)               \
-  V(_ByteDataView, getInt32, ByteDataViewGetInt32, 0x79630f81)                 \
-  V(_ByteDataView, getUint32, ByteDataViewGetUint32, 0x220d3da8)               \
-  V(_ByteDataView, getInt64, ByteDataViewGetInt64, 0x757dd5c8)                 \
-  V(_ByteDataView, getUint64, ByteDataViewGetUint64, 0x2fab992e)               \
-  V(_ByteDataView, getFloat32, ByteDataViewGetFloat32, 0x387e9fc6)             \
-  V(_ByteDataView, getFloat64, ByteDataViewGetFloat64, 0x5396432d)             \
-  V(::, exp, MathExp, 0x5b894d7b)                                              \
-  V(::, log, MathLog, 0x2e25132c)                                              \
+  V(_Uint8ArrayView, [], Uint8ArrayViewGetIndexed, 0x760ba8c2)                 \
+  V(_Uint8ArrayView, []=, Uint8ArrayViewSetIndexed, 0x44fc1997)                \
+  V(_Int8ArrayView, [], Int8ArrayViewGetIndexed, 0x7735aad3)                   \
+  V(_Int8ArrayView, []=, Int8ArrayViewSetIndexed, 0x4237db0d)                  \
+  V(_ByteDataView, setInt8, ByteDataViewSetInt8, 0x66702980)                   \
+  V(_ByteDataView, setUint8, ByteDataViewSetUint8, 0x7c729d61)                 \
+  V(_ByteDataView, setInt16, ByteDataViewSetInt16, 0x203478e8)                 \
+  V(_ByteDataView, setUint16, ByteDataViewSetUint16, 0x16c35617)               \
+  V(_ByteDataView, setInt32, ByteDataViewSetInt32, 0x200c1aae)                 \
+  V(_ByteDataView, setUint32, ByteDataViewSetUint32, 0x281c378e)               \
+  V(_ByteDataView, setInt64, ByteDataViewSetInt64, 0x10595a04)                 \
+  V(_ByteDataView, setUint64, ByteDataViewSetUint64, 0x364fcc46)               \
+  V(_ByteDataView, setFloat32, ByteDataViewSetFloat32, 0x30628609)             \
+  V(_ByteDataView, setFloat64, ByteDataViewSetFloat64, 0x331b1f4b)             \
+  V(_ByteDataView, getInt8, ByteDataViewGetInt8, 0x62761d8f)                   \
+  V(_ByteDataView, getUint8, ByteDataViewGetUint8, 0x579a5e34)                 \
+  V(_ByteDataView, getInt16, ByteDataViewGetInt16, 0x73e0175b)                 \
+  V(_ByteDataView, getUint16, ByteDataViewGetUint16, 0x3691576a)               \
+  V(_ByteDataView, getInt32, ByteDataViewGetInt32, 0x44d407a8)                 \
+  V(_ByteDataView, getUint32, ByteDataViewGetUint32, 0x160c7450)               \
+  V(_ByteDataView, getInt64, ByteDataViewGetInt64, 0x02a2ffca)                 \
+  V(_ByteDataView, getUint64, ByteDataViewGetUint64, 0x4dd4eedd)               \
+  V(_ByteDataView, getFloat32, ByteDataViewGetFloat32, 0x474b4719)             \
+  V(_ByteDataView, getFloat64, ByteDataViewGetFloat64, 0x47207cf7)             \
+  V(::, exp, MathExp, 0x4ccba23a)                                              \
+  V(::, log, MathLog, 0x3908fd3c)                                              \
   V(::, max, MathMax, 0x54121d6a)                                              \
   V(::, min, MathMin, 0x4276561c)                                              \
-  V(::, pow, MathPow, 0x438e3089)                                              \
-  V(::, _classRangeCheck, ClassRangeCheck, 0x6279a7b3)                         \
-  V(::, _classRangeCheckNegative, ClassRangeCheckNegated, 0x4799dac1)          \
+  V(::, pow, MathPow, 0x443379a8)                                              \
+  V(::, _classRangeCheck, ClassRangeCheck, 0x025e8d82)                         \
+  V(::, _classRangeCheckNegative, ClassRangeCheckNegated, 0x32451d73)          \
   V(Lists, copy, ListsCopy, 0x21a194fa)                                        \
-  V(_Bigint, get:_neg, Bigint_getNeg, 0x7bf17a57)                              \
-  V(_Bigint, get:_used, Bigint_getUsed, 0x55041013)                            \
-  V(_Bigint, get:_digits, Bigint_getDigits, 0x46a6c1b3)                        \
-  V(_HashVMBase, get:_index, LinkedHashMap_getIndex, 0x7d6bb76b)               \
-  V(_HashVMBase, set:_index, LinkedHashMap_setIndex, 0x4beb13f2)               \
-  V(_HashVMBase, get:_data, LinkedHashMap_getData, 0x4bf5ccb3)                 \
-  V(_HashVMBase, set:_data, LinkedHashMap_setData, 0x6007556d)                 \
-  V(_HashVMBase, get:_usedData, LinkedHashMap_getUsedData, 0x15e70845)         \
-  V(_HashVMBase, set:_usedData, LinkedHashMap_setUsedData, 0x3e8c6edc)         \
-  V(_HashVMBase, get:_hashMask, LinkedHashMap_getHashMask, 0x35c5ac00)         \
-  V(_HashVMBase, set:_hashMask, LinkedHashMap_setHashMask, 0x49adf69e)         \
-  V(_HashVMBase, get:_deletedKeys, LinkedHashMap_getDeletedKeys, 0x306e6a79)   \
-  V(_HashVMBase, set:_deletedKeys, LinkedHashMap_setDeletedKeys, 0x3fe95fc2)   \
+  V(_Bigint, get:_neg, Bigint_getNeg, 0x355fa565)                              \
+  V(_Bigint, get:_used, Bigint_getUsed, 0x33b9dcd2)                            \
+  V(_Bigint, get:_digits, Bigint_getDigits, 0x68de883a)                        \
+  V(_HashVMBase, get:_index, LinkedHashMap_getIndex, 0x02468899)               \
+  V(_HashVMBase, set:_index, LinkedHashMap_setIndex, 0x577d9e20)               \
+  V(_HashVMBase, get:_data, LinkedHashMap_getData, 0x2d7987ee)                 \
+  V(_HashVMBase, set:_data, LinkedHashMap_setData, 0x1674fb28)                 \
+  V(_HashVMBase, get:_usedData, LinkedHashMap_getUsedData, 0x0884b12f)         \
+  V(_HashVMBase, set:_usedData, LinkedHashMap_setUsedData, 0x66f792c6)         \
+  V(_HashVMBase, get:_hashMask, LinkedHashMap_getHashMask, 0x32f2c87d)         \
+  V(_HashVMBase, set:_hashMask, LinkedHashMap_setHashMask, 0x79ce8c9b)         \
+  V(_HashVMBase, get:_deletedKeys, LinkedHashMap_getDeletedKeys, 0x55839904)   \
+  V(_HashVMBase, set:_deletedKeys, LinkedHashMap_setDeletedKeys, 0x625e50cd)   \
 
 // A list of core function that should never be inlined.
 #define INLINE_BLACK_LIST(V)                                                   \
-  V(::, asin, MathAsin, 0x661ff68b)                                            \
-  V(::, acos, MathAcos, 0x44e71d5f)                                            \
-  V(::, atan, MathAtan, 0x4436a657)                                            \
-  V(::, atan2, MathAtan2, 0x60a40743)                                          \
-  V(::, cos, MathCos, 0x79a7611c)                                              \
-  V(::, sin, MathSin, 0x0213abe6)                                              \
-  V(::, sqrt, MathSqrt, 0x1afb83d4)                                            \
-  V(::, tan, MathTan, 0x4e2e20db)                                              \
-  V(_Bigint, _lsh, Bigint_lsh, 0x5cd95513)                                     \
-  V(_Bigint, _rsh, Bigint_rsh, 0x2d68d0e1)                                     \
-  V(_Bigint, _absAdd, Bigint_absAdd, 0x492f4865)                               \
-  V(_Bigint, _absSub, Bigint_absSub, 0x174a3a34)                               \
-  V(_Bigint, _mulAdd, Bigint_mulAdd, 0x24ced3ee)                               \
-  V(_Bigint, _sqrAdd, Bigint_sqrAdd, 0x60c6b633)                               \
-  V(_Bigint, _estQuotientDigit, Bigint_estQuotientDigit, 0x2f867482)           \
-  V(_Montgomery, _mulMod, Montgomery_mulMod, 0x741bed13)                       \
-  V(_Double, >, Double_greaterThan, 0x569b0a81)                                \
+  V(::, asin, MathAsin, 0x48ec330d)                                            \
+  V(::, acos, MathAcos, 0x22ef2552)                                            \
+  V(::, atan, MathAtan, 0x38473515)                                            \
+  V(::, atan2, MathAtan2, 0x39f1fa41)                                          \
+  V(::, cos, MathCos, 0x337a20be)                                              \
+  V(::, sin, MathSin, 0x595a044c)                                              \
+  V(::, sqrt, MathSqrt, 0x0a683033)                                            \
+  V(::, tan, MathTan, 0x29aba1ea)                                              \
+  V(_Bigint, _lsh, Bigint_lsh, 0x0619eb8a)                                     \
+  V(_Bigint, _rsh, Bigint_rsh, 0x0e1b80df)                                     \
+  V(_Bigint, _absAdd, Bigint_absAdd, 0x1a2b6326)                               \
+  V(_Bigint, _absSub, Bigint_absSub, 0x3bebab4e)                               \
+  V(_Bigint, _mulAdd, Bigint_mulAdd, 0x7d48a0b3)                               \
+  V(_Bigint, _sqrAdd, Bigint_sqrAdd, 0x638b5f5d)                               \
+  V(_Bigint, _estQuotientDigit, Bigint_estQuotientDigit, 0x467dee78)           \
+  V(_Montgomery, _mulMod, Montgomery_mulMod, 0x36065c30)                       \
+  V(_Double, >, Double_greaterThan, 0x452cd763)                                \
   V(_Double, >=, Double_greaterEqualThan, 0x6c317340)                          \
   V(_Double, <, Double_lessThan, 0x26dda4bc)                                   \
   V(_Double, <=, Double_lessEqualThan, 0x1e869d20)                             \
-  V(_Double, ==, Double_equal, 0x578a1a51)                                     \
-  V(_Double, +, Double_add, 0x4bac5dd5)                                        \
-  V(_Double, -, Double_sub, 0x62052dbb)                                        \
-  V(_Double, *, Double_mul, 0x23d068d8)                                        \
-  V(_Double, /, Double_div, 0x48bac1dc)                                        \
-  V(_IntegerImplementation, +, Integer_add, 0x0e4300c2)                        \
-  V(_IntegerImplementation, -, Integer_sub, 0x0ce294c3)                        \
-  V(_IntegerImplementation, *, Integer_mul, 0x4d8e01a4)                        \
-  V(_IntegerImplementation, ~/, Integer_truncDivide, 0x3caf6780)               \
+  V(_Double, ==, Double_equal, 0x5244dca3)                                     \
+  V(_Double, +, Double_add, 0x49b2a530)                                        \
+  V(_Double, -, Double_sub, 0x31833626)                                        \
+  V(_Double, *, Double_mul, 0x21d31f1d)                                        \
+  V(_Double, /, Double_div, 0x3e584fe8)                                        \
+  V(_IntegerImplementation, +, Integer_add, 0x20192008)                        \
+  V(_IntegerImplementation, -, Integer_sub, 0x5b877969)                        \
+  V(_IntegerImplementation, *, Integer_mul, 0x142887aa)                        \
+  V(_IntegerImplementation, ~/, Integer_truncDivide, 0x5b740346)               \
   V(_IntegerImplementation, unary-, Integer_negate, 0x59dce57c)                \
-  V(_IntegerImplementation, &, Integer_bitAnd, 0x596a453e)                     \
-  V(_IntegerImplementation, |, Integer_bitOr, 0x071e153c)                      \
-  V(_IntegerImplementation, ^, Integer_bitXor, 0x0c8aeb3d)                     \
-  V(_IntegerImplementation, >, Integer_greaterThan, 0x28287b8f)                \
-  V(_IntegerImplementation, ==, Integer_equal, 0x103da147)                     \
+  V(_IntegerImplementation, &, Integer_bitAnd, 0x50aab6e4)                     \
+  V(_IntegerImplementation, |, Integer_bitOr, 0x40b9d4c2)                      \
+  V(_IntegerImplementation, ^, Integer_bitXor, 0x16edce03)                     \
+  V(_IntegerImplementation, >, Integer_greaterThan, 0x6220711f)                \
+  V(_IntegerImplementation, ==, Integer_equal, 0x0d4d7f2c)                     \
   V(_IntegerImplementation, <, Integer_lessThan, 0x26dda4bc)                   \
   V(_IntegerImplementation, <=, Integer_lessEqualThan, 0x1e869d20)             \
   V(_IntegerImplementation, >=, Integer_greaterEqualThan, 0x6c317340)          \
-  V(_IntegerImplementation, <<, Integer_shl, 0x4334dfc0)                       \
-  V(_IntegerImplementation, >>, Integer_sar, 0x4a2583a1)                       \
+  V(_IntegerImplementation, <<, Integer_shl, 0x5f43ef06)                       \
+  V(_IntegerImplementation, >>, Integer_sar, 0x08a241c7)                       \
 
 // A list of core functions that internally dispatch based on received id.
 #define POLYMORPHIC_TARGET_LIST(V)                                             \
   V(_StringBase, [], StringBaseCharAt, 0x2cf92c45)                             \
-  V(_TypedList, _getInt8, ByteArrayBaseGetInt8, 0x59e7291d)                    \
-  V(_TypedList, _getUint8, ByteArrayBaseGetUint8, 0x38d3e5bf)                  \
-  V(_TypedList, _getInt16, ByteArrayBaseGetInt16, 0x19dde22c)                  \
-  V(_TypedList, _getUint16, ByteArrayBaseGetUint16, 0x4f3dbe58)                \
-  V(_TypedList, _getInt32, ByteArrayBaseGetInt32, 0x082db131)                  \
-  V(_TypedList, _getUint32, ByteArrayBaseGetUint32, 0x1dcbfb98)                \
-  V(_TypedList, _getFloat32, ByteArrayBaseGetFloat32, 0x63b56e15)              \
-  V(_TypedList, _getFloat64, ByteArrayBaseGetFloat64, 0x399dacf8)              \
-  V(_TypedList, _getFloat32x4, ByteArrayBaseGetFloat32x4, 0x4761a5be)          \
-  V(_TypedList, _getInt32x4, ByteArrayBaseGetInt32x4, 0x3053e92c)              \
-  V(_TypedList, _setInt8, ByteArrayBaseSetInt8, 0x4e82d1e9)                    \
-  V(_TypedList, _setUint8, ByteArrayBaseSetInt8, 0x4f3587fc)                   \
-  V(_TypedList, _setInt16, ByteArrayBaseSetInt16, 0x6cef30ee)                  \
-  V(_TypedList, _setUint16, ByteArrayBaseSetInt16, 0x64f938ac)                 \
-  V(_TypedList, _setInt32, ByteArrayBaseSetInt32, 0x3693c029)                  \
-  V(_TypedList, _setUint32, ByteArrayBaseSetUint32, 0x74bbf260)                \
-  V(_TypedList, _setFloat32, ByteArrayBaseSetFloat32, 0x6e72f2a4)              \
-  V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, 0x4765edda)              \
-  V(_TypedList, _setFloat32x4, ByteArrayBaseSetFloat32x4, 0x7cca4533)          \
-  V(_TypedList, _setInt32x4, ByteArrayBaseSetInt32x4, 0x7631bdbc)              \
+  V(_TypedList, _getInt8, ByteArrayBaseGetInt8, 0x7041895a)                    \
+  V(_TypedList, _getUint8, ByteArrayBaseGetUint8, 0x336fa3ea)                  \
+  V(_TypedList, _getInt16, ByteArrayBaseGetInt16, 0x231bbe2e)                  \
+  V(_TypedList, _getUint16, ByteArrayBaseGetUint16, 0x0371785f)                \
+  V(_TypedList, _getInt32, ByteArrayBaseGetInt32, 0x65ab3a20)                  \
+  V(_TypedList, _getUint32, ByteArrayBaseGetUint32, 0x0cb0fcf6)                \
+  V(_TypedList, _getFloat32, ByteArrayBaseGetFloat32, 0x6674ea6f)              \
+  V(_TypedList, _getFloat64, ByteArrayBaseGetFloat64, 0x236c6e7a)              \
+  V(_TypedList, _getFloat32x4, ByteArrayBaseGetFloat32x4, 0x5c367ffb)          \
+  V(_TypedList, _getInt32x4, ByteArrayBaseGetInt32x4, 0x772d1c0f)              \
+  V(_TypedList, _setInt8, ByteArrayBaseSetInt8, 0x68f17de8)                    \
+  V(_TypedList, _setUint8, ByteArrayBaseSetInt8, 0x6bb8b747)                   \
+  V(_TypedList, _setInt16, ByteArrayBaseSetInt16, 0x75b8d278)                  \
+  V(_TypedList, _setUint16, ByteArrayBaseSetInt16, 0x6e54f794)                 \
+  V(_TypedList, _setInt32, ByteArrayBaseSetInt32, 0x54123a05)                  \
+  V(_TypedList, _setUint32, ByteArrayBaseSetUint32, 0x4a3fea0b)                \
+  V(_TypedList, _setFloat32, ByteArrayBaseSetFloat32, 0x5a11a2f9)              \
+  V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, 0x0edea58b)              \
+  V(_TypedList, _setFloat32x4, ByteArrayBaseSetFloat32x4, 0x163bc6cc)          \
+  V(_TypedList, _setInt32x4, ByteArrayBaseSetInt32x4, 0x5def39d2)              \
   V(Object, get:runtimeType, ObjectRuntimeType, 0x00e7c26b)
 
 // clang-format on
@@ -540,9 +540,9 @@
 // List of recognized list factories:
 // (factory-name-symbol, result-cid, fingerprint).
 #define RECOGNIZED_LIST_FACTORY_LIST(V)                                        \
-  V(_ListFactory, kArrayCid, 0x63078b15)                                       \
-  V(_GrowableListWithData, kGrowableObjectArrayCid, 0x25a786de)                \
-  V(_GrowableListFactory, kGrowableObjectArrayCid, 0x4f4d4790)                 \
+  V(_ListFactory, kArrayCid, 0x375519ad)                                       \
+  V(_GrowableListWithData, kGrowableObjectArrayCid, 0x401f3150)                \
+  V(_GrowableListFactory, kGrowableObjectArrayCid, 0x0b8d9feb)                 \
   V(_Int8ArrayFactory, kTypedDataInt8ArrayCid, 0x2e7749e3)                     \
   V(_Uint8ArrayFactory, kTypedDataUint8ArrayCid, 0x6ab75439)                   \
   V(_Uint8ClampedArrayFactory, kTypedDataUint8ClampedArrayCid, 0x183129d7)     \
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index b3ae566..14a9b63 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -210,6 +210,28 @@
 }
 
 
+// Remove private keys, but retain getter/setter/constructor/mixin manglings.
+RawString* String::RemovePrivateKey(const String& name) {
+  ASSERT(name.IsOneByteString());
+  GrowableArray<uint8_t> without_key(name.Length());
+  intptr_t i = 0;
+  while (i < name.Length()) {
+    while (i < name.Length()) {
+      uint8_t c = name.CharAt(i++);
+      if (c == '@') break;
+      without_key.Add(c);
+    }
+    while (i < name.Length()) {
+      uint8_t c = name.CharAt(i);
+      if ((c < '0') || (c > '9')) break;
+      i++;
+    }
+  }
+
+  return String::FromLatin1(without_key.data(), without_key.length());
+}
+
+
 // Takes a vm internal name and makes it suitable for external user.
 //
 // Examples:
@@ -7018,28 +7040,8 @@
 // Construct fingerprint from token stream. The token stream contains also
 // arguments.
 int32_t Function::SourceFingerprint() const {
-  uint32_t result = 0;
-  Zone* zone = Thread::Current()->zone();
-  TokenStream::Iterator tokens_iterator(
-      zone, TokenStream::Handle(zone, Script::Handle(zone, script()).tokens()),
-      token_pos());
-  Object& obj = Object::Handle(zone);
-  String& literal = String::Handle(zone);
-  while (tokens_iterator.CurrentPosition() < end_token_pos()) {
-    uint32_t val = 0;
-    obj = tokens_iterator.CurrentToken();
-    if (obj.IsSmi()) {
-      val = Smi::Cast(obj).Value();
-    } else {
-      literal = tokens_iterator.MakeLiteralToken(obj);
-      val = literal.Hash();
-    }
-    result = 31 * result + val;
-    tokens_iterator.Advance();
-  }
-  result = result & ((static_cast<uint32_t>(1) << 31) - 1);
-  ASSERT(result <= static_cast<uint32_t>(kMaxInt32));
-  return result;
+  return Script::Handle(script()).SourceFingerprint(token_pos(),
+                                                    end_token_pos());
 }
 
 
@@ -7139,7 +7141,7 @@
     if (recalculatingFingerprints) {
       // This output can be copied into a file, then used with sed
       // to replace the old values.
-      // sed -i .bak -f /tmp/newkeys runtime/vm/method_recognizer.h
+      // sed -i.bak -f /tmp/newkeys runtime/vm/method_recognizer.h
       THR_Print("s/0x%08x/0x%08x/\n", fp, SourceFingerprint());
     } else {
       THR_Print(
@@ -9002,6 +9004,43 @@
 }
 
 
+int32_t Script::SourceFingerprint() const {
+  return SourceFingerprint(TokenPosition(TokenPosition::kMinSourcePos),
+                           TokenPosition(TokenPosition::kMaxSourcePos));
+}
+
+
+int32_t Script::SourceFingerprint(TokenPosition start,
+                                  TokenPosition end) const {
+  uint32_t result = 0;
+  Zone* zone = Thread::Current()->zone();
+  TokenStream::Iterator tokens_iterator(
+      zone, TokenStream::Handle(zone, tokens()), start);
+  Object& obj = Object::Handle(zone);
+  String& literal = String::Handle(zone);
+  while ((tokens_iterator.CurrentTokenKind() != Token::kEOS) &&
+         (tokens_iterator.CurrentPosition() < end)) {
+    uint32_t val = 0;
+    obj = tokens_iterator.CurrentToken();
+    if (obj.IsSmi()) {
+      val = Smi::Cast(obj).Value();
+    } else {
+      literal = tokens_iterator.MakeLiteralToken(obj);
+      if (tokens_iterator.CurrentTokenKind() == Token::kIDENT ||
+          tokens_iterator.CurrentTokenKind() == Token::kINTERPOL_VAR) {
+        literal = String::RemovePrivateKey(literal);
+      }
+      val = literal.Hash();
+    }
+    result = 31 * result + val;
+    tokens_iterator.Advance();
+  }
+  result = result & ((static_cast<uint32_t>(1) << 31) - 1);
+  ASSERT(result <= static_cast<uint32_t>(kMaxInt32));
+  return result;
+}
+
+
 RawString* Script::GetLine(intptr_t line_number, Heap::Space space) const {
   const String& src = String::Handle(Source());
   if (src.IsNull()) {
@@ -12957,7 +12996,8 @@
 }
 
 void ICData::AddCheck(const GrowableArray<intptr_t>& class_ids,
-                      const Function& target) const {
+                      const Function& target,
+                      intptr_t count) const {
   ASSERT(!target.IsNull());
   ASSERT((target.name() == target_name()) || ValidateInterceptor(target));
   DEBUG_ASSERT(!HasCheck(class_ids));
@@ -13001,7 +13041,7 @@
   }
   ASSERT(!target.IsNull());
   data.SetAt(data_pos++, target);
-  value = Smi::New(1);
+  value = Smi::New(count);
   data.SetAt(data_pos, value);
   // Multithreaded access to ICData requires setting of array to be the last
   // operation.
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 7b73349..f3a4d29 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1506,7 +1506,7 @@
   friend class Object;
   friend class Type;
   friend class Intrinsifier;
-  friend class Precompiler;
+  friend class ProgramVisitor;
 };
 
 
@@ -1974,7 +1974,8 @@
   // Adds one more class test to ICData. Length of 'classes' must be equal to
   // the number of arguments tested. Use only for num_args_tested > 1.
   void AddCheck(const GrowableArray<intptr_t>& class_ids,
-                const Function& target) const;
+                const Function& target,
+                intptr_t count = 1) const;
   // Adds sorted so that Smi is the first class-id. Use only for
   // num_args_tested == 1.
   void AddReceiverCheck(intptr_t receiver_class_id,
@@ -3547,6 +3548,9 @@
                         TokenPosition* first_token_index,
                         TokenPosition* last_token_index) const;
 
+  int32_t SourceFingerprint() const;
+  int32_t SourceFingerprint(TokenPosition start, TokenPosition end) const;
+
   static intptr_t InstanceSize() {
     return RoundedAllocationSize(sizeof(RawScript));
   }
@@ -6902,6 +6906,8 @@
   static RawString* ToLowerCase(const String& str,
                                 Heap::Space space = Heap::kNew);
 
+  static RawString* RemovePrivateKey(const String& name);
+
   static RawString* ScrubName(const String& name);
   static RawString* ScrubNameRetainPrivate(const String& name);
 
diff --git a/runtime/vm/pages.cc b/runtime/vm/pages.cc
index 268bebf..4c7d49d 100644
--- a/runtime/vm/pages.cc
+++ b/runtime/vm/pages.cc
@@ -139,6 +139,8 @@
 
 
 void HeapPage::WriteProtect(bool read_only) {
+  ASSERT(!embedder_allocated());
+
   VirtualMemory::Protection prot;
   if (read_only) {
     if (type_ == kExecutable) {
@@ -1100,7 +1102,13 @@
   if (*first == NULL) {
     *first = page;
   } else {
+    if (is_executable && FLAG_write_protect_code) {
+      (*tail)->WriteProtect(false);
+    }
     (*tail)->set_next(page);
+    if (is_executable && FLAG_write_protect_code) {
+      (*tail)->WriteProtect(true);
+    }
   }
   (*tail) = page;
 }
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 1286d7c..9b87e85 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -70,7 +70,6 @@
             assert_initializer,
             false,
             "Allow asserts in initializer lists.");
-DEFINE_FLAG(bool, assert_message, false, "Allow message in assert statements");
 
 DECLARE_FLAG(bool, profile_vm);
 DECLARE_FLAG(bool, trace_service);
@@ -9165,7 +9164,7 @@
   const TokenPosition condition_pos = TokenPos();
   if (!I->asserts()) {
     SkipExpr();
-    if (FLAG_assert_message && (CurrentToken() == Token::kCOMMA)) {
+    if (CurrentToken() == Token::kCOMMA) {
       ConsumeToken();
       SkipExpr();
     }
@@ -9182,7 +9181,7 @@
   const TokenPosition condition_end = TokenPos();
   AstNode* message = NULL;
   TokenPosition message_pos = TokenPosition::kNoSource;
-  if (FLAG_assert_message && CurrentToken() == Token::kCOMMA) {
+  if (CurrentToken() == Token::kCOMMA) {
     ConsumeToken();
     message_pos = TokenPos();
     message = ParseExpr(kAllowConst, kConsumeCascades);
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc
index e2eb627..e45c04c 100644
--- a/runtime/vm/precompiler.cc
+++ b/runtime/vm/precompiler.cc
@@ -33,6 +33,7 @@
 #include "vm/object_store.h"
 #include "vm/os.h"
 #include "vm/parser.h"
+#include "vm/program_visitor.h"
 #include "vm/redundancy_elimination.h"
 #include "vm/regexp_assembler.h"
 #include "vm/regexp_parser.h"
@@ -42,10 +43,11 @@
 #include "vm/timeline.h"
 #include "vm/timer.h"
 #include "vm/type_table.h"
+#include "vm/version.h"
+#include "vm/json_parser.h"
 
 namespace dart {
 
-
 #define T (thread())
 #define I (isolate())
 #define Z (zone())
@@ -76,6 +78,15 @@
 DECLARE_FLAG(bool, trace_failed_optimization_attempts);
 DECLARE_FLAG(bool, trace_inlining_intervals);
 DECLARE_FLAG(bool, trace_irregexp);
+DECLARE_FLAG(int, inlining_hotness);
+DECLARE_FLAG(int, inlining_size_threshold);
+DECLARE_FLAG(int, inlining_callee_size_threshold);
+DECLARE_FLAG(int, inline_getters_setters_smaller_than);
+DECLARE_FLAG(int, inlining_depth_threshold);
+DECLARE_FLAG(int, inlining_caller_size_threshold);
+DECLARE_FLAG(int, inlining_constant_arguments_max_size_threshold);
+DECLARE_FLAG(int, inlining_constant_arguments_min_size_threshold);
+
 
 #ifdef DART_PRECOMPILER
 
@@ -185,12 +196,37 @@
 }
 
 
+TypeRangeCache::TypeRangeCache(Precompiler* precompiler,
+                               Thread* thread,
+                               intptr_t num_cids)
+    : precompiler_(precompiler),
+      thread_(thread),
+      lower_limits_(thread->zone()->Alloc<intptr_t>(num_cids)),
+      upper_limits_(thread->zone()->Alloc<intptr_t>(num_cids)) {
+  for (intptr_t i = 0; i < num_cids; i++) {
+    lower_limits_[i] = kNotComputed;
+    upper_limits_[i] = kNotComputed;
+  }
+  ASSERT(precompiler->type_range_cache() == NULL);
+  precompiler->set_type_range_cache(this);
+}
+
+
+TypeRangeCache::~TypeRangeCache() {
+  ASSERT(precompiler_->type_range_cache() == this);
+  precompiler_->set_type_range_cache(NULL);
+}
+
+
 RawError* Precompiler::CompileAll(
     Dart_QualifiedFunctionName embedder_entry_points[],
-    bool reset_fields) {
+    bool reset_fields,
+    uint8_t* jit_feedback,
+    intptr_t jit_feedback_length) {
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
     Precompiler precompiler(Thread::Current(), reset_fields);
+    precompiler.LoadFeedback(jit_feedback, jit_feedback_length);
     precompiler.DoCompileAll(embedder_entry_points);
     return Error::null();
   } else {
@@ -294,6 +330,7 @@
       zone_(NULL),
       isolate_(thread->isolate()),
       reset_fields_(reset_fields),
+      jit_feedback_(NULL),
       changed_(false),
       function_count_(0),
       class_count_(0),
@@ -316,10 +353,52 @@
       types_to_retain_(),
       consts_to_retain_(),
       field_type_map_(),
+      type_range_cache_(NULL),
       error_(Error::Handle()),
       get_runtime_type_is_unique_(false) {}
 
 
+void Precompiler::LoadFeedback(uint8_t* buffer, intptr_t length) {
+  if (buffer == NULL) {
+    if (FLAG_trace_precompiler) {
+      THR_Print("Precompiler running without JIT feedback\n");
+    }
+
+    // Flags affecting compilation only:
+    // There is no counter feedback in precompilation, so ignore the counter
+    // when making inlining decisions.
+    FLAG_inlining_hotness = 0;
+    // Use smaller thresholds in precompilation as we are compiling everything
+    // with the optimizing compiler instead of only hot functions.
+    FLAG_inlining_size_threshold = 5;
+    FLAG_inline_getters_setters_smaller_than = 5;
+    FLAG_inlining_callee_size_threshold = 20;
+    FLAG_inlining_depth_threshold = 4;
+    FLAG_inlining_caller_size_threshold = 1000;
+    FLAG_inlining_constant_arguments_max_size_threshold = 100;
+    FLAG_inlining_constant_arguments_min_size_threshold = 30;
+    return;
+  }
+
+  if (FLAG_trace_precompiler) {
+    THR_Print("Loading JIT feedback\n");
+  }
+
+  JSONParser parser(reinterpret_cast<const char*>(buffer), length,
+                    Thread::Current()->zone());
+  ParsedJSONValue* root = parser.ParseValue();
+  if (root->IsError()) {
+    ParsedJSONError* error = static_cast<ParsedJSONError*>(root);
+    THR_Print("Error parsing JIT feedback: %s:%" Pd "\n", error->message(),
+              error->position());
+  } else if (!root->IsObject()) {
+    THR_Print("Error parsing JIT feedback: object expected\n");
+  } else {
+    jit_feedback_ = static_cast<ParsedJSONObject*>(root);
+  }
+}
+
+
 void Precompiler::DoCompileAll(
     Dart_QualifiedFunctionName embedder_entry_points[]) {
   ASSERT(I->compilation_allowed());
@@ -336,7 +415,8 @@
       FinalizeAllClasses();
 
       SortClasses();
-      TypeRangeCache trc(T, I->class_table()->NumCids());
+      TypeRangeCache trc(this, T, I->class_table()->NumCids());
+      VerifyJITFeedback();
 
       // Precompile static initializers to compute result type information.
       PrecompileStaticInitializers();
@@ -478,7 +558,7 @@
 
   HANDLESCOPE(T);
   StaticInitializerVisitor visitor(Z);
-  VisitClasses(&visitor);
+  ProgramVisitor::VisitClasses(&visitor);
 }
 
 
@@ -508,7 +588,7 @@
 
   HANDLESCOPE(T);
   ConstructorVisitor visitor(this, zone_);
-  VisitFunctions(&visitor);
+  ProgramVisitor::VisitFunctions(&visitor);
 
   FieldTypeMap::Iterator it(field_type_map_.GetIterator());
   for (FieldTypePair* current = it.Next(); current != NULL;
@@ -533,13 +613,13 @@
     }
   };
   ClearCodeFunctionVisitor function_visitor;
-  VisitFunctions(&function_visitor);
+  ProgramVisitor::VisitFunctions(&function_visitor);
 
   class ClearCodeClassVisitor : public ClassVisitor {
     void Visit(const Class& cls) { cls.DisableAllocationStub(); }
   };
   ClearCodeClassVisitor class_visitor;
-  VisitClasses(&class_visitor);
+  ProgramVisitor::VisitClasses(&class_visitor);
 }
 
 
@@ -2081,7 +2161,7 @@
   };
 
   BindStaticCallsVisitor visitor(Z);
-  VisitFunctions(&visitor);
+  ProgramVisitor::VisitFunctions(&visitor);
 }
 
 
@@ -2170,7 +2250,7 @@
 
   ASSERT(!I->compilation_allowed());
   SwitchICCallsVisitor visitor(Z);
-  VisitFunctions(&visitor);
+  ProgramVisitor::VisitFunctions(&visitor);
 #endif
 }
 
@@ -2243,7 +2323,7 @@
   };
 
   DedupStackMapsVisitor visitor(Z);
-  VisitFunctions(&visitor);
+  ProgramVisitor::VisitFunctions(&visitor);
 }
 
 
@@ -2310,7 +2390,7 @@
   };
 
   DedupListsVisitor visitor(Z);
-  VisitFunctions(&visitor);
+  ProgramVisitor::VisitFunctions(&visitor);
 }
 
 
@@ -2356,81 +2436,7 @@
   };
 
   DedupInstructionsVisitor visitor(Z);
-  VisitFunctions(&visitor);
-}
-
-
-void Precompiler::VisitClasses(ClassVisitor* visitor) {
-  Library& lib = Library::Handle(Z);
-  Class& cls = Class::Handle(Z);
-
-  for (intptr_t i = 0; i < libraries_.Length(); i++) {
-    lib ^= libraries_.At(i);
-    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
-    while (it.HasNext()) {
-      cls = it.GetNextClass();
-      if (cls.IsDynamicClass()) {
-        continue;  // class 'dynamic' is in the read-only VM isolate.
-      }
-      visitor->Visit(cls);
-    }
-  }
-}
-
-
-void Precompiler::VisitFunctions(FunctionVisitor* visitor) {
-  Library& lib = Library::Handle(Z);
-  Class& cls = Class::Handle(Z);
-  Array& functions = Array::Handle(Z);
-  Array& fields = Array::Handle(Z);
-  Field& field = Field::Handle(Z);
-  Object& object = Object::Handle(Z);
-  Function& function = Function::Handle(Z);
-  GrowableObjectArray& closures = GrowableObjectArray::Handle(Z);
-
-  for (intptr_t i = 0; i < libraries_.Length(); i++) {
-    lib ^= libraries_.At(i);
-    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
-    while (it.HasNext()) {
-      cls = it.GetNextClass();
-      if (cls.IsDynamicClass()) {
-        continue;  // class 'dynamic' is in the read-only VM isolate.
-      }
-
-      functions = cls.functions();
-      for (intptr_t j = 0; j < functions.Length(); j++) {
-        function ^= functions.At(j);
-        visitor->Visit(function);
-        if (function.HasImplicitClosureFunction()) {
-          function = function.ImplicitClosureFunction();
-          visitor->Visit(function);
-        }
-      }
-
-      functions = cls.invocation_dispatcher_cache();
-      for (intptr_t j = 0; j < functions.Length(); j++) {
-        object = functions.At(j);
-        if (object.IsFunction()) {
-          function ^= functions.At(j);
-          visitor->Visit(function);
-        }
-      }
-      fields = cls.fields();
-      for (intptr_t j = 0; j < fields.Length(); j++) {
-        field ^= fields.At(j);
-        if (field.is_static() && field.HasPrecompiledInitializer()) {
-          function ^= field.PrecompiledInitializer();
-          visitor->Visit(function);
-        }
-      }
-    }
-  }
-  closures = isolate()->object_store()->closure_functions();
-  for (intptr_t j = 0; j < closures.Length(); j++) {
-    function ^= closures.At(j);
-    visitor->Visit(function);
-    ASSERT(!function.HasImplicitClosureFunction());
-  }
+  ProgramVisitor::VisitFunctions(&visitor);
 }
 
 
@@ -2607,6 +2613,342 @@
 }
 
 
+void Precompiler::VerifyJITFeedback() {
+  if (jit_feedback_ == NULL) return;
+
+  ParsedJSONString* js_vmversion = jit_feedback_->StringAt("vmVersion");
+  if ((js_vmversion == NULL) ||
+      strcmp(js_vmversion->value(), Version::CommitString()) != 0) {
+    THR_Print(
+        "JIT feedback contains invalid vm version "
+        "(saw %s, expected %s).\n",
+        js_vmversion->value(), Version::CommitString());
+    jit_feedback_ = NULL;
+    return;
+  }
+  ParsedJSONBoolean* js_asserts = jit_feedback_->BooleanAt("asserts");
+  if ((js_asserts == NULL) || (FLAG_enable_asserts != js_asserts->value())) {
+    THR_Print("JIT feedback contains invalid FLAG_enable_asserts\n");
+    jit_feedback_ = NULL;
+    return;
+  }
+  ParsedJSONBoolean* js_typechecks = jit_feedback_->BooleanAt("typeChecks");
+  if ((js_typechecks == NULL) ||
+      (FLAG_enable_type_checks != js_typechecks->value())) {
+    THR_Print("JIT feedback contains invalid FLAG_enable_type_checks\n");
+    jit_feedback_ = NULL;
+    return;
+  }
+
+  ParsedJSONArray* js_scripts = jit_feedback_->ArrayAt("scripts");
+  ASSERT(js_scripts != NULL);
+  Script& script = Script::Handle(Z);
+  for (intptr_t i = 0; i < js_scripts->Length(); i++) {
+    ParsedJSONObject* js_script = js_scripts->ObjectAt(i);
+    ASSERT(js_script != NULL);
+    ParsedJSONString* js_uri = js_script->StringAt("uri");
+    ASSERT(js_uri != NULL);
+    ParsedJSONNumber* js_fp = js_script->NumberAt("checksum");
+    ASSERT(js_fp != NULL);
+    script = LookupScript(js_uri->value());
+    if (script.IsNull()) {
+      THR_Print("Cannot find script %s\n", js_uri->value());
+      continue;
+    }
+    intptr_t fp = script.SourceFingerprint();
+    if (fp != js_fp->value()) {
+      THR_Print(
+          "Fingerprint has changed for %s. Continuing without JIT "
+          "feedback.\n",
+          js_uri->value());
+      jit_feedback_ = NULL;
+      return;
+    }
+  }
+
+  ParsedJSONArray* js_classes = jit_feedback_->ArrayAt("classes");
+  ASSERT(js_classes != NULL);
+  Library& lib = Library::Handle(Z);
+  Class& cls = Class::Handle(Z);
+  String& str = String::Handle(Z);
+  for (intptr_t i = 0; i < js_classes->Length(); i++) {
+    ParsedJSONObject* js_class = js_classes->ObjectAt(i);
+    ASSERT(js_class != NULL);
+    ParsedJSONString* js_uri = js_class->StringAt("uri");
+    ASSERT(js_uri != NULL);
+    ParsedJSONString* js_name = js_class->StringAt("name");
+    ASSERT(js_name != NULL);
+    ParsedJSONNumber* js_cid = js_class->NumberAt("cid");
+    ASSERT(js_cid != NULL);
+
+    str = String::New(js_uri->value());
+    lib = Library::LookupLibrary(T, str);
+    if (lib.IsNull()) {
+      THR_Print("Cannot find library %s\n", js_uri->value());
+      continue;
+    }
+    str = String::New(js_name->value());
+    if (str.Equals(Symbols::TopLevel())) {
+      cls = lib.toplevel_class();
+    } else {
+      cls = lib.LookupClassAllowPrivate(str);
+    }
+    if (cls.IsNull()) {
+      THR_Print("Missing class %s\n", js_name->value());
+      continue;
+    }
+
+    feedback_cid_map_.Insert(IntptrPair(js_cid->value(), cls.id()));
+  }
+
+  ParsedJSONArray* js_functions = jit_feedback_->ArrayAt("functions");
+  ASSERT(js_functions != NULL);
+  for (intptr_t i = 0; i < js_functions->Length(); i++) {
+    ParsedJSONObject* js_function = js_functions->ObjectAt(i);
+    ASSERT(js_function != NULL);
+    ParsedJSONString* js_name = js_function->StringAt("name");
+    ASSERT(js_name != NULL);
+    ParsedJSONNumber* js_cid = js_function->NumberAt("class");
+    ASSERT(js_cid != NULL);
+    ParsedJSONNumber* js_token = js_function->NumberAt("tokenPos");
+    ASSERT(js_token != NULL);
+    ParsedJSONNumber* js_kind = js_function->NumberAt("kind");
+    ASSERT(js_kind != NULL);
+    function_feedback_map_.Insert(FunctionFeedbackPair(
+        FunctionFeedbackKey(MapCid(js_cid->value()), js_token->value(),
+                            js_kind->value()),
+        js_function));
+  }
+
+  class ApplyUsageVisitor : public FunctionVisitor {
+   public:
+    explicit ApplyUsageVisitor(Precompiler* precompiler)
+        : precompiler_(precompiler) {}
+    void Visit(const Function& function) {
+      ParsedJSONObject* js_function = precompiler_->LookupFeedback(function);
+      if (js_function == NULL) {
+        function.set_usage_counter(0);
+      } else {
+        ParsedJSONNumber* js_usage = js_function->NumberAt("usageCounter");
+        ASSERT(js_usage != NULL);
+        function.set_usage_counter(js_usage->value());
+      }
+    }
+
+   private:
+    Precompiler* precompiler_;
+  };
+
+  ApplyUsageVisitor visitor(this);
+  ProgramVisitor::VisitFunctions(&visitor);
+}
+
+
+ParsedJSONObject* Precompiler::LookupFeedback(const Function& function) {
+  const Class& owner = Class::Handle(Z, function.Owner());
+
+  FunctionFeedbackKey key(owner.id(), function.token_pos().value(),
+                          function.kind());
+  FunctionFeedbackPair* pair = function_feedback_map_.Lookup(key);
+  if (pair == NULL) {
+    return NULL;
+  }
+  return pair->value_;
+}
+
+
+RawScript* Precompiler::LookupScript(const char* uri) {
+  String& dart_uri = String::Handle(Z, String::New(uri));
+  Library& lib = Library::Handle(Z);
+  Script& script = Script::Handle(Z);
+  for (intptr_t i = 0; i < libraries_.Length(); i++) {
+    lib ^= libraries_.At(i);
+    script = lib.LookupScript(dart_uri);
+    if (!script.IsNull()) {
+      return script.raw();
+    }
+  }
+  return Script::null();
+}
+
+
+intptr_t Precompiler::MapCid(intptr_t feedback_cid) {
+  if (feedback_cid < kNumPredefinedCids) {
+    return feedback_cid;
+  }
+  IntptrPair* pair = feedback_cid_map_.Lookup(feedback_cid);
+  if (pair == NULL) return kIllegalCid;
+  return pair->value_;
+}
+
+
+void Precompiler::PopulateWithICData(const Function& function,
+                                     FlowGraph* graph) {
+  Zone* zone = Thread::Current()->zone();
+
+  for (BlockIterator block_it = graph->reverse_postorder_iterator();
+       !block_it.Done(); block_it.Advance()) {
+    ForwardInstructionIterator it(block_it.Current());
+    for (; !it.Done(); it.Advance()) {
+      Instruction* instr = it.Current();
+      if (instr->IsInstanceCall()) {
+        InstanceCallInstr* call = instr->AsInstanceCall();
+        if (!call->HasICData()) {
+          const Array& arguments_descriptor = Array::Handle(
+              zone, ArgumentsDescriptor::New(call->ArgumentCount(),
+                                             call->argument_names()));
+          const ICData& ic_data = ICData::ZoneHandle(
+              zone, ICData::New(function, call->function_name(),
+                                arguments_descriptor, call->deopt_id(),
+                                call->checked_argument_count(), false));
+          call->set_ic_data(&ic_data);
+        }
+      } else if (instr->IsStaticCall()) {
+        StaticCallInstr* call = instr->AsStaticCall();
+        if (!call->HasICData()) {
+          const Array& arguments_descriptor = Array::Handle(
+              zone, ArgumentsDescriptor::New(call->ArgumentCount(),
+                                             call->argument_names()));
+          const Function& target = call->function();
+          MethodRecognizer::Kind recognized_kind =
+              MethodRecognizer::RecognizeKind(target);
+          int num_args_checked = 0;
+          switch (recognized_kind) {
+            case MethodRecognizer::kDoubleFromInteger:
+            case MethodRecognizer::kMathMin:
+            case MethodRecognizer::kMathMax:
+              num_args_checked = 2;
+              break;
+            default:
+              break;
+          }
+          const ICData& ic_data = ICData::ZoneHandle(
+              zone, ICData::New(function, String::Handle(zone, target.name()),
+                                arguments_descriptor, call->deopt_id(),
+                                num_args_checked, true));
+          ic_data.AddTarget(target);
+          call->set_ic_data(&ic_data);
+        }
+      }
+    }
+  }
+}
+
+
+void Precompiler::TryApplyFeedback(const Function& function, FlowGraph* graph) {
+  ParsedJSONObject* js_function = LookupFeedback(function);
+  if (js_function == NULL) {
+    if (FLAG_trace_precompiler) {
+      THR_Print("No feedback available for %s\n",
+                function.ToQualifiedCString());
+    }
+    return;
+  }
+
+  ParsedJSONArray* js_icdatas = js_function->ArrayAt("ics");
+  ASSERT(js_icdatas != NULL);
+
+  for (BlockIterator block_it = graph->reverse_postorder_iterator();
+       !block_it.Done(); block_it.Advance()) {
+    ForwardInstructionIterator it(block_it.Current());
+    for (; !it.Done(); it.Advance()) {
+      Instruction* instr = it.Current();
+      if (instr->IsInstanceCall()) {
+        InstanceCallInstr* call = instr->AsInstanceCall();
+        TryApplyFeedback(js_icdatas, *call->ic_data());
+      } else if (instr->IsStaticCall()) {
+        StaticCallInstr* call = instr->AsStaticCall();
+        TryApplyFeedback(js_icdatas, *call->ic_data());
+      }
+    }
+  }
+}
+
+
+void Precompiler::TryApplyFeedback(ParsedJSONArray* js_icdatas,
+                                   const ICData& ic) {
+  for (intptr_t j = 0; j < js_icdatas->Length(); j++) {
+    ParsedJSONObject* js_icdata = js_icdatas->ObjectAt(j);
+    ASSERT(js_icdata != NULL);
+
+    ParsedJSONNumber* js_deoptid = js_icdata->NumberAt("deoptId");
+    ASSERT(js_deoptid != NULL);
+    if (js_deoptid->value() != ic.deopt_id()) continue;
+
+    ParsedJSONBoolean* js_isstaticcall = js_icdata->BooleanAt("isStaticCall");
+    ASSERT(js_isstaticcall != NULL);
+    if (js_isstaticcall->value() != ic.is_static_call()) return;
+
+    ParsedJSONNumber* js_argsTested = js_icdata->NumberAt("argsTested");
+    ASSERT(js_argsTested != NULL);
+    if (js_argsTested->value() != ic.NumArgsTested()) return;
+
+    ParsedJSONString* js_selector = js_icdata->StringAt("selector");
+    ASSERT(js_selector != NULL);
+    const String& feedback_selector =
+        String::Handle(String::New(js_selector->value()));
+    const String& selector = String::Handle(ic.target_name());
+    // N.B.: EqualsIgnoringPrivateKey is not symmetric.
+    if (!String::EqualsIgnoringPrivateKey(selector, feedback_selector)) return;
+
+    ParsedJSONArray* js_entries = js_icdata->ArrayAt("entries");
+    ASSERT(js_entries != NULL);
+    if (ic.is_static_call()) {
+      // [cid [cid]] target count
+      ParsedJSONNumber* entry = js_entries->NumberAt(js_entries->Length() - 1);
+      ASSERT(entry != NULL);
+      ic.SetCountAt(0, entry->value());
+    } else {
+      // [cid [cid [cid]]] target count
+      const Array& arguments_descriptor =
+          Array::Handle(ic.arguments_descriptor());
+      ArgumentsDescriptor args_desc(arguments_descriptor);
+
+      intptr_t num_args_checked = ic.NumArgsTested();
+      for (intptr_t k = 0; k < js_entries->Length();
+           k += num_args_checked + 1) {
+        GrowableArray<intptr_t> class_ids(num_args_checked);
+        for (intptr_t arg = 0; arg < num_args_checked; arg++) {
+          ParsedJSONNumber* entry = js_entries->NumberAt(k + arg);
+          ASSERT(entry != NULL);
+          class_ids.Add(MapCid(entry->value()));
+        }
+        ParsedJSONNumber* entry = js_entries->NumberAt(k + num_args_checked);
+        ASSERT(entry != NULL);
+        intptr_t count = entry->value();
+
+        bool has_missing_cid = false;
+        for (intptr_t arg = 0; arg < num_args_checked; arg++) {
+          if (class_ids[arg] == kIllegalCid) {
+            has_missing_cid = true;
+          }
+        }
+        if (has_missing_cid) continue;
+
+        intptr_t receiver_cid = class_ids[0];
+        const Class& receiver_cls =
+            Class::Handle(I->class_table()->At(receiver_cid));
+        if (receiver_cls.IsClass()) {
+          const Function& target =
+              Function::Handle(Resolver::ResolveDynamicForReceiverClass(
+                  receiver_cls, selector, args_desc, false));
+          // TODO(rmacnak): Create missing dispatchers.
+          if (!target.IsNull()) {
+            if (num_args_checked == 1) {
+              ic.AddReceiverCheck(receiver_cid, target, count);
+            } else {
+              ic.AddCheck(class_ids, target, count);
+            }
+          }
+        }
+      }
+    }
+
+    return;
+  }
+}
+
+
 void Precompiler::ResetPrecompilerState() {
   changed_ = false;
   function_count_ = 0;
@@ -2757,6 +3099,15 @@
             zone, parsed_function(), *ic_data_array, Compiler::kNoOSRDeoptId);
       }
 
+      if (optimized()) {
+        Precompiler::PopulateWithICData(parsed_function()->function(),
+                                        flow_graph);
+        if (precompiler_ != NULL) {
+          precompiler_->TryApplyFeedback(parsed_function()->function(),
+                                         flow_graph);
+        }
+      }
+
       const bool print_flow_graph =
           (FLAG_print_flow_graph ||
            (optimized() && FLAG_print_flow_graph_optimized)) &&
@@ -2807,7 +3158,6 @@
 
         AotOptimizer optimizer(precompiler_, flow_graph,
                                use_speculative_inlining, &inlining_black_list);
-        optimizer.PopulateWithICData();
 
         optimizer.ApplyClassIds();
         DEBUG_ASSERT(flow_graph->VerifyUseLists());
diff --git a/runtime/vm/precompiler.h b/runtime/vm/precompiler.h
index b763363..f4af735 100644
--- a/runtime/vm/precompiler.h
+++ b/runtime/vm/precompiler.h
@@ -21,28 +21,15 @@
 class RawError;
 class SequenceNode;
 class String;
+class ParsedJSONObject;
+class ParsedJSONArray;
+class Precompiler;
+class FlowGraph;
 
-
-class TypeRangeCache : public StackResource {
+class TypeRangeCache : public ValueObject {
  public:
-  TypeRangeCache(Thread* thread, intptr_t num_cids)
-      : StackResource(thread),
-        thread_(thread),
-        lower_limits_(thread->zone()->Alloc<intptr_t>(num_cids)),
-        upper_limits_(thread->zone()->Alloc<intptr_t>(num_cids)) {
-    for (intptr_t i = 0; i < num_cids; i++) {
-      lower_limits_[i] = kNotComputed;
-      upper_limits_[i] = kNotComputed;
-    }
-    // We don't re-enter the precompiler.
-    ASSERT(thread->type_range_cache() == NULL);
-    thread->set_type_range_cache(this);
-  }
-
-  ~TypeRangeCache() {
-    ASSERT(thread_->type_range_cache() == this);
-    thread_->set_type_range_cache(NULL);
-  }
+  TypeRangeCache(Precompiler* precompiler, Thread* thread, intptr_t num_cids);
+  ~TypeRangeCache();
 
   bool InstanceOfHasClassRange(const AbstractType& type,
                                intptr_t* lower_limit,
@@ -52,6 +39,7 @@
   static const intptr_t kNotComputed = -1;
   static const intptr_t kNotContiguous = -2;
 
+  Precompiler* precompiler_;
   Thread* thread_;
   intptr_t* lower_limits_;
   intptr_t* upper_limits_;
@@ -328,11 +316,79 @@
 typedef DirectChainedHashMap<FieldTypePair> FieldTypeMap;
 
 
+struct IntptrPair {
+  // Typedefs needed for the DirectChainedHashMap template.
+  typedef intptr_t Key;
+  typedef intptr_t Value;
+  typedef IntptrPair Pair;
+
+  static Key KeyOf(Pair kv) { return kv.key_; }
+
+  static Value ValueOf(Pair kv) { return kv.value_; }
+
+  static inline intptr_t Hashcode(Key key) { return key; }
+
+  static inline bool IsKeyEqual(Pair pair, Key key) { return pair.key_ == key; }
+
+  IntptrPair(intptr_t key, intptr_t value) : key_(key), value_(value) {}
+
+  IntptrPair() : key_(kIllegalCid), value_(kIllegalCid) {}
+
+  Key key_;
+  Value value_;
+};
+
+typedef DirectChainedHashMap<IntptrPair> CidMap;
+
+
+struct FunctionFeedbackKey {
+  FunctionFeedbackKey() : owner_cid_(kIllegalCid), token_(0), kind_(0) {}
+  FunctionFeedbackKey(intptr_t owner_cid, intptr_t token, intptr_t kind)
+      : owner_cid_(owner_cid), token_(token), kind_(kind) {}
+
+  intptr_t owner_cid_;
+  intptr_t token_;
+  intptr_t kind_;
+};
+
+
+struct FunctionFeedbackPair {
+  // Typedefs needed for the DirectChainedHashMap template.
+  typedef FunctionFeedbackKey Key;
+  typedef ParsedJSONObject* Value;
+  typedef FunctionFeedbackPair Pair;
+
+  static Key KeyOf(Pair kv) { return kv.key_; }
+
+  static Value ValueOf(Pair kv) { return kv.value_; }
+
+  static inline intptr_t Hashcode(Key key) {
+    return key.token_ ^ key.owner_cid_ ^ key.kind_;
+  }
+
+  static inline bool IsKeyEqual(Pair pair, Key key) {
+    return (pair.key_.owner_cid_ == key.owner_cid_) &&
+           (pair.key_.token_ == key.token_) && (pair.key_.kind_ == key.kind_);
+  }
+
+  FunctionFeedbackPair(Key key, Value value) : key_(key), value_(value) {}
+
+  FunctionFeedbackPair() : key_(), value_(NULL) {}
+
+  Key key_;
+  Value value_;
+};
+
+typedef DirectChainedHashMap<FunctionFeedbackPair> FunctionFeedbackMap;
+
+
 class Precompiler : public ValueObject {
  public:
   static RawError* CompileAll(
       Dart_QualifiedFunctionName embedder_entry_points[],
-      bool reset_fields);
+      bool reset_fields,
+      uint8_t* jit_feedback,
+      intptr_t jit_feedback_length);
 
   static RawError* CompileFunction(Precompiler* precompiler,
                                    Thread* thread,
@@ -352,10 +408,22 @@
   }
 
   FieldTypeMap* field_type_map() { return &field_type_map_; }
+  TypeRangeCache* type_range_cache() { return type_range_cache_; }
+  void set_type_range_cache(TypeRangeCache* value) {
+    type_range_cache_ = value;
+  }
+
+  bool HasFeedback() const { return jit_feedback_ != NULL; }
+  static void PopulateWithICData(const Function& func, FlowGraph* graph);
+  void TryApplyFeedback(const Function& func, FlowGraph* graph);
+  void TryApplyFeedback(ParsedJSONArray* js_icdatas, const ICData& ic);
 
  private:
   Precompiler(Thread* thread, bool reset_fields);
 
+  void LoadFeedback(uint8_t* jit_feedback, intptr_t jit_feedback_length);
+  ParsedJSONObject* LookupFeedback(const Function& function);
+
   void DoCompileAll(Dart_QualifiedFunctionName embedder_entry_points[]);
   void ClearAllCode();
   void AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]);
@@ -403,21 +471,12 @@
   void PrecompileStaticInitializers();
   void PrecompileConstructors();
 
-  template <typename T>
-  class Visitor : public ValueObject {
-   public:
-    virtual ~Visitor() {}
-    virtual void Visit(const T& obj) = 0;
-  };
-  typedef Visitor<Function> FunctionVisitor;
-  typedef Visitor<Class> ClassVisitor;
-
-  void VisitFunctions(FunctionVisitor* visitor);
-  void VisitClasses(ClassVisitor* visitor);
-
   void FinalizeAllClasses();
   void SortClasses();
   void RemapClassIds(intptr_t* old_to_new_cid);
+  void VerifyJITFeedback();
+  RawScript* LookupScript(const char* uri);
+  intptr_t MapCid(intptr_t feedback_cid);
 
   Thread* thread() const { return thread_; }
   Zone* zone() const { return zone_; }
@@ -429,6 +488,8 @@
 
   const bool reset_fields_;
 
+  ParsedJSONObject* jit_feedback_;
+
   bool changed_;
   intptr_t function_count_;
   intptr_t class_count_;
@@ -451,6 +512,9 @@
   AbstractTypeSet types_to_retain_;
   InstanceSet consts_to_retain_;
   FieldTypeMap field_type_map_;
+  TypeRangeCache* type_range_cache_;
+  CidMap feedback_cid_map_;
+  FunctionFeedbackMap function_feedback_map_;
   Error& error_;
 
   bool get_runtime_type_is_unique_;
diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc
new file mode 100644
index 0000000..4a41925
--- /dev/null
+++ b/runtime/vm/program_visitor.cc
@@ -0,0 +1,95 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/program_visitor.h"
+
+#include "vm/object.h"
+#include "vm/object_store.h"
+
+namespace dart {
+
+void ProgramVisitor::VisitClasses(ClassVisitor* visitor) {
+  Thread* thread = Thread::Current();
+  Isolate* isolate = thread->isolate();
+  Zone* zone = thread->zone();
+  GrowableObjectArray& libraries =
+      GrowableObjectArray::Handle(zone, isolate->object_store()->libraries());
+  Library& lib = Library::Handle(zone);
+  Class& cls = Class::Handle(zone);
+
+  for (intptr_t i = 0; i < libraries.Length(); i++) {
+    lib ^= libraries.At(i);
+    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
+    while (it.HasNext()) {
+      cls = it.GetNextClass();
+      if (cls.IsDynamicClass()) {
+        continue;  // class 'dynamic' is in the read-only VM isolate.
+      }
+      visitor->Visit(cls);
+    }
+  }
+}
+
+
+void ProgramVisitor::VisitFunctions(FunctionVisitor* visitor) {
+  Thread* thread = Thread::Current();
+  Isolate* isolate = thread->isolate();
+  Zone* zone = thread->zone();
+  GrowableObjectArray& libraries =
+      GrowableObjectArray::Handle(zone, isolate->object_store()->libraries());
+  Library& lib = Library::Handle(zone);
+  Class& cls = Class::Handle(zone);
+  Array& functions = Array::Handle(zone);
+  Array& fields = Array::Handle(zone);
+  Field& field = Field::Handle(zone);
+  Object& object = Object::Handle(zone);
+  Function& function = Function::Handle(zone);
+  GrowableObjectArray& closures = GrowableObjectArray::Handle(zone);
+
+  for (intptr_t i = 0; i < libraries.Length(); i++) {
+    lib ^= libraries.At(i);
+    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
+    while (it.HasNext()) {
+      cls = it.GetNextClass();
+      if (cls.IsDynamicClass()) {
+        continue;  // class 'dynamic' is in the read-only VM isolate.
+      }
+
+      functions = cls.functions();
+      for (intptr_t j = 0; j < functions.Length(); j++) {
+        function ^= functions.At(j);
+        visitor->Visit(function);
+        if (function.HasImplicitClosureFunction()) {
+          function = function.ImplicitClosureFunction();
+          visitor->Visit(function);
+        }
+      }
+
+      functions = cls.invocation_dispatcher_cache();
+      for (intptr_t j = 0; j < functions.Length(); j++) {
+        object = functions.At(j);
+        if (object.IsFunction()) {
+          function ^= functions.At(j);
+          visitor->Visit(function);
+        }
+      }
+      fields = cls.fields();
+      for (intptr_t j = 0; j < fields.Length(); j++) {
+        field ^= fields.At(j);
+        if (field.is_static() && field.HasPrecompiledInitializer()) {
+          function ^= field.PrecompiledInitializer();
+          visitor->Visit(function);
+        }
+      }
+    }
+  }
+  closures = isolate->object_store()->closure_functions();
+  for (intptr_t j = 0; j < closures.Length(); j++) {
+    function ^= closures.At(j);
+    visitor->Visit(function);
+    ASSERT(!function.HasImplicitClosureFunction());
+  }
+}
+
+}  // namespace dart
diff --git a/runtime/vm/program_visitor.h b/runtime/vm/program_visitor.h
new file mode 100644
index 0000000..5ac8130
--- /dev/null
+++ b/runtime/vm/program_visitor.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_VM_PROGRAM_VISITOR_H_
+#define RUNTIME_VM_PROGRAM_VISITOR_H_
+
+#include "vm/allocation.h"
+
+namespace dart {
+
+class Function;
+class Class;
+
+template <typename T>
+class Visitor : public ValueObject {
+ public:
+  virtual ~Visitor() {}
+  virtual void Visit(const T& obj) = 0;
+};
+
+typedef Visitor<Function> FunctionVisitor;
+typedef Visitor<Class> ClassVisitor;
+
+class ProgramVisitor : public AllStatic {
+ public:
+  static void VisitFunctions(FunctionVisitor* visitor);
+  static void VisitClasses(ClassVisitor* visitor);
+};
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_PROGRAM_VISITOR_H_
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index dea082a..b114dc6 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -3554,19 +3554,13 @@
 
   {
     BYTECODE(Deopt, A_D);
+
+    // Note: frame translation will take care of preserving result at the
+    // top of the stack. See CompilerDeoptInfo::CreateDeoptInfo.
     const bool is_lazy = rD == 0;
 
-    // Preserve result of the previous call.
-    // TODO(vegorov) we could have actually included result into the
-    // deoptimization environment because it is passed through the stack.
-    // If we do then we could remove special result handling from this code.
-    RawObject* result = SP[0];
-
-    // When not preserving the result, we still need to preserve SP[0] as it
-    // contains some temporary expression.
-    if (!is_lazy) {
-      SP++;
-    }
+    // Make sure we preserve SP[0] when entering synthetic frame below.
+    SP++;
 
     // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame.
     // The code in this frame may not cause GC.
@@ -3582,9 +3576,6 @@
 
     // We are now inside a valid frame.
     {
-      if (is_lazy) {
-        *++SP = result;  // Preserve result (call below can cause GC).
-      }
       *++SP = 0;  // Space for the result: number of materialization args.
       Exit(thread, FP, SP + 1, /*pc=*/0);
       NativeArguments native_args(thread, 0, SP, SP);
@@ -3592,10 +3583,6 @@
     }
     const intptr_t materialization_arg_count =
         Smi::Value(RAW_CAST(Smi, *SP--)) / kWordSize;
-    if (is_lazy) {
-      // Reload the result. It might have been relocated by GC.
-      result = *SP--;
-    }
 
     // Restore caller PC.
     pc = SavedCallerPC(FP);
@@ -3604,21 +3591,13 @@
     // Check if it is a fake PC marking the entry frame.
     ASSERT((reinterpret_cast<uword>(pc) & 2) == 0);
 
-    // Restore SP, FP and PP. Push result and dispatch.
-    // Note: unlike in a normal return sequence we don't need to drop
-    // arguments - those are not part of the innermost deoptimization
-    // environment they were dropped by FlowGraphCompiler::RecordAfterCall.
-
-    // If the result is not preserved, the unoptimized frame ends at the
-    // next slot.
-    SP = FrameArguments(FP, materialization_arg_count);
+    // Restore SP, FP and PP.
+    // Unoptimized frame SP is one below FrameArguments(...) because
+    // FrameArguments(...) returns a pointer to the first argument.
+    SP = FrameArguments(FP, materialization_arg_count) - 1;
     FP = SavedCallerFP(FP);
     pp = SimulatorHelpers::FrameCode(FP)->ptr()->object_pool_->ptr();
-    if (is_lazy) {
-      SP[0] = result;  // Put the result on the stack.
-    } else {
-      SP--;  // No result to push.
-    }
+
     DISPATCH();
   }
 
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 81c4342..79b5b1b 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -1399,47 +1399,6 @@
     Dart_ExitScope();
     Dart_ShutdownIsolate();
   }
-  free(script_snapshot);
-
-  // Test for Dart_CreateLibrarySnapshot.
-  {
-    // Create an Isolate using the full snapshot, load a script and create
-    // a script snapshot of the script.
-    TestCase::CreateTestIsolateFromSnapshot(full_snapshot);
-    Dart_EnterScope();  // Start a Dart API scope for invoking API functions.
-
-    // Load the library.
-    Dart_Handle lib = Dart_LoadLibrary(NewString("dart_lib"), Dart_Null(),
-                                       NewString(kScriptChars), 0, 0);
-    EXPECT_VALID(lib);
-
-    // Write out the script snapshot.
-    result = Dart_CreateLibrarySnapshot(lib, &buffer, &size);
-    EXPECT_VALID(result);
-    script_snapshot = reinterpret_cast<uint8_t*>(malloc(size));
-    memmove(script_snapshot, buffer, size);
-    Dart_ExitScope();
-    Dart_ShutdownIsolate();
-  }
-
-  {
-    // Now Create an Isolate using the full snapshot and load the
-    // script snapshot created above and execute it.
-    TestCase::CreateTestIsolateFromSnapshot(full_snapshot);
-    Dart_EnterScope();  // Start a Dart API scope for invoking API functions.
-
-    // Load the test library from the snapshot.
-    EXPECT(script_snapshot != NULL);
-    result = Dart_LoadScriptFromSnapshot(script_snapshot, size);
-    EXPECT_VALID(result);
-
-    // Invoke a function which returns an object.
-    Dart_Handle cls = Dart_GetClass(result, NewString("FieldsTest"));
-    result = Dart_Invoke(cls, NewString("testMain"), 0, NULL);
-    EXPECT_VALID(result);
-    Dart_ExitScope();
-    Dart_ShutdownIsolate();
-  }
   free(full_snapshot);
   free(script_snapshot);
 }
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index 5b6a5f5..cf77f5f 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -20,9 +20,11 @@
 
 DEFINE_FLAG(bool, disassemble_stubs, false, "Disassemble generated stubs.");
 
-#define STUB_CODE_DECLARE(name) StubEntry* StubCode::name##_entry_ = NULL;
-VM_STUB_CODE_LIST(STUB_CODE_DECLARE);
+StubEntry* StubCode::entries_[kNumStubEntries] = {
+#define STUB_CODE_DECLARE(name) NULL,
+    VM_STUB_CODE_LIST(STUB_CODE_DECLARE)
 #undef STUB_CODE_DECLARE
+};
 
 
 StubEntry::StubEntry(const Code& code)
@@ -42,16 +44,17 @@
 
 #define STUB_CODE_GENERATE(name)                                               \
   code ^= Generate("_stub_" #name, StubCode::Generate##name##Stub);            \
-  name##_entry_ = new StubEntry(code);
+  entries_[k##name##Index] = new StubEntry(code);
 
 
 void StubCode::InitOnce() {
-#if !defined(DART_PRECOMPILED_RUNTIME)
+#if defined(DART_PRECOMPILED_RUNTIME)
+  // Stubs will be loaded from the snapshot.
+  UNREACHABLE();
+#else
   // Generate all the stubs.
   Code& code = Code::Handle();
   VM_STUB_CODE_LIST(STUB_CODE_GENERATE);
-#else
-  UNREACHABLE();
 #endif  // DART_PRECOMPILED_RUNTIME
 }
 
@@ -59,30 +62,6 @@
 #undef STUB_CODE_GENERATE
 
 
-void StubCode::Push(Serializer* serializer) {
-#define WRITE_STUB(name) serializer->Push(StubCode::name##_entry()->code());
-  VM_STUB_CODE_LIST(WRITE_STUB);
-#undef WRITE_STUB
-}
-
-
-void StubCode::WriteRef(Serializer* serializer) {
-#define WRITE_STUB(name) serializer->WriteRef(StubCode::name##_entry()->code());
-  VM_STUB_CODE_LIST(WRITE_STUB);
-#undef WRITE_STUB
-}
-
-
-void StubCode::ReadRef(Deserializer* deserializer) {
-  Code& code = Code::Handle();
-#define READ_STUB(name)                                                        \
-  code ^= deserializer->ReadRef();                                             \
-  name##_entry_ = new StubEntry(code);
-  VM_STUB_CODE_LIST(READ_STUB);
-#undef READ_STUB
-}
-
-
 void StubCode::Init(Isolate* isolate) {}
 
 
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index 35d589d..cba3cdf 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -17,8 +17,6 @@
 class RawCode;
 class SnapshotReader;
 class SnapshotWriter;
-class Serializer;
-class Deserializer;
 
 // List of stubs created in the VM isolate, these stubs are shared by different
 // isolates running in this dart process.
@@ -125,10 +123,6 @@
   // only once and the stub code resides in the vm_isolate heap.
   static void InitOnce();
 
-  static void Push(Serializer* serializer);
-  static void WriteRef(Serializer* serializer);
-  static void ReadRef(Deserializer* deserializer);
-
   // Generate all stubs which are generated on a per isolate basis as they
   // have embedded objects which are isolate specific.
   static void Init(Isolate* isolate);
@@ -150,7 +144,7 @@
 
 // Define the shared stub code accessors.
 #define STUB_CODE_ACCESSOR(name)                                               \
-  static const StubEntry* name##_entry() { return name##_entry_; }             \
+  static const StubEntry* name##_entry() { return entries_[k##name##Index]; }  \
   static intptr_t name##Size() { return name##_entry()->Size(); }
   VM_STUB_CODE_LIST(STUB_CODE_ACCESSOR);
 #undef STUB_CODE_ACCESSOR
@@ -161,6 +155,12 @@
 
   static const intptr_t kNoInstantiator = 0;
 
+  static StubEntry* EntryAt(intptr_t index) { return entries_[index]; }
+  static void EntryAtPut(intptr_t index, StubEntry* entry) {
+    entries_[index] = entry;
+  }
+  static intptr_t NumEntries() { return kNumStubEntries; }
+
  private:
   friend class MegamorphicCacheTable;
 
@@ -168,12 +168,17 @@
 
 #define STUB_CODE_GENERATE(name)                                               \
   static void Generate##name##Stub(Assembler* assembler);
-  VM_STUB_CODE_LIST(STUB_CODE_GENERATE);
+  VM_STUB_CODE_LIST(STUB_CODE_GENERATE)
 #undef STUB_CODE_GENERATE
 
-#define STUB_CODE_ENTRY(name) static StubEntry* name##_entry_;
-  VM_STUB_CODE_LIST(STUB_CODE_ENTRY);
+  enum {
+#define STUB_CODE_ENTRY(name) k##name##Index,
+    VM_STUB_CODE_LIST(STUB_CODE_ENTRY)
 #undef STUB_CODE_ENTRY
+        kNumStubEntries
+  };
+
+  static StubEntry* entries_[kNumStubEntries];
 
   // Generate the stub and finalize the generated code into the stub
   // code executable area.
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 6fca06b..1b3428e 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -91,7 +91,6 @@
       deferred_interrupts_(0),
       stack_overflow_count_(0),
       cha_(NULL),
-      type_range_cache_(NULL),
       deopt_id_(0),
       pending_functions_(GrowableObjectArray::null()),
       active_exception_(Object::null()),
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 65bbdf0..576d57c 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -52,7 +52,6 @@
 class TimelineStream;
 class TypeArguments;
 class TypeParameter;
-class TypeRangeCache;
 class Zone;
 
 #define REUSABLE_HANDLE_LIST(V)                                                \
@@ -305,11 +304,6 @@
     cha_ = value;
   }
 
-  TypeRangeCache* type_range_cache() const { return type_range_cache_; }
-  void set_type_range_cache(TypeRangeCache* value) {
-    type_range_cache_ = value;
-  }
-
   int32_t no_callback_scope_depth() const { return no_callback_scope_depth_; }
 
   void IncrementNoCallbackScopeDepth() {
@@ -704,7 +698,6 @@
 
   // Compiler state:
   CHA* cha_;
-  TypeRangeCache* type_range_cache_;
   intptr_t deopt_id_;  // Compilation specific counter.
   RawGrowableObjectArray* pending_functions_;
 
diff --git a/runtime/vm/version.h b/runtime/vm/version.h
index 2acf205..5f08dd3 100644
--- a/runtime/vm/version.h
+++ b/runtime/vm/version.h
@@ -13,10 +13,12 @@
  public:
   static const char* String();
   static const char* SnapshotString();
+  static const char* CommitString();
 
  private:
   static const char* str_;
   static const char* snapshot_hash_;
+  static const char* commit_;
 };
 
 }  // namespace dart
diff --git a/runtime/vm/version_in.cc b/runtime/vm/version_in.cc
index d196310..1857ce9 100644
--- a/runtime/vm/version_in.cc
+++ b/runtime/vm/version_in.cc
@@ -26,7 +26,13 @@
   return snapshot_hash_;
 }
 
+
+const char* Version::CommitString() {
+  return commit_;
+}
+
 const char* Version::snapshot_hash_ = "{{SNAPSHOT_HASH}}";
 const char* Version::str_ = "{{VERSION_STR}} ({{BUILD_TIME}})";
+const char* Version::commit_ = "{{VERSION_STR}}";
 
 }  // namespace dart
diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi
index 990a486..9b1d27c 100644
--- a/runtime/vm/vm_sources.gypi
+++ b/runtime/vm/vm_sources.gypi
@@ -269,6 +269,7 @@
     'isolate_test.cc',
     'jit_optimizer.cc',
     'jit_optimizer.h',
+    'json_parser.h',
     'json_stream.h',
     'json_stream.cc',
     'json_test.cc',
@@ -364,6 +365,8 @@
     'port_test.cc',
     'precompiler.cc',
     'precompiler.h',
+    'program_visitor.cc',
+    'program_visitor.h',
     'kernel.h',
     'kernel.cc',
     'kernel_binary.cc',
diff --git a/sdk/lib/core/errors.dart b/sdk/lib/core/errors.dart
index c1dff42..16f2ffb 100644
--- a/sdk/lib/core/errors.dart
+++ b/sdk/lib/core/errors.dart
@@ -222,7 +222,7 @@
                     (message != null) ? message : "Value not in range");
 
   /**
-   * Create a new [RangeError] with for an invalid value being outside a range.
+   * Create a new [RangeError] for a value being outside the valid range.
    *
    * The allowed range is from [minValue] to [maxValue], inclusive.
    * If `minValue` or `maxValue` are `null`, the range is infinite in
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 04ed9e6..d16d0d0 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -1209,8 +1209,8 @@
     return _create_2(blobParts, bag);
   }
 
-  static _create_1(parts) => JS('Blob', 'new Blob(#)', parts);
-  static _create_2(parts, bag) => JS('Blob', 'new Blob(#, #)', parts, bag);
+  static _create_1(parts) => JS('Blob', 'new window.Blob(#)', parts);
+  static _create_2(parts, bag) => JS('Blob', 'new window.Blob(#, #)', parts, bag);
 
   static _create_bag() => JS('var', '{}');
   static _bag_set(bag, key, value) { JS('void', '#[#] = #', bag, key, value); }
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart
index f33b63c..1cc9d8e 100644
--- a/sdk/lib/isolate/isolate.dart
+++ b/sdk/lib/isolate/isolate.dart
@@ -439,7 +439,8 @@
    * The isolate is requested to terminate itself.
    * The [priority] argument specifies when this must happen.
    *
-   * The [priority] must be one of [IMMEDIATE] or [BEFORE_NEXT_EVENT].
+   * The [priority], when provided, must be one of [IMMEDIATE] or
+   * [BEFORE_NEXT_EVENT] (the default).
    * The shutdown is performed at different times depending on the priority:
    *
    * * `IMMEDIATE`: The isolate shuts down as soon as possible.
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status
index 3233640..3c1d647 100644
--- a/tests/co19/co19-co19.status
+++ b/tests/co19/co19-co19.status
@@ -14,6 +14,7 @@
 [ $runtime == vm || $runtime != vm ]
 # Tests that fail everywhere, including the analyzer.
 
+Language/Statements/Assert/syntax_t04: Pass, Fail # assert now has an optional second parameter.
 LibTest/typed_data/ByteData/buffer_A01_t01: Fail # co19 r736 bug - sent comment.
 LibTest/core/RegExp/firstMatch_A01_t01: Fail # co19 issue 742
 
diff --git a/tests/compiler/dart2js/all_native_test.dart b/tests/compiler/dart2js/all_native_test.dart
new file mode 100644
index 0000000..24cbdb2
--- /dev/null
+++ b/tests/compiler/dart2js/all_native_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/common/names.dart';
+import 'package:compiler/src/commandline_options.dart';
+import 'package:expect/expect.dart';
+import 'memory_compiler.dart';
+
+main() {
+  asyncTest(() async {
+    DiagnosticCollector collector = new DiagnosticCollector();
+    await runCompiler(
+        entryPoint: Uris.dart_html,
+        diagnosticHandler: collector,
+        options: [Flags.analyzeAll, Flags.verbose]);
+    int allNativeUsedCount =
+        collector.verboseInfos.where((CollectedMessage message) {
+      return message.text.startsWith('All native types marked as used due to ');
+    }).length;
+    Expect.equals(
+        1, allNativeUsedCount, "Unexpected message count: $allNativeUsedCount");
+  });
+}
diff --git a/tests/compiler/dart2js/assert_message_throw_test.dart b/tests/compiler/dart2js/assert_message_throw_test.dart
index 75a5bb4..898e3aa 100644
--- a/tests/compiler/dart2js/assert_message_throw_test.dart
+++ b/tests/compiler/dart2js/assert_message_throw_test.dart
@@ -7,6 +7,7 @@
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/elements/elements.dart';
 import 'package:compiler/src/types/masks.dart';
+import 'package:compiler/src/world.dart' show ClosedWorld;
 import 'package:expect/expect.dart';
 import 'memory_compiler.dart';
 import 'type_mask_test_helper.dart';
@@ -58,19 +59,20 @@
         memorySourceFiles: {'main.dart': SOURCE},
         options: [Flags.enableCheckedMode, Flags.enableAssertMessage]);
     Compiler compiler = result.compiler;
+    ClosedWorld closedWorld = compiler.resolverWorld.closedWorldForTesting;
 
     void check(String methodName, TypeMask expectedReturnType) {
       Element element = compiler.mainApp.find(methodName);
       TypeMask typeMask = simplify(
           compiler.globalInference.results.resultOf(element).returnType,
-          compiler);
+          closedWorld);
       Expect.equals(expectedReturnType, typeMask,
           "Unexpected return type on method '$methodName'.");
     }
 
-    check('test0', compiler.closedWorld.commonMasks.growableListType);
-    check('test1', compiler.closedWorld.commonMasks.nullType);
-    check('test2', compiler.closedWorld.commonMasks.uint31Type.nullable());
-    check('test3', compiler.closedWorld.commonMasks.intType);
+    check('test0', closedWorld.commonMasks.growableListType);
+    check('test1', closedWorld.commonMasks.nullType);
+    check('test2', closedWorld.commonMasks.uint31Type.nullable());
+    check('test3', closedWorld.commonMasks.intType);
   });
 }
diff --git a/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart b/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
index f12fe38..44ea2ba 100644
--- a/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
+++ b/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
@@ -2,8 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/types/masks.dart';
 import 'package:expect/expect.dart';
-import "package:async_helper/async_helper.dart";
 
 import 'compiler_helper.dart';
 import 'type_mask_test_helper.dart';
@@ -206,109 +207,85 @@
   }
 """;
 
-void doTest(String test, bool enableInlining, Function f) {
+typedef List<TypeMask> TestCallback(CommonMasks masks);
+
+void doTest(String test, bool enableInlining, TestCallback f) {
   compileAndFind(test, 'A', 'x', enableInlining, (compiler, element) {
-    var expectedTypes = f(compiler);
+    var inferrer = compiler.globalInference.typesInferrerInternal;
+    var closedWorld = inferrer.closedWorld;
+    var expectedTypes = f(closedWorld.commonMasks);
     var signature = element.functionSignature;
     int index = 0;
-    var inferrer = compiler.globalInference.typesInferrerInternal;
     signature.forEachParameter((Element element) {
       Expect.equals(expectedTypes[index++],
-          simplify(inferrer.getTypeOfElement(element), compiler), test);
+          simplify(inferrer.getTypeOfElement(element), closedWorld), test);
     });
     Expect.equals(index, expectedTypes.length);
   });
 }
 
-void runTest(String test, Function f) {
+void runTest(String test, TestCallback f) {
   doTest(test, false, f);
   doTest(test, true, f);
 }
 
-subclassOfInterceptor(compiler) {
-  return findTypeMask(compiler, 'Interceptor', 'nonNullSubclass');
-}
-
 void test() {
-  runTest(TEST_1, (compiler) => [compiler.closedWorld.commonMasks.stringType]);
-  runTest(TEST_2, (compiler) => [compiler.closedWorld.commonMasks.uint31Type]);
-  runTest(TEST_3, (compiler) => [compiler.closedWorld.commonMasks.intType]);
-  runTest(TEST_4, (compiler) => [compiler.closedWorld.commonMasks.numType]);
-  runTest(TEST_5, (compiler) => [compiler.closedWorld.commonMasks.numType]);
-  runTest(TEST_6, (compiler) => [compiler.closedWorld.commonMasks.numType]);
-  runTest(TEST_7a, (compiler) => [subclassOfInterceptor(compiler)]);
-  runTest(
-      TEST_7b,
-      (compiler) =>
-          [compiler.closedWorld.commonMasks.dynamicType.nonNullable()]);
+  runTest(TEST_1, (commonMasks) => [commonMasks.stringType]);
+  runTest(TEST_2, (commonMasks) => [commonMasks.uint31Type]);
+  runTest(TEST_3, (commonMasks) => [commonMasks.intType]);
+  runTest(TEST_4, (commonMasks) => [commonMasks.numType]);
+  runTest(TEST_5, (commonMasks) => [commonMasks.numType]);
+  runTest(TEST_6, (commonMasks) => [commonMasks.numType]);
+  runTest(TEST_7a, (commonMasks) => [commonMasks.interceptorType]);
+  runTest(TEST_7b, (commonMasks) => [commonMasks.dynamicType.nonNullable()]);
 
   runTest(
       TEST_8,
-      (compiler) => [
-            compiler.closedWorld.commonMasks.uint31Type,
-            subclassOfInterceptor(compiler),
-            compiler.closedWorld.commonMasks.dynamicType.nonNullable()
+      (commonMasks) => [
+            commonMasks.uint31Type,
+            commonMasks.interceptorType,
+            commonMasks.dynamicType.nonNullable()
           ]);
-  runTest(
-      TEST_9,
-      (compiler) => [
-            compiler.closedWorld.commonMasks.uint31Type,
-            compiler.closedWorld.commonMasks.uint31Type
-          ]);
-  runTest(
-      TEST_10,
-      (compiler) => [
-            compiler.closedWorld.commonMasks.uint31Type,
-            compiler.closedWorld.commonMasks.uint31Type
-          ]);
+  runTest(TEST_9,
+      (commonMasks) => [commonMasks.uint31Type, commonMasks.uint31Type]);
+  runTest(TEST_10,
+      (commonMasks) => [commonMasks.uint31Type, commonMasks.uint31Type]);
   runTest(
       TEST_11,
-      (compiler) =>
-          [subclassOfInterceptor(compiler), subclassOfInterceptor(compiler)]);
+      (commonMasks) =>
+          [commonMasks.interceptorType, commonMasks.interceptorType]);
+
+  runTest(TEST_12,
+      (commonMasks) => [commonMasks.stringType, commonMasks.uint31Type]);
+
+  runTest(TEST_13, (commonMasks) => [commonMasks.numType]);
+
+  runTest(TEST_14,
+      (commonMasks) => [commonMasks.uint31Type, commonMasks.stringType]);
 
   runTest(
-      TEST_12,
-      (compiler) => [
-            compiler.closedWorld.commonMasks.stringType,
-            compiler.closedWorld.commonMasks.uint31Type
-          ]);
-
-  runTest(TEST_13, (compiler) => [compiler.closedWorld.commonMasks.numType]);
-
-  runTest(
-      TEST_14,
-      (compiler) => [
-            compiler.closedWorld.commonMasks.uint31Type,
-            compiler.closedWorld.commonMasks.stringType
-          ]);
-
-  runTest(
-      TEST_15,
-      (compiler) => [
-            compiler.closedWorld.commonMasks.stringType,
-            compiler.closedWorld.commonMasks.boolType
-          ]);
+      TEST_15, (commonMasks) => [commonMasks.stringType, commonMasks.boolType]);
 
   runTest(
       TEST_16,
-      (compiler) => [
-            compiler.closedWorld.commonMasks.uint31Type,
-            compiler.closedWorld.commonMasks.uint31Type,
-            compiler.closedWorld.commonMasks.stringType
+      (commonMasks) => [
+            commonMasks.uint31Type,
+            commonMasks.uint31Type,
+            commonMasks.stringType
           ]);
 
   runTest(
       TEST_17,
-      (compiler) => [
-            compiler.closedWorld.commonMasks.uint31Type,
-            compiler.closedWorld.commonMasks.boolType,
-            compiler.closedWorld.commonMasks.doubleType
+      (commonMasks) => [
+            commonMasks.uint31Type,
+            commonMasks.boolType,
+            commonMasks.doubleType
           ]);
 
   runTest(
       TEST_18,
-      (compiler) =>
-          [subclassOfInterceptor(compiler), subclassOfInterceptor(compiler)]);
+      (commonMasks) =>
+          [commonMasks.interceptorType, commonMasks.interceptorType]);
 }
 
 void main() {
diff --git a/tests/compiler/dart2js/class_set_test.dart b/tests/compiler/dart2js/class_set_test.dart
index 9eea4f1..d5e6624 100644
--- a/tests/compiler/dart2js/class_set_test.dart
+++ b/tests/compiler/dart2js/class_set_test.dart
@@ -50,7 +50,7 @@
       }
       """,
       useMockCompiler: false);
-  ClosedWorld world = env.compiler.closedWorld;
+  ClosedWorld world = env.closedWorld;
 
   ClassElement A = env.getElement("A");
   ClassElement B = env.getElement("B");
@@ -383,7 +383,7 @@
       }
       """,
       useMockCompiler: false);
-  ClosedWorld world = env.compiler.closedWorld;
+  ClosedWorld world = env.closedWorld;
 
   ClassElement A = env.getElement("A");
   ClassElement B = env.getElement("B");
diff --git a/tests/compiler/dart2js/closure_tracer_test.dart b/tests/compiler/dart2js/closure_tracer_test.dart
index f76bea1..b585ea4 100644
--- a/tests/compiler/dart2js/closure_tracer_test.dart
+++ b/tests/compiler/dart2js/closure_tracer_test.dart
@@ -154,13 +154,14 @@
   Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(TEST, uri);
   asyncTest(() => compiler.run(uri).then((_) {
-        var commonMasks = compiler.closedWorld.commonMasks;
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
+        var commonMasks = closedWorld.commonMasks;
 
         checkType(String name, type) {
           var element = findElement(compiler, name);
           var mask = typesInferrer.getReturnTypeOfElement(element);
-          Expect.equals(type.nullable(), simplify(mask, compiler), name);
+          Expect.equals(type.nullable(), simplify(mask, closedWorld), name);
         }
 
         checkType('testFunctionStatement', commonMasks.uint31Type);
diff --git a/tests/compiler/dart2js/compiler_helper.dart b/tests/compiler/dart2js/compiler_helper.dart
index ccf41fa..c21397e 100644
--- a/tests/compiler/dart2js/compiler_helper.dart
+++ b/tests/compiler/dart2js/compiler_helper.dart
@@ -197,35 +197,6 @@
   return element;
 }
 
-types.TypeMask findTypeMask(compiler, String name,
-    [String how = 'nonNullExact']) {
-  var sourceName = name;
-  var element = compiler.mainApp.find(sourceName);
-  if (element == null) {
-    element = compiler.backend.helpers.interceptorsLibrary.find(sourceName);
-  }
-  if (element == null) {
-    element = compiler.commonElements.coreLibrary.find(sourceName);
-  }
-  Expect.isNotNull(element, 'Could not locate $name');
-  switch (how) {
-    case 'exact':
-      return new types.TypeMask.exact(element, compiler.closedWorld);
-    case 'nonNullExact':
-      return new types.TypeMask.nonNullExact(element, compiler.closedWorld);
-    case 'subclass':
-      return new types.TypeMask.subclass(element, compiler.closedWorld);
-    case 'nonNullSubclass':
-      return new types.TypeMask.nonNullSubclass(element, compiler.closedWorld);
-    case 'subtype':
-      return new types.TypeMask.subtype(element, compiler.closedWorld);
-    case 'nonNullSubtype':
-      return new types.TypeMask.nonNullSubtype(element, compiler.closedWorld);
-  }
-  Expect.fail('Unknown TypeMask constructor $how');
-  return null;
-}
-
 String anyIdentifier = "[a-zA-Z][a-zA-Z0-9]*";
 
 String getIntTypeCheck(String variable) {
diff --git a/tests/compiler/dart2js/concrete_type_inference_test.dart b/tests/compiler/dart2js/concrete_type_inference_test.dart
index ce5b556..2efb5d7 100644
--- a/tests/compiler/dart2js/concrete_type_inference_test.dart
+++ b/tests/compiler/dart2js/concrete_type_inference_test.dart
@@ -16,49 +16,52 @@
   });
 }
 
-void checkPrintType(String expression, checkType(compiler, type)) {
+void checkPrintType(String expression, checkType(closedWorld, type)) {
   asyncTest(() => compileAndFind('main() { print($expression); }', 'print',
           (compiler, printElement) {
         var parameter = printElement.functionSignature.requiredParameters.first;
-        checkType(compiler, _typeOf(compiler, parameter));
+        checkType(compiler.resolverWorld.closedWorldForTesting,
+            _typeOf(compiler, parameter));
       }));
 
   asyncTest(() =>
       compileAndFind('main() { var x = print; print($expression); }', 'print',
           (compiler, printElement) {
         var parameter = printElement.functionSignature.requiredParameters.first;
-        checkType(compiler, _typeOf(compiler, parameter));
+        checkType(compiler.resolverWorld.closedWorldForTesting,
+            _typeOf(compiler, parameter));
       }));
 
   asyncTest(() => compileAndFind(
           'main() { print($expression); print($expression); }', 'print',
           (compiler, printElement) {
         var parameter = printElement.functionSignature.requiredParameters.first;
-        checkType(compiler, _typeOf(compiler, parameter));
+        checkType(compiler.resolverWorld.closedWorldForTesting,
+            _typeOf(compiler, parameter));
       }));
 }
 
 void testBasicTypes() {
-  checkPrintType('true', (compiler, type) {
+  checkPrintType('true', (closedWorld, type) {
     if (type.isForwarding) type = type.forwardTo;
-    Expect.identical(compiler.closedWorld.commonMasks.boolType, type);
+    Expect.identical(closedWorld.commonMasks.boolType, type);
   });
-  checkPrintType('1.5', (compiler, type) {
-    Expect.identical(compiler.closedWorld.commonMasks.doubleType, type);
+  checkPrintType('1.5', (closedWorld, type) {
+    Expect.identical(closedWorld.commonMasks.doubleType, type);
   });
-  checkPrintType('1', (compiler, type) {
-    Expect.identical(compiler.closedWorld.commonMasks.uint31Type, type);
+  checkPrintType('1', (closedWorld, type) {
+    Expect.identical(closedWorld.commonMasks.uint31Type, type);
   });
-  checkPrintType('[]', (compiler, type) {
+  checkPrintType('[]', (closedWorld, type) {
     if (type.isForwarding) type = type.forwardTo;
-    Expect.identical(compiler.closedWorld.commonMasks.growableListType, type);
+    Expect.identical(closedWorld.commonMasks.growableListType, type);
   });
-  checkPrintType('null', (compiler, type) {
-    Expect.identical(compiler.closedWorld.commonMasks.nullType, type);
+  checkPrintType('null', (closedWorld, type) {
+    Expect.identical(closedWorld.commonMasks.nullType, type);
   });
-  checkPrintType('"foo"', (compiler, type) {
-    Expect.isTrue(compiler.closedWorld.commonMasks.stringType
-        .containsOnlyString(compiler.closedWorld));
+  checkPrintType('"foo"', (closedWorld, type) {
+    Expect.isTrue(
+        closedWorld.commonMasks.stringType.containsOnlyString(closedWorld));
   });
 }
 
@@ -68,7 +71,7 @@
     var firstParameter = fiskElement.functionSignature.requiredParameters[0];
     var secondParameter = fiskElement.functionSignature.optionalParameters[0];
     var thirdParameter = fiskElement.functionSignature.optionalParameters[1];
-    var commonMasks = compiler.closedWorld.commonMasks;
+    var commonMasks = compiler.resolverWorld.closedWorldForTesting.commonMasks;
     Expect.identical(commonMasks.uint31Type, _typeOf(compiler, firstParameter));
     Expect.identical(commonMasks.nullType, _typeOf(compiler, secondParameter));
     Expect.identical(commonMasks.nullType, _typeOf(compiler, thirdParameter));
diff --git a/tests/compiler/dart2js/container_mask_equal_test.dart b/tests/compiler/dart2js/container_mask_equal_test.dart
index 9f67840..5bb5298 100644
--- a/tests/compiler/dart2js/container_mask_equal_test.dart
+++ b/tests/compiler/dart2js/container_mask_equal_test.dart
@@ -31,6 +31,7 @@
     var result = await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
     var compiler = result.compiler;
     var typesInferrer = compiler.globalInference.typesInferrerInternal;
+    var closedWorld = typesInferrer.closedWorld;
 
     var element = compiler.mainApp.find('a');
     var mask1 = typesInferrer.getReturnTypeOfElement(element);
@@ -44,7 +45,7 @@
     element = compiler.mainApp.find('d');
     var mask4 = typesInferrer.getReturnTypeOfElement(element);
 
-    Expect.notEquals(mask1.union(mask2, compiler.closedWorld),
-        mask3.union(mask4, compiler.closedWorld));
+    Expect.notEquals(
+        mask1.union(mask2, closedWorld), mask3.union(mask4, closedWorld));
   });
 }
diff --git a/tests/compiler/dart2js/diagnostic_helper.dart b/tests/compiler/dart2js/diagnostic_helper.dart
index 7d82a3d..6f63e8a 100644
--- a/tests/compiler/dart2js/diagnostic_helper.dart
+++ b/tests/compiler/dart2js/diagnostic_helper.dart
@@ -65,6 +65,10 @@
     return filterMessagesByKinds([Diagnostic.CRASH]);
   }
 
+  Iterable<CollectedMessage> get verboseInfos {
+    return filterMessagesByKinds([Diagnostic.VERBOSE_INFO]);
+  }
+
   /// `true` if non-verbose messages has been collected.
   bool get hasRegularMessages {
     return messages.any((m) => m.kind != Diagnostic.VERBOSE_INFO);
diff --git a/tests/compiler/dart2js/dictionary_types_test.dart b/tests/compiler/dart2js/dictionary_types_test.dart
index 15a4e57..ff37cab 100644
--- a/tests/compiler/dart2js/dictionary_types_test.dart
+++ b/tests/compiler/dart2js/dictionary_types_test.dart
@@ -105,19 +105,18 @@
 
 void main() {
   asyncTest(() async {
-    await compileAndTest("AddAll.dart", (types, getType, compiler) {
+    await compileAndTest("AddAll.dart", (types, getType, closedWorld) {
       Expect.equals(getType('int'), types.uint31Type);
       Expect.equals(getType('anotherInt'), types.uint31Type);
       Expect.equals(getType('dynamic'), types.dynamicType);
       Expect.equals(getType('nullOrInt'), types.uint31Type.nullable());
     });
-    await compileAndTest("Union.dart", (types, getType, compiler) {
+    await compileAndTest("Union.dart", (types, getType, closedWorld) {
       Expect.equals(getType('nullOrInt'), types.uint31Type.nullable());
-      Expect
-          .isTrue(getType('aString').containsOnlyString(compiler.closedWorld));
+      Expect.isTrue(getType('aString').containsOnlyString(closedWorld));
       Expect.equals(getType('doubleOrNull'), types.doubleType.nullable());
     });
-    await compileAndTest("ValueType.dart", (types, getType, compiler) {
+    await compileAndTest("ValueType.dart", (types, getType, closedWorld) {
       Expect.equals(getType('knownDouble'), types.doubleType);
       Expect.equals(getType('intOrNull'), types.uint31Type.nullable());
       Expect.equals(getType('justNull'), types.nullType);
@@ -125,7 +124,7 @@
     await compileAndTest("Propagation.dart", (code) {
       Expect.isFalse(code.contains("J.\$add\$ns"));
     }, createCode: true);
-    await compileAndTest("Bailout.dart", (types, getType, compiler) {
+    await compileAndTest("Bailout.dart", (types, getType, closedWorld) {
       Expect.equals(getType('notInt'), types.dynamicType);
       Expect.equals(getType('alsoNotInt'), types.dynamicType);
       Expect.isFalse(getType('dict').isDictionary);
@@ -141,15 +140,16 @@
         compiler.stopAfterTypeInference = !createCode;
       });
   var compiler = result.compiler;
-  var commonMasks = compiler.closedWorld.commonMasks;
   var typesInferrer = compiler.globalInference.typesInferrerInternal;
+  var closedWorld = typesInferrer.closedWorld;
+  var commonMasks = closedWorld.commonMasks;
   getType(String name) {
     var element = findElement(compiler, name);
     return typesInferrer.getTypeOfElement(element);
   }
 
   if (!createCode) {
-    checker(commonMasks, getType, compiler);
+    checker(commonMasks, getType, closedWorld);
   } else {
     var element = compiler.mainFunction;
     var code = compiler.backend.getGeneratedCode(element);
diff --git a/tests/compiler/dart2js/dump_info_test.dart b/tests/compiler/dart2js/dump_info_test.dart
index 4f89313..3778de3 100644
--- a/tests/compiler/dart2js/dump_info_test.dart
+++ b/tests/compiler/dart2js/dump_info_test.dart
@@ -104,7 +104,7 @@
   var dumpTask = compiler.dumpInfoTask;
 
   StringBuffer sb = new StringBuffer();
-  dumpTask.dumpInfoJson(sb, compiler.closedWorld);
+  dumpTask.dumpInfoJson(sb, compiler.resolverWorld.closedWorldForTesting);
   String json = sb.toString();
   Map<String, dynamic> map = JSON.decode(json);
 
diff --git a/tests/compiler/dart2js/expect_annotations_test.dart b/tests/compiler/dart2js/expect_annotations_test.dart
index c9c47e0..e8b5e18 100644
--- a/tests/compiler/dart2js/expect_annotations_test.dart
+++ b/tests/compiler/dart2js/expect_annotations_test.dart
@@ -8,6 +8,7 @@
 import 'package:compiler/src/elements/elements.dart';
 import 'package:compiler/src/js_backend/js_backend.dart';
 import 'package:compiler/src/types/types.dart';
+import 'package:compiler/src/world.dart' show ClosedWorld;
 import 'type_mask_test_helper.dart';
 import 'memory_compiler.dart';
 
@@ -51,6 +52,7 @@
     CompilationResult result =
         await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
     Compiler compiler = result.compiler;
+    ClosedWorld closedWorld = compiler.resolverWorld.closedWorldForTesting;
     Expect.isFalse(compiler.compilationFailed, 'Unsuccessful compilation');
     JavaScriptBackend backend = compiler.backend;
     Expect.isNotNull(backend.annotations.expectNoInlineClass,
@@ -65,12 +67,12 @@
       for (ParameterElement parameter in function.parameters) {
         TypeMask type = inferrer.getTypeOfElement(parameter);
         Expect.equals(
-            expectedParameterType, simplify(type, compiler), "$parameter");
+            expectedParameterType, simplify(type, closedWorld), "$parameter");
       }
       if (expectedReturnType != null) {
         TypeMask type = inferrer.getReturnTypeOfElement(function);
         Expect.equals(
-            expectedReturnType, simplify(type, compiler), "$function");
+            expectedReturnType, simplify(type, closedWorld), "$function");
       }
     }
 
@@ -97,15 +99,15 @@
         testTypeMatch(
             method, expectedParameterType, expectedReturnType, inferrer);
       } else if (expectAssumeDynamic) {
-        testTypeMatch(method, compiler.closedWorld.commonMasks.dynamicType,
-            null, inferrer);
+        testTypeMatch(
+            method, closedWorld.commonMasks.dynamicType, null, inferrer);
       }
     }
 
-    TypeMask jsStringType = compiler.closedWorld.commonMasks.stringType;
-    TypeMask jsIntType = compiler.closedWorld.commonMasks.intType;
-    TypeMask coreStringType = new TypeMask.subtype(
-        compiler.coreClasses.stringClass, compiler.closedWorld);
+    TypeMask jsStringType = closedWorld.commonMasks.stringType;
+    TypeMask jsIntType = closedWorld.commonMasks.intType;
+    TypeMask coreStringType =
+        new TypeMask.subtype(compiler.coreClasses.stringClass, closedWorld);
 
     test('method');
     test('methodAssumeDynamic', expectAssumeDynamic: true);
diff --git a/tests/compiler/dart2js/field_type_simple_inferer_test.dart b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
index 0e930a0..98defee 100644
--- a/tests/compiler/dart2js/field_type_simple_inferer_test.dart
+++ b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
@@ -5,8 +5,7 @@
 import 'package:expect/expect.dart';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/types/types.dart' show TypeMask;
-import 'package:compiler/src/types/masks.dart' show CommonMasks;
-import 'package:compiler/src/compiler.dart' show Compiler;
+import 'package:compiler/src/world.dart' show ClosedWorld;
 
 import 'compiler_helper.dart';
 import 'type_mask_test_helper.dart';
@@ -471,16 +470,17 @@
   }
 """;
 
-typedef TypeMask TestCallback(Compiler compiler, CommonMasks masks);
+typedef TypeMask TestCallback(ClosedWorld closedWorld);
 
 void doTest(
     String test, bool disableInlining, Map<String, TestCallback> fields) {
   fields.forEach((String name, TestCallback f) {
     compileAndFind(test, 'A', name, disableInlining, (compiler, field) {
-      TypeMask type = f(compiler, compiler.closedWorld.commonMasks);
       var inferrer = compiler.globalInference.typesInferrerInternal;
+      var closedWorld = inferrer.closedWorld;
+      TypeMask type = f(closedWorld);
       TypeMask inferredType =
-          simplify(inferrer.getTypeOfElement(field), inferrer.compiler);
+          simplify(inferrer.getTypeOfElement(field), closedWorld);
       Expect.equals(type, inferredType, test);
     });
   });
@@ -492,114 +492,122 @@
 }
 
 void test() {
-  TypeMask subclassOfInterceptor(Compiler compiler, CommonMasks types) =>
-      findTypeMask(compiler, 'Interceptor', 'nonNullSubclass');
-
-  runTest(
-      TEST_1, <String, TestCallback>{'f': (compiler, types) => types.nullType});
+  runTest(TEST_1, <String, TestCallback>{
+    'f': (closedWorld) => closedWorld.commonMasks.nullType
+  });
   runTest(TEST_2, <String, TestCallback>{
-    'f1': (compiler, types) => types.nullType,
-    'f2': (compiler, types) => types.uint31Type
+    'f1': (closedWorld) => closedWorld.commonMasks.nullType,
+    'f2': (closedWorld) => closedWorld.commonMasks.uint31Type
   });
   runTest(TEST_3, <String, TestCallback>{
-    'f1': (compiler, types) => types.uint31Type,
-    'f2': (compiler, types) => types.uint31Type.nullable()
+    'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
+    'f2': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
   });
   runTest(TEST_4, <String, TestCallback>{
-    'f1': subclassOfInterceptor,
-    'f2': (compiler, types) => types.stringType.nullable()
+    'f1': (closedWorld) => closedWorld.commonMasks.interceptorType,
+    'f2': (closedWorld) => closedWorld.commonMasks.stringType.nullable()
   });
 
   // TODO(ngeoffray): We should try to infer that the initialization
   // code at the declaration site of the fields does not matter.
   runTest(TEST_5, <String, TestCallback>{
-    'f1': subclassOfInterceptor,
-    'f2': subclassOfInterceptor
+    'f1': (closedWorld) => closedWorld.commonMasks.interceptorType,
+    'f2': (closedWorld) => closedWorld.commonMasks.interceptorType,
   });
   runTest(TEST_6, <String, TestCallback>{
-    'f1': subclassOfInterceptor,
-    'f2': subclassOfInterceptor
+    'f1': (closedWorld) => closedWorld.commonMasks.interceptorType,
+    'f2': (closedWorld) => closedWorld.commonMasks.interceptorType,
   });
   runTest(TEST_7, <String, TestCallback>{
-    'f1': subclassOfInterceptor,
-    'f2': subclassOfInterceptor
+    'f1': (closedWorld) => closedWorld.commonMasks.interceptorType,
+    'f2': (closedWorld) => closedWorld.commonMasks.interceptorType,
   });
 
   runTest(TEST_8, <String, TestCallback>{
-    'f': (compiler, types) => types.stringType.nullable()
+    'f': (closedWorld) => closedWorld.commonMasks.stringType.nullable()
   });
   runTest(TEST_9, <String, TestCallback>{
-    'f': (compiler, types) => types.stringType.nullable()
+    'f': (closedWorld) => closedWorld.commonMasks.stringType.nullable()
   });
-  runTest(TEST_10,
-      <String, TestCallback>{'f': (compiler, types) => types.uint31Type});
-  runTest(TEST_11,
-      <String, TestCallback>{'fs': (compiler, types) => types.uint31Type});
+  runTest(TEST_10, <String, TestCallback>{
+    'f': (closedWorld) => closedWorld.commonMasks.uint31Type
+  });
+  runTest(TEST_11, <String, TestCallback>{
+    'fs': (closedWorld) => closedWorld.commonMasks.uint31Type
+  });
 
   // TODO(ngeoffray): We should try to infer that the initialization
   // code at the declaration site of the fields does not matter.
-  runTest(TEST_12, <String, TestCallback>{'fs': subclassOfInterceptor});
+  runTest(TEST_12, <String, TestCallback>{
+    'fs': (closedWorld) => closedWorld.commonMasks.interceptorType
+  });
 
-  runTest(TEST_13,
-      <String, TestCallback>{'fs': (compiler, types) => types.uint31Type});
-  runTest(TEST_14,
-      <String, TestCallback>{'f': (compiler, types) => types.uint31Type});
+  runTest(TEST_13, <String, TestCallback>{
+    'fs': (closedWorld) => closedWorld.commonMasks.uint31Type
+  });
+  runTest(TEST_14, <String, TestCallback>{
+    'f': (closedWorld) => closedWorld.commonMasks.uint31Type
+  });
   runTest(TEST_15, <String, TestCallback>{
-    'f': (compiler, types) {
-      ClassElement cls = compiler.backend.helpers.jsIndexableClass;
-      return new TypeMask.nonNullSubtype(cls, compiler.closedWorld);
+    'f': (closedWorld) {
+      ClassElement cls = closedWorld.backendClasses.indexableImplementation;
+      return new TypeMask.nonNullSubtype(cls, closedWorld);
     }
   });
-  runTest(TEST_16, <String, TestCallback>{'f': subclassOfInterceptor});
+  runTest(TEST_16, <String, TestCallback>{
+    'f': (closedWorld) => closedWorld.commonMasks.interceptorType
+  });
   runTest(TEST_17, <String, TestCallback>{
-    'f': (compiler, types) => types.uint31Type.nullable()
+    'f': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
   });
   runTest(TEST_18, <String, TestCallback>{
-    'f1': (compiler, types) => types.uint31Type,
-    'f2': (compiler, types) => types.stringType,
-    'f3': (compiler, types) => types.dynamicType
+    'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
+    'f2': (closedWorld) => closedWorld.commonMasks.stringType,
+    'f3': (closedWorld) => closedWorld.commonMasks.dynamicType
   });
   runTest(TEST_19, <String, TestCallback>{
-    'f1': (compiler, types) => types.uint31Type,
-    'f2': (compiler, types) => types.stringType,
-    'f3': (compiler, types) => types.dynamicType
+    'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
+    'f2': (closedWorld) => closedWorld.commonMasks.stringType,
+    'f3': (closedWorld) => closedWorld.commonMasks.dynamicType
   });
   runTest(TEST_20, <String, TestCallback>{
-    'f': (compiler, types) => types.uint31Type.nullable()
+    'f': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
   });
   runTest(TEST_21, <String, TestCallback>{
-    'f': (compiler, types) => types.uint31Type.nullable()
+    'f': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
   });
 
   runTest(TEST_22, <String, TestCallback>{
-    'f1': (compiler, types) => types.uint31Type,
-    'f2': (compiler, types) => types.uint31Type,
-    'f3': (compiler, types) => types.stringType.nullable()
+    'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
+    'f2': (closedWorld) => closedWorld.commonMasks.uint31Type,
+    'f3': (closedWorld) => closedWorld.commonMasks.stringType.nullable()
   });
 
   runTest(TEST_23, <String, TestCallback>{
-    'f1': (compiler, types) => types.uint31Type.nullable(),
-    'f2': (compiler, types) => types.uint31Type.nullable(),
-    'f3': (compiler, types) => types.uint31Type.nullable(),
-    'f4': (compiler, types) => types.uint31Type.nullable()
+    'f1': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable(),
+    'f2': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable(),
+    'f3': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable(),
+    'f4': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
   });
 
   runTest(TEST_24, <String, TestCallback>{
-    'f1': (compiler, types) => types.positiveIntType,
-    'f2': (compiler, types) => types.positiveIntType,
-    'f3': (compiler, types) => types.uint31Type,
-    'f4': (compiler, types) => types.uint31Type,
-    'f5': (compiler, types) => types.numType.nullable(),
-    'f6': (compiler, types) => types.stringType.nullable()
+    'f1': (closedWorld) => closedWorld.commonMasks.positiveIntType,
+    'f2': (closedWorld) => closedWorld.commonMasks.positiveIntType,
+    'f3': (closedWorld) => closedWorld.commonMasks.uint31Type,
+    'f4': (closedWorld) => closedWorld.commonMasks.uint31Type,
+    'f5': (closedWorld) => closedWorld.commonMasks.numType.nullable(),
+    'f6': (closedWorld) => closedWorld.commonMasks.stringType.nullable()
   });
 
-  runTest(TEST_25,
-      <String, TestCallback>{'f1': (compiler, types) => types.uint31Type});
-  runTest(TEST_26,
-      <String, TestCallback>{'f1': (compiler, types) => types.positiveIntType});
+  runTest(TEST_25, <String, TestCallback>{
+    'f1': (closedWorld) => closedWorld.commonMasks.uint31Type
+  });
+  runTest(TEST_26, <String, TestCallback>{
+    'f1': (closedWorld) => closedWorld.commonMasks.positiveIntType
+  });
   runTest(TEST_27, <String, TestCallback>{
-    'f1': (compiler, types) => types.uint31Type,
-    'f2': (compiler, types) => types.uint31Type.nullable()
+    'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
+    'f2': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
   });
 }
 
diff --git a/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart b/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart
index eb58e74..d4e866e 100644
--- a/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart
+++ b/tests/compiler/dart2js/gvn_dynamic_field_get_test.dart
@@ -36,7 +36,7 @@
         var element = cls.lookupLocalMember(name);
         Expect.isNotNull(element);
         Selector selector = new Selector.getter(new PublicName(name));
-        Expect.isFalse(
-            compiler.closedWorld.hasAnyUserDefinedGetter(selector, null));
+        Expect.isFalse(compiler.resolverWorld.closedWorldForTesting
+            .hasAnyUserDefinedGetter(selector, null));
       }));
 }
diff --git a/tests/compiler/dart2js/issue13354_test.dart b/tests/compiler/dart2js/issue13354_test.dart
index ecf8dba..cf87020 100644
--- a/tests/compiler/dart2js/issue13354_test.dart
+++ b/tests/compiler/dart2js/issue13354_test.dart
@@ -29,14 +29,16 @@
   Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(TEST, uri);
   asyncTest(() => compiler.run(uri).then((_) {
-        var commonMasks = compiler.closedWorld.commonMasks;
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
+        var commonMasks = closedWorld.commonMasks;
 
         checkReturn(String name, type) {
           var element = findElement(compiler, name);
           Expect.equals(
               type,
-              simplify(typesInferrer.getReturnTypeOfElement(element), compiler),
+              simplify(
+                  typesInferrer.getReturnTypeOfElement(element), closedWorld),
               name);
         }
 
@@ -46,7 +48,7 @@
           Expect.equals(
               type,
               simplify(
-                  typesInferrer.getReturnTypeOfElement(element), compiler));
+                  typesInferrer.getReturnTypeOfElement(element), closedWorld));
         }
 
         checkReturn('bar', commonMasks.uint31Type);
diff --git a/tests/compiler/dart2js/jsinterop/world_test.dart b/tests/compiler/dart2js/jsinterop/world_test.dart
index 074860f..0337799 100644
--- a/tests/compiler/dart2js/jsinterop/world_test.dart
+++ b/tests/compiler/dart2js/jsinterop/world_test.dart
@@ -87,7 +87,7 @@
       return cls;
     }
 
-    ClosedWorld world = env.compiler.closedWorld;
+    ClosedWorld world = env.closedWorld;
     JavaScriptBackend backend = env.compiler.backend;
     ClassElement Object_ = registerClass(env.compiler.coreClasses.objectClass);
     ClassElement Interceptor =
diff --git a/tests/compiler/dart2js/kernel/closed_world_test.dart b/tests/compiler/dart2js/kernel/closed_world_test.dart
index 8b64123..60a4505 100644
--- a/tests/compiler/dart2js/kernel/closed_world_test.dart
+++ b/tests/compiler/dart2js/kernel/closed_world_test.dart
@@ -136,7 +136,7 @@
       }
       return true;
     }, verbose: arguments.verbose);
-    checkClosedWorlds(compiler.closedWorld, closedWorld,
+    checkClosedWorlds(compiler.resolverWorld.closedWorldForTesting, closedWorld,
         verbose: arguments.verbose);
   });
 }
diff --git a/tests/compiler/dart2js/kernel/impact_test.dart b/tests/compiler/dart2js/kernel/impact_test.dart
index fd2467f..90042ef 100644
--- a/tests/compiler/dart2js/kernel/impact_test.dart
+++ b/tests/compiler/dart2js/kernel/impact_test.dart
@@ -168,6 +168,8 @@
   testForwardingConstructorTyped();
   testForwardingConstructorGeneric();
   testEnum();
+  testStaticGenericMethod();
+  testInstanceGenericMethod();
 }
 
 testEmpty() {}
@@ -583,6 +585,15 @@
 
 enum Enum { A }
 testEnum() => Enum.A;
+
+List<T> staticGenericMethod<T>(T arg) => [arg];
+testStaticGenericMethod() {
+  staticGenericMethod<int>(0);
+}
+
+testInstanceGenericMethod() {
+  new GenericClass<int, String>.generative().genericMethod<bool>(false);
+}
 ''',
   'helper.dart': '''
 class Class {
@@ -594,6 +605,8 @@
   const GenericClass.generative();
   factory GenericClass.fact() => null;
   const factory GenericClass.redirect() = GenericClass<X, Y>.generative;
+
+  Map<X, T> genericMethod<T>(T arg) => { null: arg };
 }
 typedef Typedef();
 typedef X GenericTypedef<X, Y>(Y y);
@@ -614,7 +627,9 @@
         ]);
     compiler.resolution.retainCachesForTesting = true;
     await compiler.run(entryPoint);
+    checkLibrary(compiler, compiler.mainApp, fullTest: args.contains('--full'));
     compiler.libraryLoader.libraries.forEach((LibraryElement library) {
+      if (library == compiler.mainApp) return;
       checkLibrary(compiler, library, fullTest: args.contains('--full'));
     });
   });
diff --git a/tests/compiler/dart2js/kernel/try_catch_test.dart b/tests/compiler/dart2js/kernel/try_catch_test.dart
index 972667c..77a1afd 100644
--- a/tests/compiler/dart2js/kernel/try_catch_test.dart
+++ b/tests/compiler/dart2js/kernel/try_catch_test.dart
@@ -93,4 +93,3 @@
     return check(code);
   });
 }
-
diff --git a/tests/compiler/dart2js/list_tracer2_test.dart b/tests/compiler/dart2js/list_tracer2_test.dart
index c0a5166..215b84a 100644
--- a/tests/compiler/dart2js/list_tracer2_test.dart
+++ b/tests/compiler/dart2js/list_tracer2_test.dart
@@ -25,13 +25,14 @@
   var compiler = compilerFor(TEST, uri);
   asyncTest(() => compiler.run(uri).then((_) {
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
 
         checkType(String name, type) {
           var element = findElement(compiler, name);
           ContainerTypeMask mask = typesInferrer.getTypeOfElement(element);
-          Expect.equals(type, simplify(mask.elementType, compiler), name);
+          Expect.equals(type, simplify(mask.elementType, closedWorld), name);
         }
 
-        checkType('myList', compiler.closedWorld.commonMasks.uint31Type);
+        checkType('myList', typesInferrer.closedWorld.commonMasks.uint31Type);
       }));
 }
diff --git a/tests/compiler/dart2js/list_tracer3_test.dart b/tests/compiler/dart2js/list_tracer3_test.dart
index 1e61858..599933c3 100644
--- a/tests/compiler/dart2js/list_tracer3_test.dart
+++ b/tests/compiler/dart2js/list_tracer3_test.dart
@@ -27,16 +27,16 @@
   var compiler = compilerFor(TEST, uri);
   asyncTest(() => compiler.run(uri).then((_) {
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
 
         checkType(String name, type) {
           var element = findElement(compiler, name);
           ContainerTypeMask mask = typesInferrer.getTypeOfElement(element);
-          Expect.equals(type, simplify(mask.elementType, compiler), name);
+          Expect.equals(type, simplify(mask.elementType, closedWorld), name);
         }
 
         var interceptorType =
-            findTypeMask(compiler, 'Interceptor', 'nonNullSubclass');
-
+            typesInferrer.closedWorld.commonMasks.interceptorType;
         checkType('myList', interceptorType);
       }));
 }
diff --git a/tests/compiler/dart2js/list_tracer_test.dart b/tests/compiler/dart2js/list_tracer_test.dart
index c407ce8..e577c9f 100644
--- a/tests/compiler/dart2js/list_tracer_test.dart
+++ b/tests/compiler/dart2js/list_tracer_test.dart
@@ -198,14 +198,15 @@
   var compiler = compilerFor(generateTest(allocation), uri,
       expectedErrors: 0, expectedWarnings: 1);
   asyncTest(() => compiler.run(uri).then((_) {
-        var commonMasks = compiler.closedWorld.commonMasks;
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
+        var commonMasks = closedWorld.commonMasks;
 
         checkType(String name, type) {
           var element = findElement(compiler, name);
           ContainerTypeMask mask = typesInferrer.getTypeOfElement(element);
           if (nullify) type = type.nullable();
-          Expect.equals(type, simplify(mask.elementType, compiler), name);
+          Expect.equals(type, simplify(mask.elementType, closedWorld), name);
         }
 
         checkType('listInField', commonMasks.numType);
diff --git a/tests/compiler/dart2js/list_tracer_typed_data_length_test.dart b/tests/compiler/dart2js/list_tracer_typed_data_length_test.dart
index ee15963..59ede2b 100644
--- a/tests/compiler/dart2js/list_tracer_typed_data_length_test.dart
+++ b/tests/compiler/dart2js/list_tracer_typed_data_length_test.dart
@@ -6,6 +6,7 @@
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/types/types.dart' show ContainerTypeMask, TypeMask;
 import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/world.dart' show ClosedWorld;
 
 import 'memory_compiler.dart';
 import 'compiler_helper.dart' show findElement;
@@ -30,17 +31,18 @@
     CompilationResult result = await runCompiler(memorySourceFiles: TEST);
     Compiler compiler = result.compiler;
     var typesInferrer = compiler.globalInference.typesInferrerInternal;
+    ClosedWorld closedWorld = typesInferrer.closedWorld;
 
     checkType(String name, type, length) {
       var element = findElement(compiler, name);
       TypeMask mask = typesInferrer.getTypeOfElement(element);
       Expect.isTrue(mask.isContainer);
       ContainerTypeMask container = mask;
-      Expect.equals(type, simplify(container.elementType, compiler), name);
+      Expect.equals(type, simplify(container.elementType, closedWorld), name);
       Expect.equals(container.length, length);
     }
 
-    checkType('myList', compiler.closedWorld.commonMasks.numType, 42);
-    checkType('myOtherList', compiler.closedWorld.commonMasks.uint31Type, 32);
+    checkType('myList', closedWorld.commonMasks.numType, 42);
+    checkType('myOtherList', closedWorld.commonMasks.uint31Type, 32);
   });
 }
diff --git a/tests/compiler/dart2js/map_tracer_const_test.dart b/tests/compiler/dart2js/map_tracer_const_test.dart
index 69d9554..69da6a5 100644
--- a/tests/compiler/dart2js/map_tracer_const_test.dart
+++ b/tests/compiler/dart2js/map_tracer_const_test.dart
@@ -33,10 +33,11 @@
   var compiler = compilerFor(TEST, uri, expectedErrors: 0, expectedWarnings: 0);
   compiler.stopAfterTypeInference = true;
   asyncTest(() => compiler.run(uri).then((_) {
-        var commonMasks = compiler.closedWorld.commonMasks;
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
+        var commonMasks = closedWorld.commonMasks;
         var element = findElement(compiler, 'closure');
         var mask = typesInferrer.getReturnTypeOfElement(element);
-        Expect.equals(commonMasks.numType, simplify(mask, compiler));
+        Expect.equals(commonMasks.numType, simplify(mask, closedWorld));
       }));
 }
diff --git a/tests/compiler/dart2js/map_tracer_keys_test.dart b/tests/compiler/dart2js/map_tracer_keys_test.dart
index 4394879..91c1bf3 100644
--- a/tests/compiler/dart2js/map_tracer_keys_test.dart
+++ b/tests/compiler/dart2js/map_tracer_keys_test.dart
@@ -57,8 +57,8 @@
   var compiler = compilerFor(generateTest(key, value, initial), uri,
       expectedErrors: 0, expectedWarnings: 0);
   asyncTest(() => compiler.run(uri).then((_) {
-        var commonMasks = compiler.closedWorld.commonMasks;
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var commonMasks = typesInferrer.closedWorld.commonMasks;
         var aDoubleType =
             typesInferrer.getTypeOfElement(findElement(compiler, 'aDouble'));
         var aListType =
diff --git a/tests/compiler/dart2js/map_tracer_test.dart b/tests/compiler/dart2js/map_tracer_test.dart
index 0bd5289..bab5e22 100644
--- a/tests/compiler/dart2js/map_tracer_test.dart
+++ b/tests/compiler/dart2js/map_tracer_test.dart
@@ -212,11 +212,11 @@
   var compiler = compilerFor(generateTest(allocation), uri,
       expectedErrors: 0, expectedWarnings: 1);
   compiler.closeResolution();
-  var closedWorld = compiler.closedWorld;
   asyncTest(() => compiler.run(uri).then((_) {
         var keyType, valueType;
-        var commonMasks = compiler.closedWorld.commonMasks;
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
+        var commonMasks = closedWorld.commonMasks;
         var emptyType = new TypeMask.nonNullEmpty();
         var aKeyType =
             typesInferrer.getTypeOfElement(findElement(compiler, 'aKey'));
@@ -234,14 +234,15 @@
         checkType(String name, keyType, valueType) {
           var element = findElement(compiler, name);
           MapTypeMask mask = typesInferrer.getTypeOfElement(element);
-          Expect.equals(keyType, simplify(mask.keyType, compiler), name);
-          Expect.equals(valueType, simplify(mask.valueType, compiler), name);
+          Expect.equals(keyType, simplify(mask.keyType, closedWorld), name);
+          Expect.equals(valueType, simplify(mask.valueType, closedWorld), name);
         }
 
         K(TypeMask other) =>
-            simplify(keyType.union(other, closedWorld), compiler);
+            simplify(keyType.union(other, closedWorld), closedWorld);
         V(TypeMask other) =>
-            simplify(valueType.union(other, closedWorld), compiler).nullable();
+            simplify(valueType.union(other, closedWorld), closedWorld)
+                .nullable();
 
         checkType('mapInField', K(aKeyType), V(commonMasks.numType));
         checkType('mapPassedToMethod', K(aKeyType), V(commonMasks.numType));
diff --git a/tests/compiler/dart2js/mirror_final_field_inferrer2_test.dart b/tests/compiler/dart2js/mirror_final_field_inferrer2_test.dart
index 3d5ce6d..4563009 100644
--- a/tests/compiler/dart2js/mirror_final_field_inferrer2_test.dart
+++ b/tests/compiler/dart2js/mirror_final_field_inferrer2_test.dart
@@ -28,9 +28,12 @@
     var result = await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
     var compiler = result.compiler;
     var element = findElement(compiler, 'field');
-    var commonMasks = compiler.closedWorld.commonMasks;
     var typesInferrer = compiler.globalInference.typesInferrerInternal;
-    Expect.equals(commonMasks.uint31Type,
-        simplify(typesInferrer.getTypeOfElement(element), compiler), 'field');
+    var closedWorld = typesInferrer.closedWorld;
+    var commonMasks = closedWorld.commonMasks;
+    Expect.equals(
+        commonMasks.uint31Type,
+        simplify(typesInferrer.getTypeOfElement(element), closedWorld),
+        'field');
   });
 }
diff --git a/tests/compiler/dart2js/mirror_final_field_inferrer_test.dart b/tests/compiler/dart2js/mirror_final_field_inferrer_test.dart
index 78ea487..0934e37 100644
--- a/tests/compiler/dart2js/mirror_final_field_inferrer_test.dart
+++ b/tests/compiler/dart2js/mirror_final_field_inferrer_test.dart
@@ -28,9 +28,12 @@
     var result = await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
     var compiler = result.compiler;
     var element = findElement(compiler, 'field');
-    var commonMasks = compiler.closedWorld.commonMasks;
     var typesInferrer = compiler.globalInference.typesInferrerInternal;
-    Expect.equals(commonMasks.uint31Type,
-        simplify(typesInferrer.getTypeOfElement(element), compiler), 'field');
+    var closedWorld = typesInferrer.closedWorld;
+    var commonMasks = closedWorld.commonMasks;
+    Expect.equals(
+        commonMasks.uint31Type,
+        simplify(typesInferrer.getTypeOfElement(element), closedWorld),
+        'field');
   });
 }
diff --git a/tests/compiler/dart2js/needs_no_such_method_test.dart b/tests/compiler/dart2js/needs_no_such_method_test.dart
index 892087e..6cd1ae6 100644
--- a/tests/compiler/dart2js/needs_no_such_method_test.dart
+++ b/tests/compiler/dart2js/needs_no_such_method_test.dart
@@ -52,7 +52,7 @@
     bar = new Selector.call(const PublicName('bar'), CallStructure.NO_ARGS);
     baz = new Selector.call(const PublicName('baz'), CallStructure.NO_ARGS);
 
-    closedWorld = env.compiler.closedWorld;
+    closedWorld = env.closedWorld;
     superclass = env.getElement('Superclass');
     subclass = env.getElement('Subclass');
     subtype = env.getElement('Subtype');
diff --git a/tests/compiler/dart2js/patch_test.dart b/tests/compiler/dart2js/patch_test.dart
index 4277cd4..523f825 100644
--- a/tests/compiler/dart2js/patch_test.dart
+++ b/tests/compiler/dart2js/patch_test.dart
@@ -974,7 +974,7 @@
       runCompiler: true,
       analyzeOnly: true);
   compiler.closeResolution();
-  ClosedWorld world = compiler.closedWorld;
+  ClosedWorld world = compiler.resolverWorld.closedWorldForTesting;
 
   ClassElement cls = ensure(
       compiler, "A", compiler.commonElements.coreLibrary.find,
diff --git a/tests/compiler/dart2js/related_types.dart b/tests/compiler/dart2js/related_types.dart
index af65613..61203ec 100644
--- a/tests/compiler/dart2js/related_types.dart
+++ b/tests/compiler/dart2js/related_types.dart
@@ -36,7 +36,6 @@
 /// Check all loaded libraries in [compiler] for unrelated types.
 void checkRelatedTypes(Compiler compiler) {
   compiler.closeResolution();
-  compiler.closedWorld;
   for (LibraryElement library in compiler.libraryLoader.libraries) {
     checkLibraryElement(compiler, library);
   }
@@ -78,7 +77,7 @@
       : this.resolvedAst = resolvedAst,
         super(resolvedAst.elements);
 
-  ClosedWorld get world => compiler.closedWorld;
+  ClosedWorld get world => compiler.resolverWorld.closedWorldForTesting;
 
   CoreClasses get coreClasses => compiler.coreClasses;
 
diff --git a/tests/compiler/dart2js/serialization/model_test_helper.dart b/tests/compiler/dart2js/serialization/model_test_helper.dart
index e970d22..735205d 100644
--- a/tests/compiler/dart2js/serialization/model_test_helper.dart
+++ b/tests/compiler/dart2js/serialization/model_test_helper.dart
@@ -98,8 +98,8 @@
     checkResolutionEnqueuers(compilerNormal.enqueuer.resolution,
         compilerDeserialized.enqueuer.resolution,
         verbose: verbose);
-    checkClosedWorlds(
-        compilerNormal.closedWorld, compilerDeserialized.closedWorld,
+    checkClosedWorlds(compilerNormal.resolverWorld.closedWorldForTesting,
+        compilerDeserialized.resolverWorld.closedWorldForTesting,
         verbose: verbose);
     checkBackendInfo(compilerNormal, compilerDeserialized, verbose: verbose);
   });
diff --git a/tests/compiler/dart2js/simple_inferrer_and_or_test.dart b/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
index 2c81edc..edb66ec 100644
--- a/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
@@ -97,32 +97,31 @@
   var compiler = compilerFor(TEST, uri);
   asyncTest(() => compiler.run(uri).then((_) {
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
 
         checkReturn(String name, type) {
           var element = findElement(compiler, name);
           Expect.equals(
               type,
               simplify(
-                  typesInferrer.getReturnTypeOfElement(element), compiler));
+                  typesInferrer.getReturnTypeOfElement(element), closedWorld));
         }
 
-        var subclassOfInterceptor =
-            findTypeMask(compiler, 'Interceptor', 'nonNullSubclass');
+        var subclassOfInterceptor = closedWorld.commonMasks.interceptorType;
 
         checkReturn('returnDyn1', subclassOfInterceptor);
         checkReturn('returnDyn2', subclassOfInterceptor);
         checkReturn('returnDyn3', subclassOfInterceptor);
-        checkReturn('returnDyn4',
-            compiler.closedWorld.commonMasks.dynamicType.nonNullable());
-        checkReturn('returnDyn5',
-            compiler.closedWorld.commonMasks.dynamicType.nonNullable());
-        checkReturn('returnDyn6',
-            compiler.closedWorld.commonMasks.dynamicType.nonNullable());
+        checkReturn(
+            'returnDyn4', closedWorld.commonMasks.dynamicType.nonNullable());
+        checkReturn(
+            'returnDyn5', closedWorld.commonMasks.dynamicType.nonNullable());
+        checkReturn(
+            'returnDyn6', closedWorld.commonMasks.dynamicType.nonNullable());
         checkReturn('returnDyn7', subclassOfInterceptor);
         checkReturn('returnDyn7b', subclassOfInterceptor);
         checkReturn('returnDyn8', subclassOfInterceptor);
         checkReturn('returnDyn9', subclassOfInterceptor);
-        checkReturn(
-            'returnString', compiler.closedWorld.commonMasks.stringType);
+        checkReturn('returnString', closedWorld.commonMasks.stringType);
       }));
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_callers_test.dart b/tests/compiler/dart2js/simple_inferrer_callers_test.dart
index a6ca00e..dc2b4f9 100644
--- a/tests/compiler/dart2js/simple_inferrer_callers_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_callers_test.dart
@@ -8,7 +8,7 @@
 import 'package:async_helper/async_helper.dart';
 import 'package:expect/expect.dart';
 import 'package:compiler/src/inferrer/type_graph_inferrer.dart';
-import 'package:compiler/src/world.dart' show ClosedWorldRefiner;
+import 'package:compiler/src/world.dart' show ClosedWorld, ClosedWorldRefiner;
 
 import 'compiler_helper.dart';
 
@@ -40,11 +40,12 @@
   var compiler = compilerFor(TEST, uri, analyzeOnly: true);
   asyncTest(() => compiler.run(uri).then((_) {
         ClosedWorldRefiner closedWorldRefiner = compiler.closeResolution();
+        ClosedWorld closedWorld = compiler.resolverWorld.closedWorldForTesting;
         var inferrer =
-            new MyInferrer(compiler, compiler.closedWorld, closedWorldRefiner);
+            new MyInferrer(compiler, closedWorld, closedWorldRefiner);
         compiler.globalInference.typesInferrerInternal = inferrer;
         compiler.globalInference.runGlobalTypeInference(
-            compiler.mainFunction, compiler.closedWorld, closedWorldRefiner);
+            compiler.mainFunction, closedWorld, closedWorldRefiner);
         var mainElement = findElement(compiler, 'main');
         var classA = findElement(compiler, 'A');
         var fieldA = classA.lookupLocalMember('field');
diff --git a/tests/compiler/dart2js/simple_inferrer_closure_test.dart b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
index 109f197..39e5811 100644
--- a/tests/compiler/dart2js/simple_inferrer_closure_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
@@ -119,29 +119,31 @@
   var compiler = compilerFor(TEST, uri);
   asyncTest(() => compiler.run(uri).then((_) {
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
 
         checkReturn(String name, type) {
           var element = findElement(compiler, name);
           Expect.equals(
               type,
-              simplify(typesInferrer.getReturnTypeOfElement(element), compiler),
+              simplify(
+                  typesInferrer.getReturnTypeOfElement(element), closedWorld),
               name);
         }
 
-        checkReturn('returnInt1', compiler.closedWorld.commonMasks.uint31Type);
-        checkReturn('returnInt2', compiler.closedWorld.commonMasks.uint31Type);
-        checkReturn('returnInt3', compiler.closedWorld.commonMasks.uint31Type);
-        checkReturn('returnInt4', compiler.closedWorld.commonMasks.uint31Type);
-        checkReturn('returnIntOrNull',
-            compiler.closedWorld.commonMasks.uint31Type.nullable());
+        checkReturn('returnInt1', closedWorld.commonMasks.uint31Type);
+        checkReturn('returnInt2', closedWorld.commonMasks.uint31Type);
+        checkReturn('returnInt3', closedWorld.commonMasks.uint31Type);
+        checkReturn('returnInt4', closedWorld.commonMasks.uint31Type);
+        checkReturn(
+            'returnIntOrNull', closedWorld.commonMasks.uint31Type.nullable());
 
-        checkReturn('returnDyn1',
-            compiler.closedWorld.commonMasks.dynamicType.nonNullable());
-        checkReturn('returnDyn2',
-            compiler.closedWorld.commonMasks.dynamicType.nonNullable());
-        checkReturn('returnDyn3',
-            compiler.closedWorld.commonMasks.dynamicType.nonNullable());
-        checkReturn('returnNum1', compiler.closedWorld.commonMasks.numType);
+        checkReturn(
+            'returnDyn1', closedWorld.commonMasks.dynamicType.nonNullable());
+        checkReturn(
+            'returnDyn2', closedWorld.commonMasks.dynamicType.nonNullable());
+        checkReturn(
+            'returnDyn3', closedWorld.commonMasks.dynamicType.nonNullable());
+        checkReturn('returnNum1', closedWorld.commonMasks.numType);
 
         checkReturnInClass(String className, String methodName, type) {
           var cls = findElement(compiler, className);
@@ -149,11 +151,11 @@
           Expect.equals(
               type,
               simplify(
-                  typesInferrer.getReturnTypeOfElement(element), compiler));
+                  typesInferrer.getReturnTypeOfElement(element), closedWorld));
         }
 
         var cls = findElement(compiler, 'A');
         checkReturnInClass(
-            'A', 'foo', new TypeMask.nonNullExact(cls, compiler.closedWorld));
+            'A', 'foo', new TypeMask.nonNullExact(cls, closedWorld));
       }));
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_const_closure2_test.dart b/tests/compiler/dart2js/simple_inferrer_const_closure2_test.dart
index 2e59a21..c4c9194 100644
--- a/tests/compiler/dart2js/simple_inferrer_const_closure2_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_const_closure2_test.dart
@@ -29,6 +29,7 @@
   var compiler = compilerFor(TEST, uri);
   asyncTest(() => compiler.run(uri).then((_) {
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
 
         checkReturn(String name, type) {
           var element = findElement(compiler, name);
@@ -38,7 +39,7 @@
               name);
         }
 
-        checkReturn('method', compiler.closedWorld.commonMasks.numType);
-        checkReturn('returnNum', compiler.closedWorld.commonMasks.numType);
+        checkReturn('method', closedWorld.commonMasks.numType);
+        checkReturn('returnNum', closedWorld.commonMasks.numType);
       }));
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_const_closure3_test.dart b/tests/compiler/dart2js/simple_inferrer_const_closure3_test.dart
index a354985..af85fa9 100644
--- a/tests/compiler/dart2js/simple_inferrer_const_closure3_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_const_closure3_test.dart
@@ -29,6 +29,7 @@
   var compiler = compilerFor(TEST, uri);
   asyncTest(() => compiler.run(uri).then((_) {
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
 
         checkArgument(String functionName, type) {
           var functionElement = findElement(compiler, functionName);
@@ -36,10 +37,10 @@
           var element = signature.requiredParameters.first;
           Expect.equals(
               type,
-              simplify(typesInferrer.getTypeOfElement(element), compiler),
+              simplify(typesInferrer.getTypeOfElement(element), closedWorld),
               functionName);
         }
 
-        checkArgument('method', compiler.closedWorld.commonMasks.uint31Type);
+        checkArgument('method', closedWorld.commonMasks.uint31Type);
       }));
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_const_closure4_test.dart b/tests/compiler/dart2js/simple_inferrer_const_closure4_test.dart
index eeeeb02..2a2fd62 100644
--- a/tests/compiler/dart2js/simple_inferrer_const_closure4_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_const_closure4_test.dart
@@ -30,6 +30,7 @@
   var compiler = compilerFor(TEST, uri);
   asyncTest(() => compiler.run(uri).then((_) {
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
 
         checkArgument(String functionName, type) {
           var functionElement = findElement(compiler, functionName);
@@ -37,11 +38,11 @@
           var element = signature.requiredParameters.first;
           Expect.equals(
               type,
-              simplify(typesInferrer.getTypeOfElement(element), compiler),
+              simplify(typesInferrer.getTypeOfElement(element), closedWorld),
               functionName);
         }
 
-        checkArgument('method', compiler.closedWorld.commonMasks.numType);
-        checkArgument('returnNum', compiler.closedWorld.commonMasks.numType);
+        checkArgument('method', closedWorld.commonMasks.numType);
+        checkArgument('returnNum', closedWorld.commonMasks.numType);
       }));
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_const_closure5_test.dart b/tests/compiler/dart2js/simple_inferrer_const_closure5_test.dart
index a41c254..41b5feb 100644
--- a/tests/compiler/dart2js/simple_inferrer_const_closure5_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_const_closure5_test.dart
@@ -30,6 +30,7 @@
   var compiler = compilerFor(TEST, uri);
   asyncTest(() => compiler.run(uri).then((_) {
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
 
         checkArgument(String functionName, type) {
           var functionElement = findElement(compiler, functionName);
@@ -37,10 +38,10 @@
           var element = signature.requiredParameters.first;
           Expect.equals(
               type,
-              simplify(typesInferrer.getTypeOfElement(element), compiler),
+              simplify(typesInferrer.getTypeOfElement(element), closedWorld),
               functionName);
         }
 
-        checkArgument('method', compiler.closedWorld.commonMasks.numType);
+        checkArgument('method', typesInferrer.closedWorld.commonMasks.numType);
       }));
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_const_closure_default_test.dart b/tests/compiler/dart2js/simple_inferrer_const_closure_default_test.dart
index f2d38c6..ce1cc2c 100644
--- a/tests/compiler/dart2js/simple_inferrer_const_closure_default_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_const_closure_default_test.dart
@@ -43,6 +43,7 @@
   var compiler = compilerFor(TEST, uri);
   asyncTest(() => compiler.run(uri).then((_) {
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
 
         checkArgument(String functionName, type) {
           var functionElement = findElement(compiler, functionName);
@@ -52,7 +53,7 @@
               : signature.optionalParameters.first;
           Expect.equals(
               type,
-              simplify(typesInferrer.getTypeOfElement(element), compiler),
+              simplify(typesInferrer.getTypeOfElement(element), closedWorld),
               functionName);
         }
 
@@ -62,51 +63,45 @@
           var element = signature.optionalParameters.first;
           Expect.equals(
               type,
-              simplify(typesInferrer.getTypeOfElement(element), compiler),
+              simplify(typesInferrer.getTypeOfElement(element), closedWorld),
               functionName);
         }
 
-        checkArgument('foo1', compiler.closedWorld.commonMasks.functionType);
+        checkArgument('foo1', closedWorld.commonMasks.functionType);
 
         /// 01: ok
-        checkArgument('foo2', compiler.closedWorld.commonMasks.functionType);
+        checkArgument('foo2', closedWorld.commonMasks.functionType);
 
         /// 02: ok
-        checkArgument('foo3', compiler.closedWorld.commonMasks.functionType);
+        checkArgument('foo3', closedWorld.commonMasks.functionType);
 
         /// 03: ok
-        checkArgument('foo4', compiler.closedWorld.commonMasks.functionType);
+        checkArgument('foo4', closedWorld.commonMasks.functionType);
 
         /// 04: ok
-        checkArgument('foo5', compiler.closedWorld.commonMasks.dynamicType);
+        checkArgument('foo5', closedWorld.commonMasks.dynamicType);
 
         /// 05: ok
-        checkArgument('foo6', compiler.closedWorld.commonMasks.dynamicType);
+        checkArgument('foo6', closedWorld.commonMasks.dynamicType);
 
         /// 06: ok
 
-        checkArgument(
-            'defaultFn1', compiler.closedWorld.commonMasks.uint31Type);
+        checkArgument('defaultFn1', closedWorld.commonMasks.uint31Type);
 
         /// 07: ok
-        checkArgument(
-            'defaultFn2', compiler.closedWorld.commonMasks.uint31Type);
+        checkArgument('defaultFn2', closedWorld.commonMasks.uint31Type);
 
         /// 08: ok
-        checkArgument(
-            'defaultFn3', compiler.closedWorld.commonMasks.uint31Type);
+        checkArgument('defaultFn3', closedWorld.commonMasks.uint31Type);
 
         /// 09: ok
-        checkArgument(
-            'defaultFn4', compiler.closedWorld.commonMasks.uint31Type);
+        checkArgument('defaultFn4', closedWorld.commonMasks.uint31Type);
 
         /// 10: ok
-        checkArgument(
-            'defaultFn5', compiler.closedWorld.commonMasks.uint31Type);
+        checkArgument('defaultFn5', closedWorld.commonMasks.uint31Type);
 
         /// 11: ok
-        checkArgument(
-            'defaultFn6', compiler.closedWorld.commonMasks.uint31Type);
+        checkArgument('defaultFn6', closedWorld.commonMasks.uint31Type);
 
         /// 12: ok
       }));
diff --git a/tests/compiler/dart2js/simple_inferrer_const_closure_test.dart b/tests/compiler/dart2js/simple_inferrer_const_closure_test.dart
index 6dbd781..6183de0 100644
--- a/tests/compiler/dart2js/simple_inferrer_const_closure_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_const_closure_test.dart
@@ -38,6 +38,7 @@
   var compiler = compilerFor(TEST, uri);
   asyncTest(() => compiler.run(uri).then((_) {
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
 
         checkReturn(String name, type) {
           var element = findElement(compiler, name);
@@ -47,10 +48,10 @@
               name);
         }
 
-        checkReturn('method1', compiler.closedWorld.commonMasks.uint31Type);
-        checkReturn('returnInt1', compiler.closedWorld.commonMasks.uint31Type);
+        checkReturn('method1', closedWorld.commonMasks.uint31Type);
+        checkReturn('returnInt1', closedWorld.commonMasks.uint31Type);
 
-        checkReturn('method2', compiler.closedWorld.commonMasks.uint31Type);
-        checkReturn('returnInt2', compiler.closedWorld.commonMasks.uint31Type);
+        checkReturn('method2', closedWorld.commonMasks.uint31Type);
+        checkReturn('returnInt2', closedWorld.commonMasks.uint31Type);
       }));
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart
index 7eeefae..c321c54 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart
@@ -28,15 +28,16 @@
   var compiler = compilerFor(TEST, uri);
   asyncTest(() => compiler.run(uri).then((_) {
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
 
         checkFieldTypeInClass(String className, String fieldName, type) {
           var cls = findElement(compiler, className);
           var element = cls.lookupLocalMember(fieldName);
           Expect.equals(type,
-              simplify(typesInferrer.getTypeOfElement(element), compiler));
+              simplify(typesInferrer.getTypeOfElement(element), closedWorld));
         }
 
-        checkFieldTypeInClass('A', 'dynamicField',
-            findTypeMask(compiler, 'Interceptor', 'nonNullSubclass'));
+        checkFieldTypeInClass(
+            'A', 'dynamicField', closedWorld.commonMasks.interceptorType);
       }));
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
index 78b3ebc..7b14057 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
@@ -32,21 +32,22 @@
   var compiler = compilerFor(TEST, uri);
   asyncTest(() => compiler.run(uri).then((_) {
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
 
         checkFieldTypeInClass(String className, String fieldName, type) {
           var cls = findElement(compiler, className);
           var element = cls.lookupLocalMember(fieldName);
           Expect.equals(type,
-              simplify(typesInferrer.getTypeOfElement(element), compiler));
+              simplify(typesInferrer.getTypeOfElement(element), closedWorld));
         }
 
         checkFieldTypeInClass(
-            'A', 'intField', compiler.closedWorld.commonMasks.uint31Type);
-        checkFieldTypeInClass('A', 'giveUpField1',
-            findTypeMask(compiler, 'Interceptor', 'nonNullSubclass'));
-        checkFieldTypeInClass('A', 'giveUpField2',
-            compiler.closedWorld.commonMasks.dynamicType.nonNullable());
+            'A', 'intField', closedWorld.commonMasks.uint31Type);
         checkFieldTypeInClass(
-            'A', 'fieldParameter', compiler.closedWorld.commonMasks.uint31Type);
+            'A', 'giveUpField1', closedWorld.commonMasks.interceptorType);
+        checkFieldTypeInClass('A', 'giveUpField2',
+            closedWorld.commonMasks.dynamicType.nonNullable());
+        checkFieldTypeInClass(
+            'A', 'fieldParameter', closedWorld.commonMasks.uint31Type);
       }));
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_global_field_closure2_test.dart b/tests/compiler/dart2js/simple_inferrer_global_field_closure2_test.dart
index 01a896a..35969e1 100644
--- a/tests/compiler/dart2js/simple_inferrer_global_field_closure2_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_global_field_closure2_test.dart
@@ -29,6 +29,7 @@
   var compiler = compilerFor(TEST, uri);
   asyncTest(() => compiler.run(uri).then((_) {
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
 
         checkArgument(String functionName, type) {
           var functionElement = findElement(compiler, functionName);
@@ -36,10 +37,10 @@
           var element = signature.requiredParameters.first;
           Expect.equals(
               type,
-              simplify(typesInferrer.getTypeOfElement(element), compiler),
+              simplify(typesInferrer.getTypeOfElement(element), closedWorld),
               functionName);
         }
 
-        checkArgument('method', compiler.closedWorld.commonMasks.uint31Type);
+        checkArgument('method', closedWorld.commonMasks.uint31Type);
       }));
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_global_field_closure_test.dart b/tests/compiler/dart2js/simple_inferrer_global_field_closure_test.dart
index f20912a..430f464 100644
--- a/tests/compiler/dart2js/simple_inferrer_global_field_closure_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_global_field_closure_test.dart
@@ -38,6 +38,7 @@
   var compiler = compilerFor(TEST, uri);
   asyncTest(() => compiler.run(uri).then((_) {
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
 
         checkReturn(String name, type) {
           var element = findElement(compiler, name);
@@ -47,10 +48,10 @@
               name);
         }
 
-        checkReturn('method1', compiler.closedWorld.commonMasks.uint31Type);
-        checkReturn('returnInt1', compiler.closedWorld.commonMasks.uint31Type);
+        checkReturn('method1', closedWorld.commonMasks.uint31Type);
+        checkReturn('returnInt1', closedWorld.commonMasks.uint31Type);
 
-        checkReturn('method2', compiler.closedWorld.commonMasks.uint31Type);
-        checkReturn('returnInt2', compiler.closedWorld.commonMasks.uint31Type);
+        checkReturn('method2', closedWorld.commonMasks.uint31Type);
+        checkReturn('returnInt2', closedWorld.commonMasks.uint31Type);
       }));
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart b/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart
index a68120c..dcddd20 100644
--- a/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart
@@ -160,88 +160,82 @@
 }
 """;
 
-main() {
+checkReturn(MockCompiler compiler, String name, type) {
+  var typesInferrer = compiler.globalInference.typesInferrerInternal;
+  var element = findElement(compiler, name);
+  Expect.equals(
+      type,
+      simplify(typesInferrer.getReturnTypeOfElement(element),
+          typesInferrer.closedWorld),
+      name);
+}
+
+test1() async {
   Uri uri = new Uri(scheme: 'source');
+  var compiler = compilerFor(TEST1, uri);
+  await compiler.run(uri);
+  var closedWorld = compiler.resolverWorld.closedWorldForTesting;
+  checkReturn(compiler, 'test1', closedWorld.commonMasks.uint31Type);
+  checkReturn(
+      compiler, 'test2', closedWorld.commonMasks.dynamicType.nonNullable());
+  checkReturn(compiler, 'test3', closedWorld.commonMasks.uint31Type);
+  checkReturn(compiler, 'test4', closedWorld.commonMasks.mapType);
+  checkReturn(
+      compiler, 'test5', closedWorld.commonMasks.dynamicType.nonNullable());
+  checkReturn(
+      compiler, 'test6', closedWorld.commonMasks.dynamicType.nonNullable());
+}
 
-  checkReturn(MockCompiler compiler, String name, type) {
-    var typesInferrer = compiler.globalInference.typesInferrerInternal;
-    var element = findElement(compiler, name);
-    Expect.equals(
-        type,
-        simplify(typesInferrer.getReturnTypeOfElement(element), compiler),
-        name);
-  }
+test2() async {
+  Uri uri = new Uri(scheme: 'source');
+  var compiler = compilerFor(TEST2, uri);
+  await compiler.run(uri);
+  var closedWorld = compiler.resolverWorld.closedWorldForTesting;
+  checkReturn(compiler, 'test1', closedWorld.commonMasks.mapType.nonNullable());
+  checkReturn(compiler, 'test2', closedWorld.commonMasks.mapType);
+  checkReturn(compiler, 'test3', closedWorld.commonMasks.mapType);
+  checkReturn(compiler, 'test4', closedWorld.commonMasks.mapType);
+  checkReturn(compiler, 'test5', closedWorld.commonMasks.mapType);
 
-  var compiler1 = compilerFor(TEST1, uri);
-  asyncTest(() => compiler1.run(uri).then((_) {
-        checkReturn(
-            compiler1, 'test1', compiler1.closedWorld.commonMasks.uint31Type);
-        checkReturn(compiler1, 'test2',
-            compiler1.closedWorld.commonMasks.dynamicType.nonNullable());
-        checkReturn(
-            compiler1, 'test3', compiler1.closedWorld.commonMasks.uint31Type);
-        checkReturn(
-            compiler1, 'test4', compiler1.closedWorld.commonMasks.mapType);
-        checkReturn(compiler1, 'test5',
-            compiler1.closedWorld.commonMasks.dynamicType.nonNullable());
-        checkReturn(compiler1, 'test6',
-            compiler1.closedWorld.commonMasks.dynamicType.nonNullable());
-      }));
+  checkReturn(compiler, 'test6', closedWorld.commonMasks.numType);
+  checkReturn(compiler, 'test7', closedWorld.commonMasks.uint31Type);
+  checkReturn(compiler, 'test8', closedWorld.commonMasks.uint31Type);
+  checkReturn(compiler, 'test9', closedWorld.commonMasks.uint31Type);
+  checkReturn(compiler, 'test10', closedWorld.commonMasks.numType);
+  checkReturn(compiler, 'test11', closedWorld.commonMasks.doubleType);
+}
 
-  var compiler2 = compilerFor(TEST2, uri);
-  asyncTest(() => compiler2.run(uri).then((_) {
-        checkReturn(compiler2, 'test1',
-            compiler2.closedWorld.commonMasks.mapType.nonNullable());
-        checkReturn(
-            compiler2, 'test2', compiler2.closedWorld.commonMasks.mapType);
-        checkReturn(
-            compiler2, 'test3', compiler2.closedWorld.commonMasks.mapType);
-        checkReturn(
-            compiler2, 'test4', compiler2.closedWorld.commonMasks.mapType);
-        checkReturn(
-            compiler2, 'test5', compiler2.closedWorld.commonMasks.mapType);
+test3() async {
+  Uri uri = new Uri(scheme: 'source');
+  var compiler = compilerFor(TEST3, uri);
+  await compiler.run(uri);
+  var closedWorld = compiler.resolverWorld.closedWorldForTesting;
+  checkReturn(compiler, 'test1', const TypeMask.nonNullEmpty());
+  checkReturn(compiler, 'test2', closedWorld.commonMasks.mapType);
+  checkReturn(compiler, 'test3', closedWorld.commonMasks.mapType);
+  checkReturn(compiler, 'test4', closedWorld.commonMasks.mapType);
+  checkReturn(compiler, 'test5', closedWorld.commonMasks.mapType);
+  checkReturn(compiler, 'test6', closedWorld.commonMasks.mapType);
+}
 
-        checkReturn(
-            compiler2, 'test6', compiler2.closedWorld.commonMasks.numType);
-        checkReturn(
-            compiler2, 'test7', compiler2.closedWorld.commonMasks.uint31Type);
-        checkReturn(
-            compiler2, 'test8', compiler2.closedWorld.commonMasks.uint31Type);
-        checkReturn(
-            compiler2, 'test9', compiler2.closedWorld.commonMasks.uint31Type);
-        checkReturn(
-            compiler2, 'test10', compiler2.closedWorld.commonMasks.numType);
-        checkReturn(
-            compiler2, 'test11', compiler2.closedWorld.commonMasks.doubleType);
-      }));
+test4() async {
+  Uri uri = new Uri(scheme: 'source');
+  var compiler = compilerFor(TEST4, uri);
+  await compiler.run(uri);
+  var closedWorld = compiler.resolverWorld.closedWorldForTesting;
+  checkReturn(compiler, 'test1', const TypeMask.nonNullEmpty());
+  checkReturn(compiler, 'test2', closedWorld.commonMasks.mapType);
+  checkReturn(compiler, 'test3', closedWorld.commonMasks.mapType);
+  checkReturn(compiler, 'test4', closedWorld.commonMasks.mapType);
+  checkReturn(compiler, 'test5', closedWorld.commonMasks.mapType);
+  checkReturn(compiler, 'test6', closedWorld.commonMasks.mapType);
+}
 
-  var compiler3 = compilerFor(TEST3, uri);
-  asyncTest(() => compiler3.run(uri).then((_) {
-        checkReturn(compiler3, 'test1', const TypeMask.nonNullEmpty());
-        checkReturn(
-            compiler3, 'test2', compiler3.closedWorld.commonMasks.mapType);
-        checkReturn(
-            compiler3, 'test3', compiler3.closedWorld.commonMasks.mapType);
-        checkReturn(
-            compiler3, 'test4', compiler3.closedWorld.commonMasks.mapType);
-        checkReturn(
-            compiler3, 'test5', compiler3.closedWorld.commonMasks.mapType);
-        checkReturn(
-            compiler3, 'test6', compiler3.closedWorld.commonMasks.mapType);
-      }));
-
-  var compiler4 = compilerFor(TEST4, uri);
-  asyncTest(() => compiler4.run(uri).then((_) {
-        checkReturn(compiler4, 'test1', const TypeMask.nonNullEmpty());
-        checkReturn(
-            compiler4, 'test2', compiler4.closedWorld.commonMasks.mapType);
-        checkReturn(
-            compiler4, 'test3', compiler4.closedWorld.commonMasks.mapType);
-        checkReturn(
-            compiler4, 'test4', compiler4.closedWorld.commonMasks.mapType);
-        checkReturn(
-            compiler4, 'test5', compiler4.closedWorld.commonMasks.mapType);
-        checkReturn(
-            compiler4, 'test6', compiler4.closedWorld.commonMasks.mapType);
-      }));
+main() {
+  asyncTest(() async {
+    await test1();
+    await test2();
+    await test3();
+    await test4();
+  });
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart b/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart
index 3d37e58..27ed1a4 100644
--- a/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart
@@ -66,20 +66,21 @@
   Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(TEST, uri);
   asyncTest(() => compiler.run(uri).then((_) {
-        var commonMasks = compiler.closedWorld.commonMasks;
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
+        var commonMasks = closedWorld.commonMasks;
 
         checkReturnInClass(String className, String methodName, type) {
           var cls = findElement(compiler, className);
           var element = cls.lookupLocalMember(methodName);
           Expect.equals(
               type,
-              simplify(typesInferrer.getReturnTypeOfElement(element), compiler),
+              simplify(
+                  typesInferrer.getReturnTypeOfElement(element), closedWorld),
               methodName);
         }
 
-        var subclassOfInterceptor =
-            findTypeMask(compiler, 'Interceptor', 'nonNullSubclass');
+        var subclassOfInterceptor = commonMasks.interceptorType;
 
         checkReturnInClass('A', 'returnNum1', commonMasks.numType);
         checkReturnInClass('A', 'returnNum2', commonMasks.numType);
diff --git a/tests/compiler/dart2js/simple_inferrer_test.dart b/tests/compiler/dart2js/simple_inferrer_test.dart
index cf29a1a..08b5620 100644
--- a/tests/compiler/dart2js/simple_inferrer_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_test.dart
@@ -727,20 +727,20 @@
   var compiler = compilerFor(TEST, uri);
   compiler.diagnosticHandler = createHandler(compiler, TEST);
   asyncTest(() => compiler.run(uri).then((_) {
-        var commonMasks = compiler.closedWorld.commonMasks;
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
-        var world = compiler.closedWorld;
+        var closedWorld = typesInferrer.closedWorld;
+        var commonMasks = closedWorld.commonMasks;
 
         checkReturn(String name, type) {
           var element = findElement(compiler, name);
           Expect.equals(
               type,
-              simplify(typesInferrer.getReturnTypeOfElement(element), compiler),
+              simplify(
+                  typesInferrer.getReturnTypeOfElement(element), closedWorld),
               name);
         }
 
-        var interceptorType =
-            findTypeMask(compiler, 'Interceptor', 'nonNullSubclass');
+        var interceptorType = commonMasks.interceptorType;
 
         checkReturn('returnNum1', commonMasks.numType);
         checkReturn('returnNum2', commonMasks.numType);
@@ -761,7 +761,7 @@
         checkReturn('returnEmpty1', const TypeMask.nonNullEmpty());
         checkReturn('returnEmpty2', const TypeMask.nonNullEmpty());
         TypeMask intType = new TypeMask.nonNullSubtype(
-            compiler.coreClasses.intClass, compiler.closedWorld);
+            compiler.coreClasses.intClass, closedWorld);
         checkReturn('testIsCheck1', intType);
         checkReturn('testIsCheck2', intType);
         checkReturn('testIsCheck3', intType.nullable());
@@ -796,7 +796,7 @@
         checkReturn(
             'returnAsString',
             new TypeMask.subtype(
-                compiler.coreClasses.stringClass, compiler.closedWorld));
+                compiler.coreClasses.stringClass, closedWorld));
         checkReturn('returnIntAsNum', commonMasks.uint31Type);
         checkReturn('returnAsTypedef', commonMasks.functionType.nullable());
         checkReturn('returnTopLevelGetter', commonMasks.uint31Type);
@@ -806,9 +806,9 @@
             'testSwitch1',
             simplify(
                 commonMasks.intType
-                    .union(commonMasks.doubleType, compiler.closedWorld)
+                    .union(commonMasks.doubleType, closedWorld)
                     .nullable(),
-                compiler));
+                closedWorld));
         checkReturn('testSwitch2', commonMasks.uint31Type);
         checkReturn('testSwitch3', interceptorType.nullable());
         checkReturn('testSwitch4', commonMasks.uint31Type);
@@ -832,7 +832,8 @@
           var element = cls.lookupLocalMember(methodName);
           Expect.equals(
               type,
-              simplify(typesInferrer.getReturnTypeOfElement(element), compiler),
+              simplify(
+                  typesInferrer.getReturnTypeOfElement(element), closedWorld),
               '$className:$methodName');
         }
 
@@ -864,7 +865,7 @@
         checkFactoryConstructor(String className, String factoryName) {
           var cls = findElement(compiler, className);
           var element = cls.localLookup(factoryName);
-          Expect.equals(new TypeMask.nonNullExact(cls, world),
+          Expect.equals(new TypeMask.nonNullExact(cls, closedWorld),
               typesInferrer.getReturnTypeOfElement(element));
         }
 
@@ -874,7 +875,7 @@
         checkReturn(
             'testCascade2',
             new TypeMask.nonNullExact(
-                findElement(compiler, 'CascadeHelper'), world));
+                findElement(compiler, 'CascadeHelper'), closedWorld));
         checkReturn('testSpecialization1', commonMasks.numType);
         checkReturn('testSpecialization2', commonMasks.dynamicType);
         checkReturn('testSpecialization3', commonMasks.uint31Type.nullable());
diff --git a/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
index 207a861..b6fc660 100644
--- a/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
@@ -167,15 +167,16 @@
   Uri uri = new Uri(scheme: 'source');
   var compiler = compilerFor(TEST, uri);
   asyncTest(() => compiler.run(uri).then((_) {
-        var commonMasks = compiler.closedWorld.commonMasks;
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
+        var commonMasks = closedWorld.commonMasks;
 
         checkReturn(String name, type) {
           var element = findElement(compiler, name);
           Expect.equals(
               type,
               simplify(
-                  typesInferrer.getReturnTypeOfElement(element), compiler));
+                  typesInferrer.getReturnTypeOfElement(element), closedWorld));
         }
 
         checkReturn('returnInt1', commonMasks.uint31Type);
@@ -186,10 +187,9 @@
         checkReturn(
             'returnInt6',
             new TypeMask.nonNullSubtype(
-                compiler.coreClasses.intClass, compiler.closedWorld));
+                closedWorld.coreClasses.intClass, closedWorld));
 
-        var subclassOfInterceptor =
-            findTypeMask(compiler, 'Interceptor', 'nonNullSubclass');
+        var subclassOfInterceptor = commonMasks.interceptorType;
 
         checkReturn('returnDyn1', subclassOfInterceptor);
         checkReturn('returnDyn2', subclassOfInterceptor);
diff --git a/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart b/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart
index f0be6f8..8456a95 100644
--- a/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart
@@ -41,6 +41,6 @@
         }
 
         checkReturnInClass(
-            'A', '+', compiler.closedWorld.commonMasks.uint31Type);
+            'A', '+', typesInferrer.closedWorld.commonMasks.uint31Type);
       }));
 }
diff --git a/tests/compiler/dart2js/subtypeset_test.dart b/tests/compiler/dart2js/subtypeset_test.dart
index 1f0fd7f..418e547 100644
--- a/tests/compiler/dart2js/subtypeset_test.dart
+++ b/tests/compiler/dart2js/subtypeset_test.dart
@@ -47,7 +47,7 @@
       """,
               useMockCompiler: false)
           .then((env) {
-        ClosedWorld world = env.compiler.closedWorld;
+        ClosedWorld world = env.closedWorld;
 
         ClassElement A = env.getElement("A");
         ClassElement B = env.getElement("B");
diff --git a/tests/compiler/dart2js/trust_type_annotations_test.dart b/tests/compiler/dart2js/trust_type_annotations_test.dart
index 764e5ef..70fb5f1 100644
--- a/tests/compiler/dart2js/trust_type_annotations_test.dart
+++ b/tests/compiler/dart2js/trust_type_annotations_test.dart
@@ -51,6 +51,7 @@
   var compiler = compilerFor(TEST, uri, trustTypeAnnotations: true);
   asyncTest(() => compiler.run(uri).then((_) {
         var typesInferrer = compiler.globalInference.typesInferrerInternal;
+        var closedWorld = typesInferrer.closedWorld;
 
         ClassElement classA = findElement(compiler, "A");
 
@@ -58,18 +59,17 @@
           var element = classA.lookupMember(name);
           var mask = typesInferrer.getReturnTypeOfElement(element);
           Expect.isTrue(type.containsMask(
-              typesInferrer.getReturnTypeOfElement(element),
-              compiler.closedWorld));
+              typesInferrer.getReturnTypeOfElement(element), closedWorld));
         }
 
         checkType(String name, type) {
           var element = classA.lookupMember(name);
           Expect.isTrue(type.containsMask(
-              typesInferrer.getTypeOfElement(element), compiler.closedWorld));
+              typesInferrer.getTypeOfElement(element), closedWorld));
         }
 
-        var intMask = new TypeMask.subtype(
-            compiler.coreClasses.intClass, compiler.closedWorld);
+        var intMask =
+            new TypeMask.subtype(compiler.coreClasses.intClass, closedWorld);
 
         checkReturn('foo', intMask);
         checkReturn('faa', intMask);
diff --git a/tests/compiler/dart2js/type_combination_test.dart b/tests/compiler/dart2js/type_combination_test.dart
index fc68975..479e717 100644
--- a/tests/compiler/dart2js/type_combination_test.dart
+++ b/tests/compiler/dart2js/type_combination_test.dart
@@ -102,8 +102,9 @@
 }
 
 void testUnion(MockCompiler compiler) {
-  RuleSet ruleSet = new RuleSet('union',
-      (t1, t2) => simplify(t1.union(t2, compiler.closedWorld), compiler));
+  ClosedWorld closedWorld = compiler.resolverWorld.closedWorldForTesting;
+  RuleSet ruleSet = new RuleSet(
+      'union', (t1, t2) => simplify(t1.union(t2, closedWorld), closedWorld));
   rule(type1, type2, result) => ruleSet.rule(type1, type2, result);
   check(type1, type2, predicate) => ruleSet.check(type1, type2, predicate);
 
@@ -415,8 +416,9 @@
 void testIntersection(MockCompiler compiler) {
   JavaScriptBackend backend = compiler.backend;
   BackendHelpers helpers = backend.helpers;
-  RuleSet ruleSet = new RuleSet(
-      'intersection', (t1, t2) => t1.intersection(t2, compiler.closedWorld));
+  ClosedWorld closedWorld = compiler.resolverWorld.closedWorldForTesting;
+  RuleSet ruleSet =
+      new RuleSet('intersection', (t1, t2) => t1.intersection(t2, closedWorld));
   rule(type1, type2, result) => ruleSet.rule(type1, type2, result);
 
   rule(emptyType, emptyType, emptyType);
@@ -557,9 +559,9 @@
   rule(jsIndexable, nonPrimitive1, emptyType);
   rule(jsIndexable, nonPrimitive2, emptyType);
   rule(jsIndexable, potentialArray,
-      new TypeMask.nonNullSubtype(helpers.jsArrayClass, compiler.closedWorld));
+      new TypeMask.nonNullSubtype(helpers.jsArrayClass, closedWorld));
   rule(jsIndexable, potentialString,
-      new TypeMask.nonNullSubtype(helpers.jsStringClass, compiler.closedWorld));
+      new TypeMask.nonNullSubtype(helpers.jsStringClass, closedWorld));
   rule(jsIndexable, jsBooleanOrNull, emptyType);
   rule(jsIndexable, jsNumberOrNull, emptyType);
   rule(jsIndexable, jsIntegerOrNull, emptyType);
@@ -724,10 +726,11 @@
 }
 
 void testRegressions(MockCompiler compiler) {
+  ClosedWorld closedWorld = compiler.resolverWorld.closedWorldForTesting;
   TypeMask nonNullPotentialString =
-      new TypeMask.nonNullSubtype(patternClass, compiler.closedWorld);
+      new TypeMask.nonNullSubtype(patternClass, closedWorld);
   Expect.equals(potentialString,
-      jsStringOrNull.union(nonNullPotentialString, compiler.closedWorld));
+      jsStringOrNull.union(nonNullPotentialString, closedWorld));
 }
 
 void main() {
@@ -757,57 +760,62 @@
         .registerTypeUse(new TypeUse.instantiation(patternImplClass.rawType));
     compiler.enqueuer.resolution.applyImpact(impactBuilder);
     compiler.closeResolution();
-    ClosedWorld world = compiler.closedWorld;
+    ClosedWorld closedWorld = compiler.resolverWorld.closedWorldForTesting;
 
     // Grab hold of a supertype for String so we can produce potential
     // string types.
-    patternClass = compiler.commonElements.coreLibrary.find('Pattern');
+    patternClass = closedWorld.commonElements.coreLibrary.find('Pattern');
 
-    nonPrimitive1 =
-        new TypeMask.nonNullSubtype(compiler.coreClasses.mapClass, world);
-    nonPrimitive2 =
-        new TypeMask.nonNullSubtype(compiler.coreClasses.functionClass, world);
+    nonPrimitive1 = new TypeMask.nonNullSubtype(
+        closedWorld.coreClasses.mapClass, closedWorld);
+    nonPrimitive2 = new TypeMask.nonNullSubtype(
+        closedWorld.coreClasses.functionClass, closedWorld);
     potentialArray =
-        new TypeMask.subtype(compiler.coreClasses.listClass, world);
-    potentialString = new TypeMask.subtype(patternClass, world);
+        new TypeMask.subtype(closedWorld.coreClasses.listClass, closedWorld);
+    potentialString = new TypeMask.subtype(patternClass, closedWorld);
     jsInterceptor =
-        new TypeMask.nonNullSubclass(helpers.jsInterceptorClass, world);
-    jsArrayOrNull = new TypeMask.subclass(helpers.jsArrayClass, world);
-    jsReadableArray = new TypeMask.nonNullSubclass(helpers.jsArrayClass, world);
+        new TypeMask.nonNullSubclass(helpers.jsInterceptorClass, closedWorld);
+    jsArrayOrNull = new TypeMask.subclass(helpers.jsArrayClass, closedWorld);
+    jsReadableArray =
+        new TypeMask.nonNullSubclass(helpers.jsArrayClass, closedWorld);
     jsMutableArrayOrNull =
-        new TypeMask.subclass(helpers.jsMutableArrayClass, world);
+        new TypeMask.subclass(helpers.jsMutableArrayClass, closedWorld);
     jsMutableArray =
-        new TypeMask.nonNullSubclass(helpers.jsMutableArrayClass, world);
-    jsFixedArrayOrNull = new TypeMask.exact(helpers.jsFixedArrayClass, world);
-    jsFixedArray = new TypeMask.nonNullExact(helpers.jsFixedArrayClass, world);
+        new TypeMask.nonNullSubclass(helpers.jsMutableArrayClass, closedWorld);
+    jsFixedArrayOrNull =
+        new TypeMask.exact(helpers.jsFixedArrayClass, closedWorld);
+    jsFixedArray =
+        new TypeMask.nonNullExact(helpers.jsFixedArrayClass, closedWorld);
     jsExtendableArrayOrNull =
-        new TypeMask.exact(helpers.jsExtendableArrayClass, world);
+        new TypeMask.exact(helpers.jsExtendableArrayClass, closedWorld);
     jsExtendableArray =
-        new TypeMask.nonNullExact(helpers.jsExtendableArrayClass, world);
+        new TypeMask.nonNullExact(helpers.jsExtendableArrayClass, closedWorld);
     jsUnmodifiableArrayOrNull =
-        new TypeMask.exact(helpers.jsUnmodifiableArrayClass, world);
-    jsUnmodifiableArray =
-        new TypeMask.nonNullExact(helpers.jsUnmodifiableArrayClass, world);
-    jsIndexableOrNull = new TypeMask.subtype(helpers.jsIndexableClass, world);
-    jsIndexable = new TypeMask.nonNullSubtype(helpers.jsIndexableClass, world);
+        new TypeMask.exact(helpers.jsUnmodifiableArrayClass, closedWorld);
+    jsUnmodifiableArray = new TypeMask.nonNullExact(
+        helpers.jsUnmodifiableArrayClass, closedWorld);
+    jsIndexableOrNull =
+        new TypeMask.subtype(helpers.jsIndexableClass, closedWorld);
+    jsIndexable =
+        new TypeMask.nonNullSubtype(helpers.jsIndexableClass, closedWorld);
     jsInterceptorOrNull =
-        new TypeMask.subclass(helpers.jsInterceptorClass, world);
-    jsStringOrNull = new TypeMask.exact(helpers.jsStringClass, world);
-    jsString = new TypeMask.nonNullExact(helpers.jsStringClass, world);
-    jsBoolean = new TypeMask.nonNullExact(helpers.jsBoolClass, world);
-    jsNumber = new TypeMask.nonNullSubclass(helpers.jsNumberClass, world);
-    jsInteger = new TypeMask.nonNullExact(helpers.jsIntClass, world);
-    jsDouble = new TypeMask.nonNullExact(helpers.jsDoubleClass, world);
-    jsBooleanOrNull = new TypeMask.exact(helpers.jsBoolClass, world);
-    jsNumberOrNull = new TypeMask.subclass(helpers.jsNumberClass, world);
-    jsIntegerOrNull = new TypeMask.exact(helpers.jsIntClass, world);
-    jsDoubleOrNull = new TypeMask.exact(helpers.jsDoubleClass, world);
+        new TypeMask.subclass(helpers.jsInterceptorClass, closedWorld);
+    jsStringOrNull = new TypeMask.exact(helpers.jsStringClass, closedWorld);
+    jsString = new TypeMask.nonNullExact(helpers.jsStringClass, closedWorld);
+    jsBoolean = new TypeMask.nonNullExact(helpers.jsBoolClass, closedWorld);
+    jsNumber = new TypeMask.nonNullSubclass(helpers.jsNumberClass, closedWorld);
+    jsInteger = new TypeMask.nonNullExact(helpers.jsIntClass, closedWorld);
+    jsDouble = new TypeMask.nonNullExact(helpers.jsDoubleClass, closedWorld);
+    jsBooleanOrNull = new TypeMask.exact(helpers.jsBoolClass, closedWorld);
+    jsNumberOrNull = new TypeMask.subclass(helpers.jsNumberClass, c