Version 1.12.0-dev.3.0

Merge commit '10b7db100ffec216aa09d1d7816f1c59677eb70b' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 164dd2c..bb3f571 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,8 @@
   * Added two new file modes, `WRITE_ONLY` and `WRITE_ONLY_APPEND` for
     opening a file write only.
     [eaeecf2](https://github.com/dart-lang/sdk/commit/eaeecf2ed13ba6c7fbfd653c3c592974a7120960)
+  * Change stdout/stderr to binary mode on Windows.
+    [4205b29](https://github.com/dart-lang/sdk/commit/4205b2997e01f2cea8e2f44c6f46ed6259ab7277)
 
 ### Tool changes
 
@@ -27,6 +29,15 @@
   * `pub run` starts up faster for executables that don't import transformed
     code.
 
+  * An issue where HTTP requests were sometimes made even though `--offline` was
+    passed to `pub get` or `pub upgrade` has been fixed.
+
+  * A bug with `--offline` that caused an unhelpful error message has been
+    fixed.
+
+  * A crashing bug involving transformers that only apply to non-public code has
+    been fixed.
+
 [package spec proposal]: https://github.com/lrhn/dep-pkgspec
 
 ## 1.11.1
diff --git a/DEPS b/DEPS
index ef0d4fa..ee3e737 100644
--- a/DEPS
+++ b/DEPS
@@ -38,7 +38,7 @@
 
   # Revisions of /third_party/* dependencies.
   "7zip_rev" : "@19997",
-  "analyzer_cli_rev" : "@8bf3516dd645ca289d7ebc641f7c228d5b3d37c4",
+  "analyzer_cli_rev" : "@5069b75f6ccef59b2ba4e2c382bc000037290125",
   "args_tag": "@0.13.0",
   "async_tag": "@1.2.0",
   "barback_rev" : "@29ee90dbcf77cfd64632fa2797a4c8a4f29a4b51",
@@ -49,7 +49,7 @@
   "collection_rev": "@1da9a07f32efa2ba0c391b289e2037391e31da0e",
   "crypto_rev" : "@2df57a1e26dd88e8d0614207d4b062c73209917d",
   "csslib_tag" : "@0.12.0",
-  "dartdoc_rev" : "@9f677ec40f9beeb8933374885ef3af4c63d35d25",
+  "dartdoc_tag" : "@v0.0.3",
   "dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
   "dart_style_tag": "@0.1.8+1",
   "dev_compiler_rev": "@0.1.1",
@@ -79,12 +79,12 @@
   "observe_rev": "@eee2b8ec34236fa46982575fbccff84f61202ac6",
   "observatory_pub_packages_rev": "@45565",
   "package_config_tag": "@0.1.1",
-  "path_rev": "@93b3e2aa1db0ac0c8bab9d341588d77acda60320",
+  "path_tag": "@1.3.6",
   "petitparser_rev" : "@37878",
   "ply_rev": "@604b32590ffad5cbb82e4afef1d305512d06ae93",
   "plugin_tag": "@0.1.0",
   "pool_rev": "@e454b4b54d2987e8d2f0fbd3ac519641ada9bd0f",
-  "pub_rev": "@e05cfca67574acfdbce55a8422c6bc458be93d10",
+  "pub_rev": "@072c5d85f4741bd4eede3eb8d309669b887e3c54",
   "pub_cache_tag": "@v0.0.1+2",
   "pub_semver_tag": "@1.2.1",
   "quiver_tag": "@0.21.4",
@@ -199,7 +199,7 @@
   Var("dart_root") + "/third_party/pkg_tested/dart_style":
       (Var("github_mirror") % "dart_style") + Var("dart_style_tag"),
   Var("dart_root") + "/third_party/pkg/dartdoc":  
-      "https://github.com/dart-lang/dartdoc.git" + Var("dartdoc_rev"),
+      "https://github.com/dart-lang/dartdoc.git" + Var("dartdoc_tag"),
   Var("dart_root") + "/third_party/pkg/dev_compiler":
       "https://github.com/dart-lang/dev_compiler.git" + Var("dev_compiler_rev"),
   Var("dart_root") + "/third_party/pkg/glob":
@@ -245,7 +245,7 @@
       (Var("github_mirror") % "package_config") +
       Var("package_config_tag"),
   Var("dart_root") + "/third_party/pkg/path":
-      (Var("github_mirror") % "path") + Var("path_rev"),
+      (Var("github_mirror") % "path") + Var("path_tag"),
   Var("dart_root") + "/third_party/pkg/plugin":
       (Var("github_mirror") % "plugin") + Var("plugin_tag"),
   Var("dart_root") + "/third_party/pkg/pool":
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 4353e57..38a28ab 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -555,6 +555,13 @@
           always choosing a region that starts at the beginning of a line and
           ends at the end of a (possibly different) line in the file.
         </p>
+        <p>
+          If a request is made for a file which does not exist, or
+          which is not currently subject to analysis (e.g. because it
+          is not associated with any analysis root specified to
+          analysis.setAnalysisRoots), an error of type
+          <tt>GET_NAVIGATION_INVALID_FILE</tt> will be generated.
+        </p>
         
         
       <h4>Parameters</h4><dl><dt class="field"><b><i>file ( <a href="#type_FilePath">FilePath</a> )</i></b></dt><dd>
@@ -3161,6 +3168,13 @@
               which does not match a file currently subject to
               analysis.
             </p>
+          </dd><dt class="value">GET_NAVIGATION_INVALID_FILE</dt><dd>
+            
+            <p>
+              An "analysis.getErrors" request specified a FilePath
+              which does not match a file currently subject to
+              analysis.
+            </p>
           </dd><dt class="value">INVALID_ANALYSIS_ROOT</dt><dd>
             
             <p>
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 6d8be8a..7f135d2 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -25,6 +25,8 @@
 import 'package:analysis_server/uri/resolver_provider.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
+import 'package:analyzer/source/package_map_resolver.dart';
+import 'package:analyzer/source/sdk_ext.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/element.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -1429,9 +1431,17 @@
   SourceFactory _createSourceFactory(UriResolver packageUriResolver) {
     UriResolver dartResolver = new DartUriResolver(analysisServer.defaultSdk);
     UriResolver resourceResolver = new ResourceUriResolver(resourceProvider);
-    List<UriResolver> resolvers = packageUriResolver != null
-        ? <UriResolver>[dartResolver, packageUriResolver, resourceResolver]
-        : <UriResolver>[dartResolver, resourceResolver];
+    List<UriResolver> resolvers = [];
+    resolvers.add(dartResolver);
+    if (packageUriResolver is PackageMapUriResolver) {
+      UriResolver sdkExtResolver =
+          new SdkExtUriResolver(packageUriResolver.packageMap);
+      resolvers.add(sdkExtResolver);
+    }
+    if (packageUriResolver != null) {
+      resolvers.add(packageUriResolver);
+    }
+    resolvers.add(resourceResolver);
     return new SourceFactory(resolvers);
   }
 }
diff --git a/pkg/analysis_server/lib/src/computer/computer_navigation.dart b/pkg/analysis_server/lib/src/computer/computer_navigation.dart
index 14a47ec..1297379 100644
--- a/pkg/analysis_server/lib/src/computer/computer_navigation.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_navigation.dart
@@ -16,21 +16,17 @@
  * A computer for navigation regions in a Dart [CompilationUnit].
  */
 class DartUnitNavigationComputer {
-  final CompilationUnit _unit;
-
   final List<String> files = <String>[];
   final Map<String, int> fileMap = new HashMap<String, int>();
   final List<protocol.NavigationTarget> targets = <protocol.NavigationTarget>[];
   final Map<Element, int> targetMap = new HashMap<Element, int>();
   final List<protocol.NavigationRegion> regions = <protocol.NavigationRegion>[];
 
-  DartUnitNavigationComputer(this._unit);
-
   /**
    * Computes [regions], [targets] and [files].
    */
-  void compute() {
-    _unit.accept(new _DartUnitNavigationComputerVisitor(this));
+  void compute(AstNode node) {
+    node.accept(new _DartUnitNavigationComputerVisitor(this));
   }
 
   int _addFile(String file) {
diff --git a/pkg/analysis_server/lib/src/constants.dart b/pkg/analysis_server/lib/src/constants.dart
index 4f5e232..63dc297 100644
--- a/pkg/analysis_server/lib/src/constants.dart
+++ b/pkg/analysis_server/lib/src/constants.dart
@@ -25,6 +25,7 @@
 const String ANALYSIS_GET_HOVER = 'analysis.getHover';
 const String ANALYSIS_GET_LIBRARY_DEPENDENCIES =
     'analysis.getLibraryDependencies';
+const String ANALYSIS_GET_NAVIGATION = 'analysis.getNavigation';
 const String ANALYSIS_REANALYZE = 'analysis.reanalyze';
 const String ANALYSIS_SET_ANALYSIS_ROOTS = 'analysis.setAnalysisRoots';
 const String ANALYSIS_SET_PRIORITY_FILES = 'analysis.setPriorityFiles';
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index fd32646..c09c511 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -9,6 +9,7 @@
 
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/computer/computer_hover.dart';
+import 'package:analysis_server/src/computer/computer_navigation.dart';
 import 'package:analysis_server/src/constants.dart';
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/services/dependencies/library_dependencies.dart';
@@ -105,6 +106,52 @@
     return Response.DELAYED_RESPONSE;
   }
 
+  /**
+   * Implement the `analysis.getNavigation` request.
+   */
+  Response getNavigation(Request request) {
+    var params = new AnalysisGetNavigationParams.fromRequest(request);
+    String file = params.file;
+    int offset = params.offset;
+    Future<AnalysisDoneReason> completionFuture =
+        server.onFileAnalysisComplete(file);
+    if (completionFuture == null) {
+      return new Response.getNavigationInvalidFile(request);
+    }
+    completionFuture.then((AnalysisDoneReason reason) {
+      switch (reason) {
+        case AnalysisDoneReason.COMPLETE:
+          List<CompilationUnit> units =
+              server.getResolvedCompilationUnits(file);
+          if (units.isEmpty) {
+            server.sendResponse(new Response.getNavigationInvalidFile(request));
+          } else {
+            DartUnitNavigationComputer computer =
+                new DartUnitNavigationComputer();
+            for (CompilationUnit unit in units) {
+              AstNode node = new NodeLocator(offset).searchWithin(unit);
+              if (node != null) {
+                computer.compute(node);
+              }
+            }
+            server.sendResponse(new AnalysisGetNavigationResult(
+                    computer.files, computer.targets, computer.regions)
+                .toResponse(request.id));
+          }
+          break;
+        case AnalysisDoneReason.CONTEXT_REMOVED:
+          // The active contexts have changed, so try again.
+          Response response = getNavigation(request);
+          if (response != Response.DELAYED_RESPONSE) {
+            server.sendResponse(response);
+          }
+          break;
+      }
+    });
+    // delay response
+    return Response.DELAYED_RESPONSE;
+  }
+
   @override
   Response handleRequest(Request request) {
     try {
@@ -115,6 +162,8 @@
         return getHover(request);
       } else if (requestName == ANALYSIS_GET_LIBRARY_DEPENDENCIES) {
         return getLibraryDependencies(request);
+      } else if (requestName == ANALYSIS_GET_NAVIGATION) {
+        return getNavigation(request);
       } else if (requestName == ANALYSIS_REANALYZE) {
         return reanalyze(request);
       } else if (requestName == ANALYSIS_SET_ANALYSIS_ROOTS) {
diff --git a/pkg/analysis_server/lib/src/generated_protocol.dart b/pkg/analysis_server/lib/src/generated_protocol.dart
index 9a7d1f2..66e92ba 100644
--- a/pkg/analysis_server/lib/src/generated_protocol.dart
+++ b/pkg/analysis_server/lib/src/generated_protocol.dart
@@ -12121,6 +12121,7 @@
  *   FORMAT_INVALID_FILE
  *   FORMAT_WITH_ERRORS
  *   GET_ERRORS_INVALID_FILE
+ *   GET_NAVIGATION_INVALID_FILE
  *   INVALID_ANALYSIS_ROOT
  *   INVALID_EXECUTION_CONTEXT
  *   INVALID_OVERLAY_CHANGE
@@ -12164,6 +12165,12 @@
   static const GET_ERRORS_INVALID_FILE = const RequestErrorCode._("GET_ERRORS_INVALID_FILE");
 
   /**
+   * An "analysis.getErrors" request specified a FilePath which does not match
+   * a file currently subject to analysis.
+   */
+  static const GET_NAVIGATION_INVALID_FILE = const RequestErrorCode._("GET_NAVIGATION_INVALID_FILE");
+
+  /**
    * A path passed as an argument to a request (such as analysis.reanalyze) is
    * required to be an analysis root, but isn't.
    */
@@ -12263,7 +12270,7 @@
   /**
    * A list containing all of the enum values that are defined.
    */
-  static const List<RequestErrorCode> VALUES = const <RequestErrorCode>[CONTENT_MODIFIED, FORMAT_INVALID_FILE, FORMAT_WITH_ERRORS, GET_ERRORS_INVALID_FILE, INVALID_ANALYSIS_ROOT, INVALID_EXECUTION_CONTEXT, INVALID_OVERLAY_CHANGE, INVALID_PARAMETER, INVALID_REQUEST, NO_INDEX_GENERATED, REFACTORING_REQUEST_CANCELLED, SERVER_ALREADY_STARTED, SERVER_ERROR, SORT_MEMBERS_INVALID_FILE, SORT_MEMBERS_PARSE_ERRORS, UNANALYZED_PRIORITY_FILES, UNKNOWN_REQUEST, UNKNOWN_SOURCE, UNSUPPORTED_FEATURE];
+  static const List<RequestErrorCode> VALUES = const <RequestErrorCode>[CONTENT_MODIFIED, FORMAT_INVALID_FILE, FORMAT_WITH_ERRORS, GET_ERRORS_INVALID_FILE, GET_NAVIGATION_INVALID_FILE, INVALID_ANALYSIS_ROOT, INVALID_EXECUTION_CONTEXT, INVALID_OVERLAY_CHANGE, INVALID_PARAMETER, INVALID_REQUEST, NO_INDEX_GENERATED, REFACTORING_REQUEST_CANCELLED, SERVER_ALREADY_STARTED, SERVER_ERROR, SORT_MEMBERS_INVALID_FILE, SORT_MEMBERS_PARSE_ERRORS, UNANALYZED_PRIORITY_FILES, UNKNOWN_REQUEST, UNKNOWN_SOURCE, UNSUPPORTED_FEATURE];
 
   final String name;
 
@@ -12279,6 +12286,8 @@
         return FORMAT_WITH_ERRORS;
       case "GET_ERRORS_INVALID_FILE":
         return GET_ERRORS_INVALID_FILE;
+      case "GET_NAVIGATION_INVALID_FILE":
+        return GET_NAVIGATION_INVALID_FILE;
       case "INVALID_ANALYSIS_ROOT":
         return INVALID_ANALYSIS_ROOT;
       case "INVALID_EXECUTION_CONTEXT":
diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
index 1e71683..ebe71e7 100644
--- a/pkg/analysis_server/lib/src/operation/operation_analysis.dart
+++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
@@ -133,8 +133,8 @@
 void sendAnalysisNotificationNavigation(
     AnalysisServer server, String file, CompilationUnit dartUnit) {
   _sendNotification(server, () {
-    var computer = new DartUnitNavigationComputer(dartUnit);
-    computer.compute();
+    var computer = new DartUnitNavigationComputer();
+    computer.compute(dartUnit);
     var params = new protocol.AnalysisNavigationParams(
         file, computer.regions, computer.targets, computer.files);
     server.sendNotification(params.toNotification());
diff --git a/pkg/analysis_server/lib/src/protocol.dart b/pkg/analysis_server/lib/src/protocol.dart
index 8a15ebe..f633eb8 100644
--- a/pkg/analysis_server/lib/src/protocol.dart
+++ b/pkg/analysis_server/lib/src/protocol.dart
@@ -513,37 +513,6 @@
       : _params = params != null ? params : new HashMap<String, Object>();
 
   /**
-   * Return a request parsed from the given [data], or `null` if the [data] is
-   * not a valid json representation of a request. The [data] is expected to
-   * have the following format:
-   *
-   *   {
-   *     'clientRequestTime': millisecondsSinceEpoch
-   *     'id': String,
-   *     'method': methodName,
-   *     'params': {
-   *       paramter_name: value
-   *     }
-   *   }
-   *
-   * where both the parameters and clientRequestTime are optional.
-   * The parameters can contain any number of name/value pairs.
-   * The clientRequestTime must be an int representing the time at which
-   * the client issued the request (milliseconds since epoch).
-   */
-  factory Request.fromString(String data) {
-    try {
-      var result = JSON.decode(data);
-      if (result is Map) {
-        return new Request.fromJson(result);
-      }
-      return null;
-    } catch (exception) {
-      return null;
-    }
-  }
-
-  /**
    * Return a request parsed from the given json, or `null` if the [data] is
    * not a valid json representation of a request. The [data] is expected to
    * have the following format:
@@ -581,6 +550,37 @@
   }
 
   /**
+   * Return a request parsed from the given [data], or `null` if the [data] is
+   * not a valid json representation of a request. The [data] is expected to
+   * have the following format:
+   *
+   *   {
+   *     'clientRequestTime': millisecondsSinceEpoch
+   *     'id': String,
+   *     'method': methodName,
+   *     'params': {
+   *       paramter_name: value
+   *     }
+   *   }
+   *
+   * where both the parameters and clientRequestTime are optional.
+   * The parameters can contain any number of name/value pairs.
+   * The clientRequestTime must be an int representing the time at which
+   * the client issued the request (milliseconds since epoch).
+   */
+  factory Request.fromString(String data) {
+    try {
+      var result = JSON.decode(data);
+      if (result is Map) {
+        return new Request.fromJson(result);
+      }
+      return null;
+    } catch (exception) {
+      return null;
+    }
+  }
+
+  /**
    * Return a table representing the structure of the Json object that will be
    * sent to the client to represent this response.
    */
@@ -763,6 +763,14 @@
               'Error during `analysis.getErrors`: invalid file.'));
 
   /**
+   * Initialize a newly created instance to represent the
+   * GET_NAVIGATION_INVALID_FILE error condition.
+   */
+  Response.getNavigationInvalidFile(Request request) : this(request.id,
+          error: new RequestError(RequestErrorCode.GET_NAVIGATION_INVALID_FILE,
+              'Error during `analysis.getNavigation`: invalid file.'));
+
+  /**
    * Initialize a newly created instance to represent an error condition caused
    * by an analysis.reanalyze [request] that specifies an analysis root that is
    * not in the current list of analysis roots.
diff --git a/pkg/analysis_server/test/analysis/get_navigation_test.dart b/pkg/analysis_server/test/analysis/get_navigation_test.dart
new file mode 100644
index 0000000..b5c224e
--- /dev/null
+++ b/pkg/analysis_server/test/analysis/get_navigation_test.dart
@@ -0,0 +1,114 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test.analysis.get_navigation;
+
+import 'package:analysis_server/src/domain_analysis.dart';
+import 'package:analysis_server/src/protocol.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'package:unittest/unittest.dart';
+
+import 'notification_navigation_test.dart';
+
+main() {
+  groupSep = ' | ';
+  defineReflectiveTests(GetNavigationTest);
+}
+
+@reflectiveTest
+class GetNavigationTest extends AbstractNavigationTest {
+  static const String requestId = 'test-getNavigtion';
+
+  @override
+  void setUp() {
+    super.setUp();
+    server.handlers = [new AnalysisDomainHandler(server),];
+    createProject();
+  }
+
+  test_afterAnalysisComplete() async {
+    addTestFile('''
+main() {
+  var test = 0;
+  print(test);
+}
+''');
+    await waitForTasksFinished();
+    await _getNavigation(testFile, testCode.indexOf('test);'), 0);
+    assertHasRegion('test);');
+    assertHasTarget('test = 0');
+  }
+
+  test_beforeAnalysisComplete() async {
+    addTestFile('''
+main() {
+  var test = 0;
+  print(test);
+}
+''');
+    await _getNavigation(testFile, testCode.indexOf('test);'), 0);
+    assertHasRegion('test);');
+    assertHasTarget('test = 0');
+  }
+
+  test_fileDoesNotExist() {
+    String file = '$projectPath/doesNotExist.dart';
+    return _checkInvalid(file, -1, -1);
+  }
+
+  test_fileWithoutContext() {
+    String file = '/outside.dart';
+    addFile(file, '''
+main() {
+  print(42);
+}
+''');
+    return _checkInvalid(file, -1, -1);
+  }
+
+  test_removeContextAfterRequest() async {
+    addTestFile('''
+main() {
+  var test = 0;
+  print(test);
+}
+''');
+    // handle the request synchronously
+    Request request =
+        _createGetNavigationRequest(testFile, testCode.indexOf('test);'), 0);
+    server.handleRequest(request);
+    // remove context, causes sending an "invalid file" error
+    {
+      Folder projectFolder = resourceProvider.getResource(projectPath);
+      server.contextDirectoryManager.removeContext(projectFolder);
+    }
+    // wait for an error response
+    Response response = await serverChannel.waitForResponse(request);
+    expect(response.error, isNotNull);
+    expect(response.error.code, RequestErrorCode.GET_NAVIGATION_INVALID_FILE);
+  }
+
+  _checkInvalid(String file, int offset, int length) async {
+    Request request = _createGetNavigationRequest(file, offset, length);
+    Response response = await serverChannel.sendRequest(request);
+    expect(response.error, isNotNull);
+    expect(response.error.code, RequestErrorCode.GET_NAVIGATION_INVALID_FILE);
+  }
+
+  Request _createGetNavigationRequest(String file, int offset, int length) {
+    return new AnalysisGetNavigationParams(file, offset, length)
+        .toRequest(requestId);
+  }
+
+  _getNavigation(String file, int offset, int length) async {
+    Request request = _createGetNavigationRequest(file, offset, length);
+    Response response = await serverChannel.sendRequest(request);
+    AnalysisGetNavigationResult result =
+        new AnalysisGetNavigationResult.fromResponse(response);
+    targetFiles = result.files;
+    targets = result.targets;
+    regions = result.regions;
+  }
+}
diff --git a/pkg/analysis_server/test/analysis/notification_navigation_test.dart b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
index 16d1bcd..13d54cd 100644
--- a/pkg/analysis_server/test/analysis/notification_navigation_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
@@ -19,154 +19,7 @@
 }
 
 @reflectiveTest
-class AnalysisNotificationNavigationTest extends AbstractAnalysisTest {
-  List<NavigationRegion> regions;
-  List<NavigationTarget> targets;
-  List<String> targetFiles;
-
-  NavigationRegion testRegion;
-  List<int> testTargetIndexes;
-  NavigationTarget testTarget;
-
-  /**
-   * Validates that there is a target in [testTargetIndexes] with [file],
-   * at [offset] and with the given [length].
-   */
-  void assertHasFileTarget(String file, int offset, int length) {
-    List<NavigationTarget> testTargets =
-        testTargetIndexes.map((int index) => targets[index]).toList();
-    for (NavigationTarget target in testTargets) {
-      if (targetFiles[target.fileIndex] == file &&
-          target.offset == offset &&
-          target.length == length) {
-        testTarget = target;
-        return;
-      }
-    }
-    fail(
-        'Expected to find target (file=$file; offset=$offset; length=$length) in\n'
-        '${testRegion} in\n' '${testTargets.join('\n')}');
-  }
-
-  void assertHasOperatorRegion(String regionSearch, int regionLength,
-      String targetSearch, int targetLength) {
-    assertHasRegion(regionSearch, regionLength);
-    assertHasTarget(targetSearch, targetLength);
-  }
-
-  /**
-   * Validates that there is a region at the offset of [search] in [testFile].
-   * If [length] is not specified explicitly, then length of an identifier
-   * from [search] is used.
-   */
-  void assertHasRegion(String search, [int length = -1]) {
-    int offset = findOffset(search);
-    if (length == -1) {
-      length = findIdentifierLength(search);
-    }
-    findRegion(offset, length, true);
-  }
-
-  /**
-   * Validates that there is a region at the offset of [search] in [testFile]
-   * with the given [length] or the length of [search].
-   */
-  void assertHasRegionString(String search, [int length = -1]) {
-    int offset = findOffset(search);
-    if (length == -1) {
-      length = search.length;
-    }
-    findRegion(offset, length, true);
-  }
-
-  /**
-   * Validates that there is an identifier region at [regionSearch] with target
-   * at [targetSearch].
-   */
-  void assertHasRegionTarget(String regionSearch, String targetSearch) {
-    assertHasRegion(regionSearch);
-    assertHasTarget(targetSearch);
-  }
-
-  /**
-   * Validates that there is a target in [testTargets]  with [testFile], at the
-   * offset of [search] in [testFile], and with the given [length] or the length
-   * of an leading identifier in [search].
-   */
-  void assertHasTarget(String search, [int length = -1]) {
-    int offset = findOffset(search);
-    if (length == -1) {
-      length = findIdentifierLength(search);
-    }
-    assertHasFileTarget(testFile, offset, length);
-  }
-
-  /**
-   * Validates that there is no a region at [search] and with the given
-   * [length].
-   */
-  void assertNoRegion(String search, int length) {
-    int offset = findOffset(search);
-    findRegion(offset, length, false);
-  }
-
-  /**
-   * Validates that there is no a region at [search] with any length.
-   */
-  void assertNoRegionAt(String search) {
-    int offset = findOffset(search);
-    findRegion(offset, -1, false);
-  }
-
-  /**
-   * Validates that there is no a region for [search] string.
-   */
-  void assertNoRegionString(String search) {
-    int offset = findOffset(search);
-    int length = search.length;
-    findRegion(offset, length, false);
-  }
-
-  void assertRegionsSorted() {
-    int lastEnd = -1;
-    for (NavigationRegion region in regions) {
-      int offset = region.offset;
-      if (offset < lastEnd) {
-        fail('$lastEnd was expected to be > $offset in\n' + regions.join('\n'));
-      }
-      lastEnd = offset + region.length;
-    }
-  }
-
-  /**
-   * Finds the navigation region with the given [offset] and [length].
-   * If [length] is `-1`, then it is ignored.
-   *
-   * If [exists] is `true`, then fails if such region does not exist.
-   * Otherwise remembers this it into [testRegion].
-   * Also fills [testTargets] with its targets.
-   *
-   * If [exists] is `false`, then fails if such region exists.
-   */
-  void findRegion(int offset, int length, bool exists) {
-    for (NavigationRegion region in regions) {
-      if (region.offset == offset &&
-          (length == -1 || region.length == length)) {
-        if (exists == false) {
-          fail('Not expected to find (offset=$offset; length=$length) in\n'
-              '${regions.join('\n')}');
-        }
-        testRegion = region;
-        testTargetIndexes = region.targets;
-        return;
-      }
-    }
-    if (exists == true) {
-      fail('Expected to find (offset=$offset; length=$length) in\n'
-          '${regions.join('\n')}');
-    }
-  }
-
+class AnalysisNotificationNavigationTest extends AbstractNavigationTest {
   Future prepareNavigation() {
     addAnalysisSubscription(AnalysisService.NAVIGATION, testFile);
     return waitForTasksFinished().then((_) {
@@ -785,3 +638,152 @@
     });
   }
 }
+
+class AbstractNavigationTest extends AbstractAnalysisTest {
+  List<NavigationRegion> regions;
+  List<NavigationTarget> targets;
+  List<String> targetFiles;
+
+  NavigationRegion testRegion;
+  List<int> testTargetIndexes;
+  NavigationTarget testTarget;
+
+  /**
+   * Validates that there is a target in [testTargetIndexes] with [file],
+   * at [offset] and with the given [length].
+   */
+  void assertHasFileTarget(String file, int offset, int length) {
+    List<NavigationTarget> testTargets =
+        testTargetIndexes.map((int index) => targets[index]).toList();
+    for (NavigationTarget target in testTargets) {
+      if (targetFiles[target.fileIndex] == file &&
+          target.offset == offset &&
+          target.length == length) {
+        testTarget = target;
+        return;
+      }
+    }
+    fail(
+        'Expected to find target (file=$file; offset=$offset; length=$length) in\n'
+        '${testRegion} in\n' '${testTargets.join('\n')}');
+  }
+
+  void assertHasOperatorRegion(String regionSearch, int regionLength,
+      String targetSearch, int targetLength) {
+    assertHasRegion(regionSearch, regionLength);
+    assertHasTarget(targetSearch, targetLength);
+  }
+
+  /**
+   * Validates that there is a region at the offset of [search] in [testFile].
+   * If [length] is not specified explicitly, then length of an identifier
+   * from [search] is used.
+   */
+  void assertHasRegion(String search, [int length = -1]) {
+    int offset = findOffset(search);
+    if (length == -1) {
+      length = findIdentifierLength(search);
+    }
+    findRegion(offset, length, true);
+  }
+
+  /**
+   * Validates that there is a region at the offset of [search] in [testFile]
+   * with the given [length] or the length of [search].
+   */
+  void assertHasRegionString(String search, [int length = -1]) {
+    int offset = findOffset(search);
+    if (length == -1) {
+      length = search.length;
+    }
+    findRegion(offset, length, true);
+  }
+
+  /**
+   * Validates that there is an identifier region at [regionSearch] with target
+   * at [targetSearch].
+   */
+  void assertHasRegionTarget(String regionSearch, String targetSearch) {
+    assertHasRegion(regionSearch);
+    assertHasTarget(targetSearch);
+  }
+
+  /**
+   * Validates that there is a target in [testTargets]  with [testFile], at the
+   * offset of [search] in [testFile], and with the given [length] or the length
+   * of an leading identifier in [search].
+   */
+  void assertHasTarget(String search, [int length = -1]) {
+    int offset = findOffset(search);
+    if (length == -1) {
+      length = findIdentifierLength(search);
+    }
+    assertHasFileTarget(testFile, offset, length);
+  }
+
+  /**
+   * Validates that there is no a region at [search] and with the given
+   * [length].
+   */
+  void assertNoRegion(String search, int length) {
+    int offset = findOffset(search);
+    findRegion(offset, length, false);
+  }
+
+  /**
+   * Validates that there is no a region at [search] with any length.
+   */
+  void assertNoRegionAt(String search) {
+    int offset = findOffset(search);
+    findRegion(offset, -1, false);
+  }
+
+  /**
+   * Validates that there is no a region for [search] string.
+   */
+  void assertNoRegionString(String search) {
+    int offset = findOffset(search);
+    int length = search.length;
+    findRegion(offset, length, false);
+  }
+
+  void assertRegionsSorted() {
+    int lastEnd = -1;
+    for (NavigationRegion region in regions) {
+      int offset = region.offset;
+      if (offset < lastEnd) {
+        fail('$lastEnd was expected to be > $offset in\n' + regions.join('\n'));
+      }
+      lastEnd = offset + region.length;
+    }
+  }
+
+  /**
+   * Finds the navigation region with the given [offset] and [length].
+   * If [length] is `-1`, then it is ignored.
+   *
+   * If [exists] is `true`, then fails if such region does not exist.
+   * Otherwise remembers this it into [testRegion].
+   * Also fills [testTargets] with its targets.
+   *
+   * If [exists] is `false`, then fails if such region exists.
+   */
+  void findRegion(int offset, int length, bool exists) {
+    for (NavigationRegion region in regions) {
+      if (region.offset == offset &&
+          (length == -1 || region.length == length)) {
+        if (exists == false) {
+          fail('Not expected to find (offset=$offset; length=$length) in\n'
+              '${regions.join('\n')}');
+        }
+        testRegion = region;
+        testTargetIndexes = region.targets;
+        return;
+      }
+    }
+    if (exists == true) {
+      fail('Expected to find (offset=$offset; length=$length) in\n'
+          '${regions.join('\n')}');
+    }
+  }
+}
diff --git a/pkg/analysis_server/test/analysis/test_all.dart b/pkg/analysis_server/test/analysis/test_all.dart
index e9867c2..b28a687 100644
--- a/pkg/analysis_server/test/analysis/test_all.dart
+++ b/pkg/analysis_server/test/analysis/test_all.dart
@@ -7,6 +7,7 @@
 
 import 'get_errors_test.dart' as get_errors_test;
 import 'get_hover_test.dart' as get_hover_test;
+import 'get_navigation_test.dart' as get_navigation_test;
 import 'notification_errors_test.dart' as notification_errors_test;
 import 'notification_highlights_test.dart' as notification_highlights_test;
 import 'notification_navigation_test.dart' as notification_navigation_test;
@@ -23,6 +24,7 @@
   group('search', () {
     get_errors_test.main();
     get_hover_test.main();
+    get_navigation_test.main();
     notification_errors_test.main();
     notification_highlights_test.main();
     notification_navigation_test.main();
diff --git a/pkg/analysis_server/test/integration/integration_test_methods.dart b/pkg/analysis_server/test/integration/integration_test_methods.dart
index 3b609f2..5794acb 100644
--- a/pkg/analysis_server/test/integration/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/integration_test_methods.dart
@@ -277,6 +277,11 @@
    * region that starts at the beginning of a line and ends at the end of a
    * (possibly different) line in the file.
    *
+   * If a request is made for a file which does not exist, or which is not
+   * currently subject to analysis (e.g. because it is not associated with any
+   * analysis root specified to analysis.setAnalysisRoots), an error of type
+   * GET_NAVIGATION_INVALID_FILE will be generated.
+   *
    * Parameters
    *
    * file ( FilePath )
diff --git a/pkg/analysis_server/test/integration/protocol_matchers.dart b/pkg/analysis_server/test/integration/protocol_matchers.dart
index 60515ea..fbb40a8 100644
--- a/pkg/analysis_server/test/integration/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/protocol_matchers.dart
@@ -1829,6 +1829,7 @@
  *   FORMAT_INVALID_FILE
  *   FORMAT_WITH_ERRORS
  *   GET_ERRORS_INVALID_FILE
+ *   GET_NAVIGATION_INVALID_FILE
  *   INVALID_ANALYSIS_ROOT
  *   INVALID_EXECUTION_CONTEXT
  *   INVALID_OVERLAY_CHANGE
@@ -1851,6 +1852,7 @@
   "FORMAT_INVALID_FILE",
   "FORMAT_WITH_ERRORS",
   "GET_ERRORS_INVALID_FILE",
+  "GET_NAVIGATION_INVALID_FILE",
   "INVALID_ANALYSIS_ROOT",
   "INVALID_EXECUTION_CONTEXT",
   "INVALID_OVERLAY_CHANGE",
diff --git a/pkg/analysis_server/test/services/refactoring/extract_method_test.dart b/pkg/analysis_server/test/services/refactoring/extract_method_test.dart
index 5e376f3..d33a930 100644
--- a/pkg/analysis_server/test/services/refactoring/extract_method_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/extract_method_test.dart
@@ -1804,7 +1804,7 @@
   var a = res(v1, v2); // marker
 }
 
-num res(int v1, int v2) => v1 + v2 + v1;
+int res(int v1, int v2) => v1 + v2 + v1;
 ''');
   }
 
diff --git a/pkg/analysis_server/tool/spec/api.dart b/pkg/analysis_server/tool/spec/api.dart
index 6f47644..a558f17 100644
--- a/pkg/analysis_server/tool/spec/api.dart
+++ b/pkg/analysis_server/tool/spec/api.dart
@@ -176,7 +176,7 @@
 }
 
 /**
- * Description of a request method.
+ * Description of a notification method.
  */
 class Notification extends ApiNode {
   /**
@@ -429,7 +429,7 @@
   final bool optional;
 
   /**
-   * Value which the field is required to contain, or null if it may vary.
+   * Value that the field is required to contain, or null if it may vary.
    */
   final Object value;
 
diff --git a/pkg/analysis_server/tool/spec/codegen_tools.dart b/pkg/analysis_server/tool/spec/codegen_tools.dart
index 0d7e95f..f388379 100644
--- a/pkg/analysis_server/tool/spec/codegen_tools.dart
+++ b/pkg/analysis_server/tool/spec/codegen_tools.dart
@@ -85,8 +85,8 @@
   /**
    * Generate a doc comment based on the HTML in [docs].
    *
-   * If [javadocStyle] is true, then the output is compatable with Javadoc,
-   * which understands certain HTML constructs.
+   * When generating java code, the output is compatible with Javadoc, which
+   * understands certain HTML constructs.
    */
   void docComment(List<dom.Node> docs) {
     if (containsOnlyWhitespace(docs)) {
@@ -251,7 +251,7 @@
 
 /**
  * Class representing a single output directory (either generated code or
- * generated HTML). No other content should exisit in the directory.
+ * generated HTML). No other content should exist in the directory.
  */
 class GeneratedDirectory extends GeneratedContent {
 
@@ -261,7 +261,7 @@
   final String outputDirPath;
 
   /**
-   * Callback function which computes the directory contents.
+   * Callback function that computes the directory contents.
    */
   final DirectoryContentsComputer directoryContentsComputer;
 
diff --git a/pkg/analysis_server/tool/spec/from_html.dart b/pkg/analysis_server/tool/spec/from_html.dart
index 938aacc..72c1ee2 100644
--- a/pkg/analysis_server/tool/spec/from_html.dart
+++ b/pkg/analysis_server/tool/spec/from_html.dart
@@ -303,7 +303,7 @@
       if (elementProcessors.containsKey(node.localName)) {
         elementProcessors[node.localName](node);
       } else if (specialElements.contains(node.localName)) {
-        throw new Exception('$context: Unexpected use of <${node.localName}');
+        throw new Exception('$context: Unexpected use of <${node.localName}>');
       } else {
         recurse(node, context, elementProcessors);
       }
diff --git a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
index dff7552..c6debb7 100644
--- a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
+++ b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
@@ -105,6 +105,10 @@
    * choosing a region that starts at the beginning of a line and ends at the end of a (possibly
    * different) line in the file.
    *
+   * If a request is made for a file which does not exist, or which is not currently subject to
+   * analysis (e.g. because it is not associated with any analysis root specified to
+   * analysis.setAnalysisRoots), an error of type GET_NAVIGATION_INVALID_FILE will be generated.
+   *
    * @param file The file in which navigation information is being requested.
    * @param offset The offset of the region for which navigation information is being requested.
    * @param length The length of the region for which navigation information is being requested.
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java b/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java
index d86609d..8e39aff 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java
@@ -47,6 +47,12 @@
   public static final String GET_ERRORS_INVALID_FILE = "GET_ERRORS_INVALID_FILE";
 
   /**
+   * An "analysis.getErrors" request specified a FilePath which does not match a file currently
+   * subject to analysis.
+   */
+  public static final String GET_NAVIGATION_INVALID_FILE = "GET_NAVIGATION_INVALID_FILE";
+
+  /**
    * A path passed as an argument to a request (such as analysis.reanalyze) is required to be an
    * analysis root, but isn't.
    */
diff --git a/pkg/analysis_server/tool/spec/html_tools.dart b/pkg/analysis_server/tool/spec/html_tools.dart
index 419fe63..d46419f 100644
--- a/pkg/analysis_server/tool/spec/html_tools.dart
+++ b/pkg/analysis_server/tool/spec/html_tools.dart
@@ -96,8 +96,8 @@
 
   /**
    * Execute [callback], collecting any code that is output using [write],
-   * [writeln], [add], or [addAll], and return the result as a list of HTML
-   * nodes.
+   * [writeln], [add], [addAll] or [element], and return the result as a list
+   * of HTML nodes.
    */
   List<dom.Node> collectHtml(void callback()) {
     List<dom.Node> oldHtml = _html;
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index b2e68fc..b88c8ac 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -441,6 +441,13 @@
           always choosing a region that starts at the beginning of a line and
           ends at the end of a (possibly different) line in the file.
         </p>
+        <p>
+          If a request is made for a file which does not exist, or
+          which is not currently subject to analysis (e.g. because it
+          is not associated with any analysis root specified to
+          analysis.setAnalysisRoots), an error of type
+          <tt>GET_NAVIGATION_INVALID_FILE</tt> will be generated.
+        </p>
         <params>
           <field name="file">
             <ref>FilePath</ref>
@@ -3161,6 +3168,14 @@
             </p>
           </value>
           <value>
+            <code>GET_NAVIGATION_INVALID_FILE</code>
+            <p>
+              An "analysis.getErrors" request specified a FilePath
+              which does not match a file currently subject to
+              analysis.
+            </p>
+          </value>
+          <value>
             <code>INVALID_ANALYSIS_ROOT</code>
             <p>
               A path passed as an argument to a request (such as
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 7cbf18f..6e22891 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,16 @@
+## 0.25.2-alpha.1
+
+* `dart:sdk` extension `.sdkext` changed to `_sdkext` (to play nicer with pub).
+
+## 0.25.2-alpha.0
+
+* Initial support for analyzing `dart:sdk` extensions from `.sdkext`. 
+
+## 0.25.1
+
+* (Internal) code reorganization to address analysis warnings due to SDK reorg.
+* First steps towards `.packages` support.
+
 ## 0.25.0
 
 * Commandline interface moved to dedicated `analyzer_cli` package. Files moved:
diff --git a/pkg/analyzer/lib/source/sdk_ext.dart b/pkg/analyzer/lib/source/sdk_ext.dart
new file mode 100644
index 0000000..696e181
--- /dev/null
+++ b/pkg/analyzer/lib/source/sdk_ext.dart
@@ -0,0 +1,176 @@
+// 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.
+
+library source.sdk_ext;
+
+import 'dart:convert';
+import 'dart:core' hide Resource;
+
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/generated/java_io.dart' show JavaFile;
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/source_io.dart' show FileBasedSource;
+import 'package:path/path.dart' as pathos;
+
+/// Given a packageMap (see [PackageMapProvider]), check in each package's lib
+/// directory for the existence of a `_sdkext` file. This file must contain a
+/// JSON encoded map. Each key in the map is a `dart:` library name. Each value
+/// is a path (relative to the directory containing `_sdkext`) to a dart script
+/// for the given library. For example:
+/// {
+///   "dart:sky": "../sdk_ext/dart_sky.dart"
+/// }
+///
+/// If a key doesn't begin with `dart:` it is ignored.
+class SdkExtUriResolver extends UriResolver {
+  static const String SDK_EXT_NAME = '_sdkext';
+  static const String DART_COLON_PREFIX = 'dart:';
+
+  final Map<String, String> _urlMappings = <String,String>{};
+
+  /// Construct a [SdkExtUriResolver] from a package map
+  /// (see [PackageMapProvider]).
+  SdkExtUriResolver(Map<String, List<Folder>> packageMap) {
+    if (packageMap == null) {
+      return;
+    }
+    packageMap.forEach(_processPackage);
+  }
+
+  /// Number of sdk extensions.
+  int get length => _urlMappings.length;
+
+  /// Return the path mapping for [libName] or null if there is none.
+  String operator[](String libName) => _urlMappings[libName];
+
+  /// Programmatically add a new SDK extension given a JSON description
+  /// ([sdkExtJSON]) and a lib directory ([libDir]).
+  void addSdkExt(String sdkExtJSON, Folder libDir) {
+    _processSdkExt(sdkExtJSON, libDir);
+  }
+
+  @override
+  Source resolveAbsolute(Uri importUri) {
+    String libraryName = _libraryName(importUri);
+    String partPath = _partPath(importUri);
+    // Lookup library name in mappings.
+    String mapping = _urlMappings[libraryName];
+    if (mapping == null) {
+      // Not found.
+      return null;
+    }
+    // This mapping points to the main entry file of the sdk extension.
+    Uri libraryEntry = new Uri.file(mapping);
+    if (!libraryEntry.isAbsolute) {
+      // We expect an absolute path.
+      return null;
+    }
+
+    if (partPath != null) {
+      return _resolvePart(libraryEntry, partPath, importUri);
+    } else {
+      return _resolveEntry(libraryEntry, importUri);
+    }
+  }
+
+  @override
+  Uri restoreAbsolute(Source source) {
+    String libraryName = _libraryName(source.uri);
+    if (_registeredSdkExtension(libraryName)) {
+      return source.uri;
+    }
+    return null;
+  }
+
+  /// Return the library name of [importUri].
+  String _libraryName(Uri importUri) {
+    var uri = importUri.toString();
+    int index = uri.indexOf('/');
+    if (index >= 0) {
+      return uri.substring(0, index);
+    }
+    return uri;
+  }
+
+  /// Return the part path of [importUri].
+  String _partPath(Uri importUri) {
+    var uri = importUri.toString();
+    int index = uri.indexOf('/');
+    if (index >= 0) {
+      return uri.substring(index + 1);
+    }
+    return null;
+  }
+
+  /// Given a package [name] and a list of folders ([libDirs]),
+  /// add any found sdk extensions.
+  void _processPackage(String name, List<Folder> libDirs) {
+    for (var libDir in libDirs) {
+      var sdkExt = _readDotSdkExt(libDir);
+      if (sdkExt != null) {
+        _processSdkExt(sdkExt, libDir);
+      }
+    }
+  }
+
+  /// Given the JSON for an SDK extension ([sdkExtJSON]) and a folder
+  /// ([libDir]), setup the uri mapping.
+  void _processSdkExt(String sdkExtJSON, Folder libDir) {
+    var sdkExt;
+    try {
+      sdkExt = JSON.decode(sdkExtJSON);
+    } catch (e) {
+      return;
+    }
+    if ((sdkExt == null) || (sdkExt is! Map)) {
+      return;
+    }
+    sdkExt.forEach((k, v) => _processSdkExtension(k, v, libDir));
+  }
+
+  /// Install the mapping from [name] to [libDir]/[file].
+  void _processSdkExtension(String name, String file, Folder libDir) {
+    if (!name.startsWith(DART_COLON_PREFIX)) {
+      // SDK extensions must begin with 'dart:'.
+      return;
+    }
+    var key = name;
+    var value = libDir.canonicalizePath(file);
+    _urlMappings[key] = value;
+  }
+
+  /// Read the contents of [libDir]/[SDK_EXT_NAME] as a string.
+  /// Returns null if the file doesn't exist.
+  String _readDotSdkExt(Folder libDir) {
+    var file = libDir.getChild(SDK_EXT_NAME);
+    try {
+      return file.readAsStringSync();
+    } on FileSystemException {
+      // File can't be read.
+      return null;
+    }
+  }
+
+  /// Returns true if [libraryName] is a registered sdk extension.
+  bool _registeredSdkExtension(String libraryName) {
+    return _urlMappings[libraryName] != null;
+  }
+
+  /// Resolve an import of an sdk extension.
+  Source _resolveEntry(Uri libraryEntry, Uri importUri) {
+    // Library entry.
+    JavaFile javaFile = new JavaFile.fromUri(libraryEntry);
+    return new FileBasedSource(javaFile, importUri);
+  }
+
+  /// Resolve a 'part' statement inside an sdk extension.
+  Source _resolvePart(Uri libraryEntry, String partPath, Uri importUri) {
+    // Library part.
+    var directory = pathos.dirname(libraryEntry.path);
+    var partUri = new Uri.file(pathos.join(directory, partPath));
+    assert(partUri.isAbsolute);
+    JavaFile javaFile = new JavaFile.fromUri(partUri);
+    return new FileBasedSource(javaFile, importUri);
+  }
+}
diff --git a/pkg/analyzer/lib/src/generated/element.dart b/pkg/analyzer/lib/src/generated/element.dart
index 24344aa..395dc27 100644
--- a/pkg/analyzer/lib/src/generated/element.dart
+++ b/pkg/analyzer/lib/src/generated/element.dart
@@ -3593,6 +3593,12 @@
    * Return the type of function defined by this executable element.
    */
   FunctionType get type;
+
+  /**
+   * Return a list containing all of the type parameters defined for this
+   * executable element.
+   */
+  List<TypeParameterElement> get typeParameters;
 }
 
 /**
@@ -3630,6 +3636,12 @@
   List<ParameterElement> _parameters = ParameterElement.EMPTY_LIST;
 
   /**
+   * A list containing all of the type parameters defined for this executable
+   * element.
+   */
+  List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST;
+
+  /**
    * The return type defined by this executable element.
    */
   DartType returnType;
@@ -3746,8 +3758,33 @@
   }
 
   @override
+  List<TypeParameterElement> get typeParameters => _typeParameters;
+
+  /**
+   * Set the type parameters defined by this executable element to the given
+   * [typeParameters].
+   */
+  void set typeParameters(List<TypeParameterElement> typeParameters) {
+    for (TypeParameterElement parameter in typeParameters) {
+      (parameter as TypeParameterElementImpl).enclosingElement = this;
+    }
+    this._typeParameters = typeParameters;
+  }
+
+  @override
   void appendTo(StringBuffer buffer) {
     if (this.kind != ElementKind.GETTER) {
+      int typeParameterCount = _typeParameters.length;
+      if (typeParameterCount > 0) {
+        buffer.write('<');
+        for (int i = 0; i < typeParameterCount; i++) {
+          if (i > 0) {
+            buffer.write(", ");
+          }
+          (_typeParameters[i] as TypeParameterElementImpl).appendTo(buffer);
+        }
+        buffer.write('>');
+      }
       buffer.write("(");
       String closing = null;
       ParameterKind kind = ParameterKind.REQUIRED;
@@ -3903,6 +3940,9 @@
   FunctionType get type => substituteFor(baseElement.type);
 
   @override
+  List<TypeParameterElement> get typeParameters => baseElement.typeParameters;
+
+  @override
   void visitChildren(ElementVisitor visitor) {
     // TODO(brianwilkerson) We need to finish implementing the accessors used
     // below so that we can safely invoke them.
@@ -8604,6 +8644,13 @@
    */
   List<ParameterElement> get parameters;
 
+  /**
+   * Return a list containing all of the type parameters defined by this
+   * parameter. A parameter will only define other parameters if it is a
+   * function typed parameter.
+   */
+  List<TypeParameterElement> get typeParameters;
+
   @override
   FormalParameter computeNode();
 }
@@ -8627,6 +8674,13 @@
   List<ParameterElement> _parameters = ParameterElement.EMPTY_LIST;
 
   /**
+   * A list containing all of the type parameters defined for this parameter
+   * element. There will only be parameters if this parameter is a function
+   * typed parameter.
+   */
+  List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST;
+
+  /**
    * The kind of this parameter.
    */
   ParameterKind parameterKind;
@@ -8697,6 +8751,20 @@
   }
 
   @override
+  List<TypeParameterElement> get typeParameters => _typeParameters;
+
+  /**
+   * Set the type parameters defined by this parameter element to the given
+   * [typeParameters].
+   */
+  void set typeParameters(List<TypeParameterElement> typeParameters) {
+    for (TypeParameterElement parameter in typeParameters) {
+      (parameter as TypeParameterElementImpl).enclosingElement = this;
+    }
+    this._typeParameters = typeParameters;
+  }
+
+  @override
   SourceRange get visibleRange {
     if (_visibleRangeLength < 0) {
       return null;
@@ -8852,6 +8920,9 @@
   }
 
   @override
+  List<TypeParameterElement> get typeParameters => baseElement.typeParameters;
+
+  @override
   SourceRange get visibleRange => baseElement.visibleRange;
 
   @override
diff --git a/pkg/analyzer/lib/src/generated/element_handle.dart b/pkg/analyzer/lib/src/generated/element_handle.dart
index 1cba143..e5921d6 100644
--- a/pkg/analyzer/lib/src/generated/element_handle.dart
+++ b/pkg/analyzer/lib/src/generated/element_handle.dart
@@ -549,6 +549,9 @@
 
   @override
   FunctionType get type => actualElement.type;
+
+  @override
+  List<TypeParameterElement> get typeParameters => actualElement.typeParameters;
 }
 
 /**
@@ -919,6 +922,9 @@
   List<ParameterElement> get parameters => actualElement.parameters;
 
   @override
+  List<TypeParameterElement> get typeParameters => actualElement.typeParameters;
+
+  @override
   SourceRange get visibleRange => actualElement.visibleRange;
 }
 
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index 33f470f..c4bc15a 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -10,7 +10,6 @@
 import 'package:analyzer/src/context/cache.dart'
     show CacheEntry, TargetedResult;
 import 'package:analyzer/src/generated/constant.dart';
-import 'package:analyzer/src/services/lint.dart';
 import 'package:analyzer/src/task/dart.dart'
     show
         HINTS,
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index c01e769..49fc6c7 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -2672,7 +2672,9 @@
     //
     ElementHolder holder = new ElementHolder();
     _visitChildren(holder, node);
-    (node.element as ParameterElementImpl).parameters = holder.parameters;
+    ParameterElementImpl element = node.element;
+    element.parameters = holder.parameters;
+    element.typeParameters = holder.typeParameters;
     holder.validate();
     return null;
   }
@@ -2702,6 +2704,7 @@
         element.labels = holder.labels;
         element.localVariables = holder.localVariables;
         element.parameters = holder.parameters;
+        element.typeParameters = holder.typeParameters;
         if (body.isAsynchronous) {
           element.asynchronous = true;
         }
@@ -2809,6 +2812,7 @@
     element.labels = holder.labels;
     element.localVariables = holder.localVariables;
     element.parameters = holder.parameters;
+    element.typeParameters = holder.typeParameters;
     if (body.isAsynchronous) {
       element.asynchronous = true;
     }
@@ -2871,7 +2875,9 @@
     //
     ElementHolder holder = new ElementHolder();
     _visitChildren(holder, node);
-    (node.element as ParameterElementImpl).parameters = holder.parameters;
+    ParameterElementImpl element = node.element;
+    element.parameters = holder.parameters;
+    element.typeParameters = holder.typeParameters;
     holder.validate();
     return null;
   }
@@ -2921,6 +2927,7 @@
         element.localVariables = holder.localVariables;
         element.parameters = holder.parameters;
         element.static = isStatic;
+        element.typeParameters = holder.typeParameters;
         if (body.isAsynchronous) {
           element.asynchronous = true;
         }
@@ -4295,28 +4302,35 @@
 }
 
 /**
- * Instances of the class `FunctionScope` implement the scope defined by a function.
+ * The scope defined by a function.
  */
 class FunctionScope extends EnclosedScope {
+  /**
+   * The element representing the function that defines this scope.
+   */
   final ExecutableElement _functionElement;
 
+  /**
+   * A flag indicating whether the parameters have already been defined, used to
+   * prevent the parameters from being defined multiple times.
+   */
   bool _parametersDefined = false;
 
   /**
-   * Initialize a newly created scope enclosed within another scope.
-   *
-   * @param enclosingScope the scope in which this scope is lexically enclosed
-   * @param functionElement the element representing the type represented by this scope
+   * Initialize a newly created scope enclosed within the [enclosingScope] that
+   * represents the given [_functionElement].
    */
   FunctionScope(Scope enclosingScope, this._functionElement)
-      : super(new EnclosedScope(enclosingScope)) {
+      : super(new EnclosedScope(new EnclosedScope(enclosingScope))) {
     if (_functionElement == null) {
       throw new IllegalArgumentException("function element cannot be null");
     }
+    _defineTypeParameters();
   }
 
   /**
-   * Define the parameters for the given function in the scope that encloses this function.
+   * Define the parameters for the given function in the scope that encloses
+   * this function.
    */
   void defineParameters() {
     if (_parametersDefined) {
@@ -4330,11 +4344,21 @@
       }
     }
   }
+
+  /**
+   * Define the type parameters for the function.
+   */
+  void _defineTypeParameters() {
+    Scope typeParameterScope = enclosingScope.enclosingScope;
+    for (TypeParameterElement typeParameter
+        in _functionElement.typeParameters) {
+      typeParameterScope.define(typeParameter);
+    }
+  }
 }
 
 /**
- * Instances of the class `FunctionTypeScope` implement the scope defined by a function type
- * alias.
+ * The scope defined by a function type alias.
  */
 class FunctionTypeScope extends EnclosedScope {
   final FunctionTypeAliasElement _typeElement;
@@ -4342,10 +4366,8 @@
   bool _parametersDefined = false;
 
   /**
-   * Initialize a newly created scope enclosed within another scope.
-   *
-   * @param enclosingScope the scope in which this scope is lexically enclosed
-   * @param typeElement the element representing the type alias represented by this scope
+   * Initialize a newly created scope enclosed within the [enclosingScope] that
+   * represents the given [_typeElement].
    */
   FunctionTypeScope(Scope enclosingScope, this._typeElement)
       : super(new EnclosedScope(enclosingScope)) {
@@ -4354,8 +4376,6 @@
 
   /**
    * Define the parameters for the function type alias.
-   *
-   * @param typeElement the element representing the type represented by this scope
    */
   void defineParameters() {
     if (_parametersDefined) {
@@ -4369,8 +4389,6 @@
 
   /**
    * Define the type parameters for the function type alias.
-   *
-   * @param typeElement the element representing the type represented by this scope
    */
   void _defineTypeParameters() {
     Scope typeParameterScope = enclosingScope;
@@ -12080,6 +12098,29 @@
   }
 
   @override
+  Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
+    Scope outerScope = nameScope;
+    try {
+      ParameterElement parameterElement = node.element;
+      if (parameterElement == null) {
+        AnalysisEngine.instance.logger.logInformation(
+            "Missing element for function typed formal parameter ${node.identifier.name} in ${definingLibrary.source.fullName}",
+            new CaughtException(new AnalysisException(), null));
+      } else {
+        nameScope = new EnclosedScope(nameScope);
+        for (TypeParameterElement typeParameter
+            in parameterElement.typeParameters) {
+          nameScope.define(typeParameter);
+        }
+      }
+      super.visitFunctionTypedFormalParameter(node);
+    } finally {
+      nameScope = outerScope;
+    }
+    return null;
+  }
+
+  @override
   Object visitIfStatement(IfStatement node) {
     safelyVisit(node.condition);
     visitStatementInScope(node.thenStatement);
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index 75c175a..5b96dbd 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -818,10 +818,11 @@
     if (_packages != null && containedUri.scheme == 'package') {
       Uri packageUri =
           _packages.resolve(containedUri, notFound: (Uri packageUri) => null);
-      //TODO(pquitslund): package_config needs to be updated to set schemes for file URIs.
+      // Ensure scheme is set.
       if (packageUri != null && packageUri.scheme == '') {
-        containedUri = packageUri.replace(scheme: 'file');
+        packageUri = packageUri.replace(scheme: 'file');
       }
+      containedUri = packageUri;
     }
     for (UriResolver resolver in _resolvers) {
       Source result = resolver.resolveAbsolute(containedUri);
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 20f3957..096c14b 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -253,12 +253,14 @@
     }
     ExecutableElement staticMethodElement = node.staticElement;
     DartType staticType = _computeStaticReturnType(staticMethodElement);
-    staticType = _refineBinaryExpressionType(node, staticType);
+    staticType = _refineBinaryExpressionType(node, staticType, _getStaticType);
     _recordStaticType(node, staticType);
     MethodElement propagatedMethodElement = node.propagatedElement;
     if (!identical(propagatedMethodElement, staticMethodElement)) {
       DartType propagatedType =
           _computeStaticReturnType(propagatedMethodElement);
+      propagatedType =
+          _refineBinaryExpressionType(node, propagatedType, _getBestType);
       _resolver.recordPropagatedTypeIfBetter(node, propagatedType);
     }
     return null;
@@ -1381,6 +1383,13 @@
   }
 
   /**
+   * Return the best type of the given [expression].
+   */
+  DartType _getBestType(Expression expression) {
+    return expression.bestType;
+  }
+
+  /**
    * If the given element name can be mapped to the name of a class defined within the given
    * library, return the type specified by the argument.
    *
@@ -1507,10 +1516,7 @@
   }
 
   /**
-   * Return the static type of the given expression.
-   *
-   * @param expression the expression whose type is to be returned
-   * @return the static type of the given expression
+   * Return the static type of the given [expression].
    */
   DartType _getStaticType(Expression expression) {
     DartType type = expression.staticType;
@@ -1697,15 +1703,15 @@
   }
 
   /**
-   * Attempts to make a better guess for the static type of the given binary expression.
-   *
-   * @param node the binary expression to analyze
-   * @param staticType the static type of the expression as resolved
-   * @return the better type guess, or the same static type as given
+   * Attempts to make a better guess for the type of the given binary
+   * [expression], given that resolution has so far produced the [currentType].
+   * The [typeAccessor] is used to access the corresponding type of the left
+   * and right operands.
    */
   DartType _refineBinaryExpressionType(
-      BinaryExpression node, DartType staticType) {
-    sc.TokenType operator = node.operator.type;
+      BinaryExpression expression, DartType currentType,
+      [DartType typeAccessor(Expression node)]) {
+    sc.TokenType operator = expression.operator.type;
     // bool
     if (operator == sc.TokenType.AMPERSAND_AMPERSAND ||
         operator == sc.TokenType.BAR_BAR ||
@@ -1714,14 +1720,14 @@
       return _typeProvider.boolType;
     }
     DartType intType = _typeProvider.intType;
-    if (_getStaticType(node.leftOperand) == intType) {
+    if (typeAccessor(expression.leftOperand) == intType) {
       // int op double
       if (operator == sc.TokenType.MINUS ||
           operator == sc.TokenType.PERCENT ||
           operator == sc.TokenType.PLUS ||
           operator == sc.TokenType.STAR) {
         DartType doubleType = _typeProvider.doubleType;
-        if (_getStaticType(node.rightOperand) == doubleType) {
+        if (typeAccessor(expression.rightOperand) == doubleType) {
           return doubleType;
         }
       }
@@ -1731,13 +1737,13 @@
           operator == sc.TokenType.PLUS ||
           operator == sc.TokenType.STAR ||
           operator == sc.TokenType.TILDE_SLASH) {
-        if (_getStaticType(node.rightOperand) == intType) {
-          staticType = intType;
+        if (typeAccessor(expression.rightOperand) == intType) {
+          return intType;
         }
       }
     }
     // default
-    return staticType;
+    return currentType;
   }
 
   /**
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 961627c..99ad62c 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.25.1
+version: 0.25.2-alpha.1
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: http://www.dartlang.org
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index 0a1b03a..1b13295 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -5391,6 +5391,7 @@
     expect(declaration.functionExpression.element, same(function));
     expect(function.isExternal, isTrue);
     expect(function.isSynthetic, isFalse);
+    expect(function.typeParameters, hasLength(0));
   }
 
   void test_visitFunctionDeclaration_getter() {
@@ -5412,6 +5413,7 @@
     expect(accessor.isExternal, isFalse);
     expect(accessor.isSetter, isFalse);
     expect(accessor.isSynthetic, isFalse);
+    expect(accessor.typeParameters, hasLength(0));
     PropertyInducingElement variable = accessor.variable;
     EngineTestCase.assertInstanceOf((obj) => obj is TopLevelVariableElement,
         TopLevelVariableElement, variable);
@@ -5435,6 +5437,7 @@
     expect(declaration.functionExpression.element, same(function));
     expect(function.isExternal, isFalse);
     expect(function.isSynthetic, isFalse);
+    expect(function.typeParameters, hasLength(0));
   }
 
   void test_visitFunctionDeclaration_setter() {
@@ -5456,12 +5459,40 @@
     expect(accessor.isExternal, isFalse);
     expect(accessor.isSetter, isTrue);
     expect(accessor.isSynthetic, isFalse);
+    expect(accessor.typeParameters, hasLength(0));
     PropertyInducingElement variable = accessor.variable;
     EngineTestCase.assertInstanceOf((obj) => obj is TopLevelVariableElement,
         TopLevelVariableElement, variable);
     expect(variable.isSynthetic, isTrue);
   }
 
+  void test_visitFunctionDeclaration_typeParameters() {
+    ElementHolder holder = new ElementHolder();
+    ElementBuilder builder = new ElementBuilder(holder);
+    String functionName = 'f';
+    String typeParameterName = 'E';
+    FunctionExpression expression = AstFactory.functionExpression3(
+        AstFactory.typeParameterList([typeParameterName]),
+        AstFactory.formalParameterList(), AstFactory.blockFunctionBody2());
+    FunctionDeclaration declaration =
+        AstFactory.functionDeclaration(null, null, functionName, expression);
+    declaration.accept(builder);
+    List<FunctionElement> functions = holder.functions;
+    expect(functions, hasLength(1));
+    FunctionElement function = functions[0];
+    expect(function, isNotNull);
+    expect(function.name, functionName);
+    expect(function.isExternal, isFalse);
+    expect(function.isSynthetic, isFalse);
+    expect(declaration.element, same(function));
+    expect(expression.element, same(function));
+    List<TypeParameterElement> typeParameters = function.typeParameters;
+    expect(typeParameters, hasLength(1));
+    TypeParameterElement typeParameter = typeParameters[0];
+    expect(typeParameter, isNotNull);
+    expect(typeParameter.name, typeParameterName);
+  }
+
   void test_visitFunctionExpression() {
     ElementHolder holder = new ElementHolder();
     ElementBuilder builder = new ElementBuilder(holder);
@@ -5474,6 +5505,7 @@
     expect(function, isNotNull);
     expect(expression.element, same(function));
     expect(function.isSynthetic, isFalse);
+    expect(function.typeParameters, hasLength(0));
   }
 
   void test_visitFunctionTypeAlias() {
@@ -5515,11 +5547,34 @@
     expect(parameter.isFinal, isFalse);
     expect(parameter.isSynthetic, isFalse);
     expect(parameter.parameterKind, ParameterKind.REQUIRED);
-    {
-      SourceRange visibleRange = parameter.visibleRange;
-      expect(100, visibleRange.offset);
-      expect(110, visibleRange.end);
-    }
+    SourceRange visibleRange = parameter.visibleRange;
+    expect(100, visibleRange.offset);
+    expect(110, visibleRange.end);
+  }
+
+  void test_visitFunctionTypedFormalParameter_withTypeParameters() {
+    ElementHolder holder = new ElementHolder();
+    ElementBuilder builder = new ElementBuilder(holder);
+    String parameterName = "p";
+    FunctionTypedFormalParameter formalParameter =
+        AstFactory.functionTypedFormalParameter(null, parameterName);
+    formalParameter.typeParameters = AstFactory.typeParameterList(['F']);
+    _useParameterInMethod(formalParameter, 100, 110);
+    formalParameter.accept(builder);
+    List<ParameterElement> parameters = holder.parameters;
+    expect(parameters, hasLength(1));
+    ParameterElement parameter = parameters[0];
+    expect(parameter, isNotNull);
+    expect(parameter.name, parameterName);
+    expect(parameter.initializer, isNull);
+    expect(parameter.isConst, isFalse);
+    expect(parameter.isFinal, isFalse);
+    expect(parameter.isSynthetic, isFalse);
+    expect(parameter.parameterKind, ParameterKind.REQUIRED);
+    expect(parameter.typeParameters, hasLength(1));
+    SourceRange visibleRange = parameter.visibleRange;
+    expect(100, visibleRange.offset);
+    expect(110, visibleRange.end);
   }
 
   void test_visitLabeledStatement() {
@@ -5554,6 +5609,7 @@
     expect(method.labels, hasLength(0));
     expect(method.localVariables, hasLength(0));
     expect(method.parameters, hasLength(0));
+    expect(method.typeParameters, hasLength(0));
     expect(method.isAbstract, isTrue);
     expect(method.isExternal, isFalse);
     expect(method.isStatic, isFalse);
@@ -5579,6 +5635,7 @@
     expect(method.labels, hasLength(0));
     expect(method.localVariables, hasLength(0));
     expect(method.parameters, hasLength(0));
+    expect(method.typeParameters, hasLength(0));
     expect(method.isAbstract, isFalse);
     expect(method.isExternal, isTrue);
     expect(method.isStatic, isFalse);
@@ -5691,6 +5748,7 @@
     expect(method.labels, hasLength(0));
     expect(method.localVariables, hasLength(0));
     expect(method.parameters, hasLength(0));
+    expect(method.typeParameters, hasLength(0));
     expect(method.isAbstract, isFalse);
     expect(method.isExternal, isFalse);
     expect(method.isStatic, isFalse);
@@ -5716,6 +5774,7 @@
     expect(method.labels, hasLength(0));
     expect(method.localVariables, hasLength(0));
     expect(method.parameters, hasLength(1));
+    expect(method.typeParameters, hasLength(0));
     expect(method.isAbstract, isFalse);
     expect(method.isExternal, isFalse);
     expect(method.isStatic, isFalse);
@@ -5831,12 +5890,38 @@
     expect(method.labels, hasLength(0));
     expect(method.localVariables, hasLength(0));
     expect(method.parameters, hasLength(0));
+    expect(method.typeParameters, hasLength(0));
     expect(method.isAbstract, isFalse);
     expect(method.isExternal, isFalse);
     expect(method.isStatic, isTrue);
     expect(method.isSynthetic, isFalse);
   }
 
+  void test_visitMethodDeclaration_typeParameters() {
+    ElementHolder holder = new ElementHolder();
+    ElementBuilder builder = new ElementBuilder(holder);
+    String methodName = "m";
+    MethodDeclaration methodDeclaration = AstFactory.methodDeclaration2(null,
+        null, null, null, AstFactory.identifier3(methodName),
+        AstFactory.formalParameterList(), AstFactory.blockFunctionBody2());
+    methodDeclaration.typeParameters = AstFactory.typeParameterList(['E']);
+    methodDeclaration.accept(builder);
+    List<MethodElement> methods = holder.methods;
+    expect(methods, hasLength(1));
+    MethodElement method = methods[0];
+    expect(method, isNotNull);
+    expect(method.name, methodName);
+    expect(method.functions, hasLength(0));
+    expect(method.labels, hasLength(0));
+    expect(method.localVariables, hasLength(0));
+    expect(method.parameters, hasLength(0));
+    expect(method.typeParameters, hasLength(1));
+    expect(method.isAbstract, isFalse);
+    expect(method.isExternal, isFalse);
+    expect(method.isStatic, isFalse);
+    expect(method.isSynthetic, isFalse);
+  }
+
   void test_visitMethodDeclaration_withMembers() {
     ElementHolder holder = new ElementHolder();
     ElementBuilder builder = new ElementBuilder(holder);
@@ -5863,6 +5948,7 @@
     MethodElement method = methods[0];
     expect(method, isNotNull);
     expect(method.name, methodName);
+    expect(method.typeParameters, hasLength(0));
     expect(method.isAbstract, isFalse);
     expect(method.isExternal, isFalse);
     expect(method.isStatic, isFalse);
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index e07053d..1e17493 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -10111,6 +10111,17 @@
     _listener.assertNoErrors();
   }
 
+  void test_visitBinaryExpression_minusID_propagated() {
+    // a - b
+    BinaryExpression node = AstFactory.binaryExpression(
+        _propagatedVariable(_typeProvider.intType, 'a'), TokenType.MINUS,
+        _propagatedVariable(_typeProvider.doubleType, 'b'));
+    node.propagatedElement = getMethod(_typeProvider.numType, "+");
+    _analyze(node);
+    expect(node.propagatedType, same(_typeProvider.doubleType));
+    _listener.assertNoErrors();
+  }
+
   void test_visitBinaryExpression_notEquals() {
     // 2 != 3
     Expression node = AstFactory.binaryExpression(
@@ -10137,6 +10148,17 @@
     _listener.assertNoErrors();
   }
 
+  void test_visitBinaryExpression_plusII_propagated() {
+    // a + b
+    BinaryExpression node = AstFactory.binaryExpression(
+        _propagatedVariable(_typeProvider.intType, 'a'), TokenType.PLUS,
+        _propagatedVariable(_typeProvider.intType, 'b'));
+    node.propagatedElement = getMethod(_typeProvider.numType, "+");
+    _analyze(node);
+    expect(node.propagatedType, same(_typeProvider.intType));
+    _listener.assertNoErrors();
+  }
+
   void test_visitBinaryExpression_slash() {
     // 2 / 2
     BinaryExpression node = AstFactory.binaryExpression(
@@ -11104,6 +11126,25 @@
       StaticTypeAnalyzer.flattenFutures(_typeProvider, type);
 
   /**
+   * Return a simple identifier that has been resolved to a variable element with the given type.
+   *
+   * @param type the type of the variable being represented
+   * @param variableName the name of the variable
+   * @return a simple identifier that has been resolved to a variable element with the given type
+   */
+  SimpleIdentifier _propagatedVariable(
+      InterfaceType type, String variableName) {
+    SimpleIdentifier identifier = AstFactory.identifier3(variableName);
+    VariableElementImpl element =
+        ElementFactory.localVariableElement(identifier);
+    element.type = type;
+    identifier.staticType = _typeProvider.dynamicType;
+    identifier.propagatedElement = element;
+    identifier.propagatedType = type;
+    return identifier;
+  }
+
+  /**
    * Return an integer literal that has been resolved to the correct type.
    *
    * @param value the value of the literal
@@ -13376,26 +13417,11 @@
     _listener.assertNoErrors();
   }
 
-  void fail_visitFunctionDeclaration() {
-    fail("Not yet tested");
-    _listener.assertNoErrors();
-  }
-
   void fail_visitFunctionTypeAlias() {
     fail("Not yet tested");
     _listener.assertNoErrors();
   }
 
-  void fail_visitFunctionTypedFormalParameter() {
-    fail("Not yet tested");
-    _listener.assertNoErrors();
-  }
-
-  void fail_visitMethodDeclaration() {
-    fail("Not yet tested");
-    _listener.assertNoErrors();
-  }
-
   void fail_visitVariableDeclaration() {
     fail("Not yet tested");
     ClassElement type = ElementFactory.classElement2("A");
@@ -13698,6 +13724,148 @@
     _listener.assertNoErrors();
   }
 
+  void test_visitFunctionDeclaration() {
+    // R f(P p) {}
+    // class R {}
+    // class P {}
+    ClassElement elementR = ElementFactory.classElement2('R');
+    ClassElement elementP = ElementFactory.classElement2('P');
+    FunctionElement elementF = ElementFactory.functionElement('f');
+    FunctionDeclaration declaration = AstFactory.functionDeclaration(
+        AstFactory.typeName4('R'), null, 'f', AstFactory.functionExpression2(
+            AstFactory.formalParameterList([
+      AstFactory.simpleFormalParameter4(AstFactory.typeName4('P'), 'p')
+    ]), null));
+    declaration.name.staticElement = elementF;
+    _resolveNode(declaration, [elementR, elementP]);
+    expect(declaration.returnType.type, elementR.type);
+    SimpleFormalParameter parameter =
+        declaration.functionExpression.parameters.parameters[0];
+    expect(parameter.type.type, elementP.type);
+    _listener.assertNoErrors();
+  }
+
+  void test_visitFunctionDeclaration_typeParameter() {
+    // E f<E>(E e) {}
+    TypeParameterElement elementE = ElementFactory.typeParameterElement('E');
+    FunctionElementImpl elementF = ElementFactory.functionElement('f');
+    elementF.typeParameters = <TypeParameterElement>[elementE];
+    FunctionDeclaration declaration = AstFactory.functionDeclaration(
+        AstFactory.typeName4('E'), null, 'f', AstFactory.functionExpression2(
+            AstFactory.formalParameterList([
+      AstFactory.simpleFormalParameter4(AstFactory.typeName4('E'), 'e')
+    ]), null));
+    declaration.name.staticElement = elementF;
+    _resolveNode(declaration, []);
+    expect(declaration.returnType.type, elementE.type);
+    SimpleFormalParameter parameter =
+        declaration.functionExpression.parameters.parameters[0];
+    expect(parameter.type.type, elementE.type);
+    _listener.assertNoErrors();
+  }
+
+  void test_visitFunctionTypedFormalParameter() {
+    // R f(R g(P p)) {}
+    // class R {}
+    // class P {}
+    ClassElement elementR = ElementFactory.classElement2('R');
+    ClassElement elementP = ElementFactory.classElement2('P');
+    FunctionElement elementF = ElementFactory.functionElement('f');
+    ParameterElementImpl requiredParameter =
+        ElementFactory.requiredParameter('p');
+    FunctionTypedFormalParameter parameterDeclaration = AstFactory
+        .functionTypedFormalParameter(AstFactory.typeName4('R'), 'g', [
+      AstFactory.simpleFormalParameter4(AstFactory.typeName4('P'), 'p')
+    ]);
+    parameterDeclaration.identifier.staticElement = requiredParameter;
+    FunctionDeclaration declaration = AstFactory.functionDeclaration(
+        AstFactory.typeName4('R'), null, 'f', AstFactory.functionExpression2(
+            AstFactory.formalParameterList([parameterDeclaration]), null));
+    declaration.name.staticElement = elementF;
+    _resolveNode(declaration, [elementR, elementP]);
+    expect(declaration.returnType.type, elementR.type);
+    FunctionTypedFormalParameter parameter =
+        declaration.functionExpression.parameters.parameters[0];
+    expect(parameter.returnType.type, elementR.type);
+    SimpleFormalParameter innerParameter = parameter.parameters.parameters[0];
+    expect(innerParameter.type.type, elementP.type);
+    _listener.assertNoErrors();
+  }
+
+  void test_visitFunctionTypedFormalParameter_typeParameter() {
+    // R f(R g<E>(E e)) {}
+    // class R {}
+    ClassElement elementR = ElementFactory.classElement2('R');
+    TypeParameterElement elementE = ElementFactory.typeParameterElement('E');
+    FunctionElement elementF = ElementFactory.functionElement('f');
+    ParameterElementImpl requiredParameter =
+        ElementFactory.requiredParameter('g');
+    requiredParameter.typeParameters = <TypeParameterElement>[elementE];
+    FunctionTypedFormalParameter parameterDeclaration = AstFactory
+        .functionTypedFormalParameter(AstFactory.typeName4('R'), 'g', [
+      AstFactory.simpleFormalParameter4(AstFactory.typeName4('E'), 'e')
+    ]);
+    parameterDeclaration.identifier.staticElement = requiredParameter;
+    FunctionDeclaration declaration = AstFactory.functionDeclaration(
+        AstFactory.typeName4('R'), null, 'f', AstFactory.functionExpression2(
+            AstFactory.formalParameterList([parameterDeclaration]), null));
+    declaration.name.staticElement = elementF;
+    _resolveNode(declaration, [elementR]);
+    expect(declaration.returnType.type, elementR.type);
+    FunctionTypedFormalParameter parameter =
+        declaration.functionExpression.parameters.parameters[0];
+    expect(parameter.returnType.type, elementR.type);
+    SimpleFormalParameter innerParameter = parameter.parameters.parameters[0];
+    expect(innerParameter.type.type, elementE.type);
+    _listener.assertNoErrors();
+  }
+
+  void test_visitMethodDeclaration() {
+    // class A {
+    //   R m(P p) {}
+    // }
+    // class R {}
+    // class P {}
+    ClassElementImpl elementA = ElementFactory.classElement2('A');
+    ClassElement elementR = ElementFactory.classElement2('R');
+    ClassElement elementP = ElementFactory.classElement2('P');
+    MethodElement elementM = ElementFactory.methodElement('m', null);
+    elementA.methods = <MethodElement>[elementM];
+    MethodDeclaration declaration = AstFactory.methodDeclaration(null,
+        AstFactory.typeName4('R'), null, null, AstFactory.identifier3('m'),
+        AstFactory.formalParameterList([
+      AstFactory.simpleFormalParameter4(AstFactory.typeName4('P'), 'p')
+    ]));
+    declaration.name.staticElement = elementM;
+    _resolveNode(declaration, [elementA, elementR, elementP]);
+    expect(declaration.returnType.type, elementR.type);
+    SimpleFormalParameter parameter = declaration.parameters.parameters[0];
+    expect(parameter.type.type, elementP.type);
+    _listener.assertNoErrors();
+  }
+
+  void test_visitMethodDeclaration_typeParameter() {
+    // class A {
+    //   E m<E>(E e) {}
+    // }
+    ClassElementImpl elementA = ElementFactory.classElement2('A');
+    TypeParameterElement elementE = ElementFactory.typeParameterElement('E');
+    MethodElementImpl elementM = ElementFactory.methodElement('m', null);
+    elementM.typeParameters = <TypeParameterElement>[elementE];
+    elementA.methods = <MethodElement>[elementM];
+    MethodDeclaration declaration = AstFactory.methodDeclaration(null,
+        AstFactory.typeName4('E'), null, null, AstFactory.identifier3('m'),
+        AstFactory.formalParameterList([
+      AstFactory.simpleFormalParameter4(AstFactory.typeName4('E'), 'e')
+    ]));
+    declaration.name.staticElement = elementM;
+    _resolveNode(declaration, [elementA]);
+    expect(declaration.returnType.type, elementE.type);
+    SimpleFormalParameter parameter = declaration.parameters.parameters[0];
+    expect(parameter.type.type, elementE.type);
+    _listener.assertNoErrors();
+  }
+
   void test_visitSimpleFormalParameter_noType() {
     // p
     FormalParameter node = AstFactory.simpleFormalParameter3("p");
diff --git a/pkg/analyzer/test/generated/source_factory_test.dart b/pkg/analyzer/test/generated/source_factory_test.dart
index e510949..7ff5572 100644
--- a/pkg/analyzer/test/generated/source_factory_test.dart
+++ b/pkg/analyzer/test/generated/source_factory_test.dart
@@ -77,6 +77,15 @@
       group('resolveUri', () {
         test('URI in mapping', () {
           String uri = resolvePackageUri(config: '''
+unittest:file:///home/somebody/.pub/cache/unittest-0.9.9/lib/
+async:file:///home/somebody/.pub/cache/async-1.1.0/lib/
+quiver:file:///home/somebody/.pub/cache/quiver-1.2.1/lib
+''', uri: 'package:unittest/unittest.dart');
+          expect(uri, equals(
+              '/home/somebody/.pub/cache/unittest-0.9.9/lib/unittest.dart'));
+        });
+        test('URI in mapping (no scheme)', () {
+          String uri = resolvePackageUri(config: '''
 unittest:/home/somebody/.pub/cache/unittest-0.9.9/lib/
 async:/home/somebody/.pub/cache/async-1.1.0/lib/
 quiver:/home/somebody/.pub/cache/quiver-1.2.1/lib
diff --git a/pkg/analyzer/test/source/sdk_ext_test.dart b/pkg/analyzer/test/source/sdk_ext_test.dart
new file mode 100644
index 0000000..288fe37
--- /dev/null
+++ b/pkg/analyzer/test/source/sdk_ext_test.dart
@@ -0,0 +1,96 @@
+// 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.
+
+library test.source.sdk_ext;
+
+import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/source/sdk_ext.dart';
+import 'package:unittest/unittest.dart';
+
+main() {
+  groupSep = ' | ';
+  group('SdkExtUriResolverTest', () {
+    setUp(() {
+      buildResourceProvider();
+    });
+    tearDown(() {
+      clearResourceProvider();
+    });
+    test('test_NullPackageMap', () {
+      var resolver = new SdkExtUriResolver(null);
+      expect(resolver.length, equals(0));
+    });
+    test('test_NoSdkExtPackageMap', () {
+      var resolver = new SdkExtUriResolver({
+        'fox': [resourceProvider.getResource('/empty')]
+      });
+      expect(resolver.length, equals(0));
+    });
+    test('test_SdkExtPackageMap', () {
+      var resolver = new SdkExtUriResolver({
+        'fox': [resourceProvider.getResource('/tmp')]
+      });
+      // We have four mappings.
+      expect(resolver.length, equals(4));
+      // Check that they map to the correct paths.
+      expect(resolver['dart:fox'], equals("/tmp/slippy.dart"));
+      expect(resolver['dart:bear'], equals("/tmp/grizzly.dart"));
+      expect(resolver['dart:relative'], equals("/relative.dart"));
+      expect(resolver['dart:deep'], equals("/tmp/deep/directory/file.dart"));
+    });
+    test('test_BadJSON', () {
+      var resolver = new SdkExtUriResolver(null);
+      resolver.addSdkExt(r'''{{{,{{}}},}}''', null);
+      expect(resolver.length, equals(0));
+    });
+    test('test_restoreAbsolute', () {
+      var resolver = new SdkExtUriResolver({
+        'fox': [resourceProvider.getResource('/tmp')]
+      });
+      var source = resolver.resolveAbsolute(Uri.parse('dart:fox'));
+      expect(source, isNotNull);
+      // Restore source's uri.
+      var restoreUri = resolver.restoreAbsolute(source);
+      expect(restoreUri, isNotNull);
+      // Verify that it is 'dart:fox'.
+      expect(restoreUri.toString(), equals('dart:fox'));
+      expect(restoreUri.scheme, equals('dart'));
+      expect(restoreUri.path, equals('fox'));
+    });
+    test('test_resolvePart', () {
+      var resolver = new SdkExtUriResolver({
+        'fox': [resourceProvider.getResource('/tmp')]
+      });
+      var source = resolver.resolveAbsolute(Uri.parse('dart:fox/foo.dart'));
+      expect(source, isNotNull);
+      // Restore source's uri.
+      var restoreUri = resolver.restoreAbsolute(source);
+      expect(restoreUri, isNotNull);
+      // Verify that it is 'dart:fox/foo.dart'.
+      expect(restoreUri.toString(), equals('dart:fox/foo.dart'));
+      expect(restoreUri.scheme, equals('dart'));
+      expect(restoreUri.path, equals('fox/foo.dart'));
+    });
+  });
+}
+
+MemoryResourceProvider resourceProvider;
+
+buildResourceProvider() {
+  resourceProvider = new MemoryResourceProvider();
+  resourceProvider.newFolder('/empty');
+  resourceProvider.newFolder('/tmp');
+  resourceProvider.newFile('/tmp/_sdkext', r'''
+  {
+    "dart:fox": "slippy.dart",
+    "dart:bear": "grizzly.dart",
+    "dart:relative": "../relative.dart",
+    "dart:deep": "deep/directory/file.dart",
+    "fart:loudly": "nomatter.dart"
+  }''');
+}
+
+clearResourceProvider() {
+  resourceProvider = null;
+}
diff --git a/pkg/analyzer/test/source/test_all.dart b/pkg/analyzer/test/source/test_all.dart
index d2de433..b8c09bf 100644
--- a/pkg/analyzer/test/source/test_all.dart
+++ b/pkg/analyzer/test/source/test_all.dart
@@ -8,6 +8,7 @@
 
 import 'package_map_provider_test.dart' as package_map_provider_test;
 import 'package_map_resolver_test.dart' as package_map_resolver_test;
+import 'sdk_ext_test.dart' as sdk_ext_test;
 
 /// Utility for manually running all tests.
 main() {
@@ -15,5 +16,6 @@
   group('source', () {
     package_map_provider_test.main();
     package_map_resolver_test.main();
+    sdk_ext_test.main();
   });
 }
diff --git a/pkg/analyzer/test/src/task/html_work_manager_test.dart b/pkg/analyzer/test/src/task/html_work_manager_test.dart
index 94015ae..ad1027c 100644
--- a/pkg/analyzer/test/src/task/html_work_manager_test.dart
+++ b/pkg/analyzer/test/src/task/html_work_manager_test.dart
@@ -16,7 +16,6 @@
 import 'package:analyzer/src/generated/error.dart'
     show AnalysisError, HtmlErrorCode;
 import 'package:analyzer/src/generated/java_engine.dart' show CaughtException;
-import 'package:analyzer/src/generated/scanner.dart' show ScannerErrorCode;
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/task/driver.dart';
 import 'package:analyzer/src/task/html.dart';
diff --git a/pkg/analyzer/tool/task_dependency_graph.dart b/pkg/analyzer/tool/task_dependency_graph.dart
new file mode 100644
index 0000000..79e6d50
--- /dev/null
+++ b/pkg/analyzer/tool/task_dependency_graph.dart
@@ -0,0 +1,151 @@
+// 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.
+
+/**
+ * This file contains code to output a description of tasks and their
+ * dependencies in ".dot" format.  Prior to running, the user should run "pub
+ * get" in the analyzer directory to ensure that a "packages" folder exists.
+ *
+ * The ".dot" file is output to standard out.  To convert it to a pdf, store it
+ * in a file (e.g. "tasks.dot"), and post-process it with
+ * "dot tasks.dart -Tpdf -O".
+ *
+ * TODO(paulberry):
+ * - Add general.dart and html.dart for completeness.
+ * - Use Graphviz's "record" feature to produce more compact output
+ *   (http://www.graphviz.org/content/node-shapes#record)
+ * - Produce a warning if a result descriptor is found which isn't the output
+ *   of exactly one task.
+ * - Convert this tool to use package_config to find the package map.
+ */
+library task_dependency_graph;
+
+import 'dart:io' hide File;
+
+import 'package:analyzer/analyzer.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/src/generated/element.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/java_io.dart';
+import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/src/generated/sdk_io.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+import 'package:path/path.dart' as path;
+
+main() {
+  new Driver().run();
+}
+
+typedef void ResultDescriptorFinderCallback(PropertyAccessorElement element);
+
+class Driver {
+  PhysicalResourceProvider resourceProvider;
+  AnalysisContext context;
+  InterfaceType resultDescriptorType;
+  String rootDir;
+
+  void findResultDescriptors(
+      AstNode node, void callback(String descriptorName)) {
+    Set<PropertyAccessorElement> resultDescriptors =
+        new Set<PropertyAccessorElement>();
+    node.accept(new ResultDescriptorFinder(
+        resultDescriptorType, resultDescriptors.add));
+    for (PropertyAccessorElement resultDescriptor in resultDescriptors) {
+      callback(resultDescriptor.name);
+    }
+  }
+
+  /**
+   * Find the root directory of the analyzer package by proceeding
+   * upward to the 'tool' dir, and then going up one more directory.
+   */
+  String findRoot(String pathname) {
+    while (path.basename(pathname) != 'tool') {
+      String parent = path.dirname(pathname);
+      if (parent.length >= pathname.length) {
+        throw new Exception("Can't find root directory");
+      }
+      pathname = parent;
+    }
+    return path.dirname(pathname);
+  }
+
+  CompilationUnit getUnit(Source source) =>
+      context.resolveCompilationUnit2(source, source);
+
+  void run() {
+    rootDir = findRoot(Platform.script.toFilePath(windows: Platform.isWindows));
+    resourceProvider = PhysicalResourceProvider.INSTANCE;
+    DartSdk sdk = DirectoryBasedDartSdk.defaultSdk;
+    context = AnalysisEngine.instance.createAnalysisContext();
+    JavaFile packagesDir = new JavaFile(path.join(rootDir, 'packages'));
+    List<UriResolver> uriResolvers = [
+      new FileUriResolver(),
+      new DartUriResolver(sdk),
+      new PackageUriResolver(<JavaFile>[packagesDir])
+    ];
+    context.sourceFactory = new SourceFactory(uriResolvers);
+    Source taskSource =
+        setupSource(path.join('lib', 'src', 'task', 'dart.dart'));
+    Source modelSource = setupSource(path.join('lib', 'task', 'model.dart'));
+    CompilationUnitElement modelElement = getUnit(modelSource).element;
+    InterfaceType analysisTaskType = modelElement.getType('AnalysisTask').type;
+    DartType dynamicType = context.typeProvider.dynamicType;
+    resultDescriptorType = modelElement.getType('ResultDescriptor').type
+        .substitute4([dynamicType]);
+    CompilationUnit taskUnit = getUnit(taskSource);
+    CompilationUnitElement taskUnitElement = taskUnit.element;
+    print('digraph G {');
+    Set<String> results = new Set<String>();
+    for (ClassElement cls in taskUnitElement.types) {
+      if (!cls.isAbstract && cls.type.isSubtypeOf(analysisTaskType)) {
+        String task = cls.name;
+        // TODO(paulberry): node is deprecated.  What am I supposed to do
+        // instead?
+        findResultDescriptors(cls.getMethod('buildInputs').node,
+            (String input) {
+          results.add(input);
+          print('  $input -> $task');
+        });
+        findResultDescriptors(cls.getField('DESCRIPTOR').node, (String output) {
+          results.add(output);
+          print('  $task -> $output');
+        });
+      }
+    }
+    for (String result in results) {
+      print('  $result [shape=box]');
+    }
+    print('}');
+  }
+
+  Source setupSource(String filename) {
+    String filePath = path.join(rootDir, filename);
+    File file = resourceProvider.getResource(filePath);
+    Source source = file.createSource();
+    ChangeSet changeSet = new ChangeSet();
+    changeSet.addedSource(source);
+    context.applyChanges(changeSet);
+    return source;
+  }
+}
+
+class ResultDescriptorFinder extends GeneralizingAstVisitor {
+  final InterfaceType resultDescriptorType;
+  final ResultDescriptorFinderCallback callback;
+
+  ResultDescriptorFinder(this.resultDescriptorType, this.callback);
+
+  @override
+  visitIdentifier(Identifier node) {
+    Element element = node.staticElement;
+    if (element is PropertyAccessorElement &&
+        element.isGetter &&
+        element.returnType.isSubtypeOf(resultDescriptorType)) {
+      callback(element);
+    }
+  }
+}
diff --git a/pkg/compiler/lib/src/apiimpl.dart b/pkg/compiler/lib/src/apiimpl.dart
index 9fd865a..c65cbc5 100644
--- a/pkg/compiler/lib/src/apiimpl.dart
+++ b/pkg/compiler/lib/src/apiimpl.dart
@@ -104,9 +104,7 @@
                 hasOption(options, '--generate-code-with-compile-time-errors'),
             testMode: hasOption(options, '--test-mode'),
             allowNativeExtensions:
-                hasOption(options, '--allow-native-extensions'),
-            enableNullAwareOperators:
-                hasOption(options, '--enable-null-aware-operators')) {
+                hasOption(options, '--allow-native-extensions')) {
     tasks.addAll([
         userHandlerTask = new leg.GenericTask('Diagnostic handler', this),
         userProviderTask = new leg.GenericTask('Input provider', this),
@@ -369,46 +367,52 @@
         });
   }
 
-  Future setupPackages(Uri uri) async {
+  Future setupPackages(Uri uri) {
     if (packageRoot != null) {
       // Use "non-file" packages because the file version requires a [Directory]
       // and we can't depend on 'dart:io' classes.
       packages = new NonFilePackagesDirectoryPackages(packageRoot);
     } else if (packageConfig != null) {
-      var packageConfigContents = await provider(packageConfig);
-      if (packageConfigContents is String) {
-        packageConfigContents = UTF8.encode(packageConfigContents);
-      }
-      packages =
-          new MapPackages(pkgs.parse(packageConfigContents, packageConfig));
+      return provider(packageConfig).then((packageConfigContents) {
+        if (packageConfigContents is String) {
+          packageConfigContents = UTF8.encode(packageConfigContents);
+        }
+        packages =
+            new MapPackages(pkgs.parse(packageConfigContents, packageConfig));
+      });
     } else {
       if (packagesDiscoveryProvider == null) {
         packages = Packages.noPackages;
       } else {
-        packages = await callUserPackagesDiscovery(uri);
+        return callUserPackagesDiscovery(uri).then((p) {
+          packages = p;
+        });
       }
     }
+    return new Future.value();
   }
 
-  Future<bool> run(Uri uri) async {
+  Future<bool> run(Uri uri) {
     log('Allowed library categories: $allowedLibraryCategories');
 
-    await setupPackages(uri);
-    assert(packages != null);
+    return setupPackages(uri).then((_) {
+      assert(packages != null);
 
-    bool success = await super.run(uri);
-    int cumulated = 0;
-    for (final task in tasks) {
-      int elapsed = task.timing;
-      if (elapsed != 0) {
-        cumulated += elapsed;
-        log('${task.name} took ${elapsed}msec');
-      }
-    }
-    int total = totalCompileTime.elapsedMilliseconds;
-    log('Total compile-time ${total}msec;'
-        ' unaccounted ${total - cumulated}msec');
-    return success;
+      return super.run(uri).then((bool success) {
+        int cumulated = 0;
+        for (final task in tasks) {
+          int elapsed = task.timing;
+          if (elapsed != 0) {
+            cumulated += elapsed;
+            log('${task.name} took ${elapsed}msec');
+          }
+        }
+        int total = totalCompileTime.elapsedMilliseconds;
+        log('Total compile-time ${total}msec;'
+            ' unaccounted ${total - cumulated}msec');
+        return success;
+      });
+    });
   }
 
   void reportDiagnostic(leg.Spannable node,
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 8360a5d..0cc5a67 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -791,10 +791,6 @@
   /// If `true` native extension syntax is supported by the frontend.
   final bool allowNativeExtensions;
 
-  /// Temporary flag to enable `?.`, `??`, and `??=` until it becomes part of
-  /// the spec.
-  final bool enableNullAwareOperators;
-
   /// Output provider from user of Compiler API.
   api.CompilerOutputProvider userOutputProvider;
 
@@ -1063,7 +1059,6 @@
             bool hasIncrementalSupport: false,
             this.enableExperimentalMirrors: false,
             this.allowNativeExtensions: false,
-            this.enableNullAwareOperators: false,
             this.generateCodeWithCompileTimeErrors: false,
             this.testMode: false,
             api.CompilerOutputProvider outputProvider,
diff --git a/pkg/compiler/lib/src/cps_ir/cps_fragment.dart b/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
new file mode 100644
index 0000000..6eda707
--- /dev/null
+++ b/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
@@ -0,0 +1,292 @@
+// 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.
+
+library cps_ir.cps_fragment;
+
+import 'cps_ir_nodes.dart';
+import '../constants/values.dart';
+import '../universe/universe.dart' show Selector;
+import '../types/types.dart' show TypeMask;
+import '../io/source_information.dart';
+import '../elements/elements.dart';
+
+/// Builds a CPS fragment that can be plugged into another CPS term.
+///
+/// A CPS fragment contains a CPS term, possibly with a "hole" in it denoting
+/// where to insert new IR nodes. We say a fragment is "open" if it has such
+/// a hole. Otherwise, the fragment is "closed" and cannot be extended further.
+///
+/// This class is designed for building non-trivial CPS terms in a readable and
+/// non-error prone manner. It is not designed to manipulate existing IR nodes,
+/// nor is it intended to shield the user from every complexity in the IR.
+///
+/// EXAMPLES:
+///
+/// Call `cont` with `obj.field + 1` as argument:
+///
+///   CpsFragment cps = new CpsFragment();
+///   var fieldValue = cps.letPrim(new GetField(obj, field));
+///   var plusOne = cps.applyBuiltin(BuiltinOperator.NumAdd,
+///                                  [fieldValue, cps.makeOne()]);
+///   cps.invokeContinuation(cont, [plusOne]);
+///
+/// If `condition` is true then invoke `cont1`, else `cont2`.
+///
+///   cps.ifTrue(condition).invokeContinuation(cont1, []);
+///   cps.invokeContinuation(cont2, []);
+///
+/// If `condition` is true then invoke `cont` with a bound primitive:
+///
+///   CpsFragment branch = cps.ifTrue(condition);
+///   branch.invokeContinuation(cont, [branch.letPrim(arg)]);
+///
+/// Loop and call a method until it returns false:
+///
+///   Continuation loop = cps.beginLoop();
+///   var result = cps.invokeMethod(receiver, selector, ...);
+///   cps.ifFalse(result).invokeContinuation(exit, []);
+///   cps.continueLoop(loop);
+///
+class CpsFragment {
+  /// The root of the IR built using this fragment.
+  Expression root;
+
+  /// Node whose body is the hole in this CPS fragment. May be null.
+  InteriorNode context;
+
+  /// Source information to attach to every IR node created in the fragment.
+  SourceInformation sourceInformation;
+
+  CpsFragment([this.sourceInformation, this.context]);
+
+  bool get isOpen => root == null || context != null;
+  bool get isClosed => !isOpen;
+  bool get isEmpty => root == null;
+
+  /// Asserts that the fragment is non-empty and closed and returns the IR that
+  /// was built.
+  Expression get result {
+    assert(!isEmpty);
+    assert(isClosed);
+    return root;
+  }
+
+  /// Put the given expression into the fragment's hole.
+  ///
+  /// Afterwards the fragment is closed and cannot be extended until a new
+  /// [context] is set.
+  void put(Expression node) {
+    assert(root == null || context != null); // We must put the node somewhere.
+    if (root == null) {
+      root = node;
+    }
+    if (context != null) {
+      context.body = node;
+    }
+    context = null;
+  }
+
+  /// Bind a primitive. Returns the same primitive for convenience.
+  Primitive letPrim(Primitive prim) {
+    assert(prim != null);
+    LetPrim let = new LetPrim(prim);
+    put(let);
+    context = let;
+    return prim;
+  }
+
+  /// Bind a constant value.
+  Primitive makeConstant(ConstantValue constant) {
+    return letPrim(new Constant(constant));
+  }
+
+  Primitive makeZero() => makeConstant(new IntConstantValue(0));
+  Primitive makeOne() => makeConstant(new IntConstantValue(1));
+  Primitive makeNull() => makeConstant(new NullConstantValue());
+  Primitive makeTrue() => makeConstant(new TrueConstantValue());
+  Primitive makeFalse() => makeConstant(new FalseConstantValue());
+
+  /// Invoke a built-in operator.
+  Primitive applyBuiltin(BuiltinOperator op, List<Primitive> args) {
+    return letPrim(new ApplyBuiltinOperator(op, args));
+  }
+
+  /// Inserts an invocation. binds its continuation, and returns the
+  /// continuation parameter (i.e. the return value of the invocation).
+  ///
+  /// The continuation body becomes the new hole.
+  Parameter invokeMethod(Primitive receiver,
+                         Selector selector,
+                         TypeMask mask,
+                         List<Primitive> arguments) {
+    Continuation cont = new Continuation(<Parameter>[new Parameter(null)]);
+    InvokeMethod invoke =
+      new InvokeMethod(receiver, selector, mask, arguments, cont,
+                       sourceInformation);
+    put(new LetCont(cont, invoke));
+    context = cont;
+    return cont.parameters.single;
+  }
+
+  /// Inserts an invocation. binds its continuation, and returns the
+  /// continuation parameter (i.e. the return value of the invocation).
+  ///
+  /// The continuation body becomes the new hole.
+  Parameter invokeStatic(FunctionElement target, List<Primitive> arguments) {
+    Continuation cont = new Continuation(<Parameter>[new Parameter(null)]);
+    InvokeStatic invoke =
+      new InvokeStatic(target, new Selector.fromElement(target), arguments,
+                       cont, sourceInformation);
+    put(new LetCont(cont, invoke));
+    context = cont;
+    return cont.parameters.single;
+  }
+
+  /// Inserts an invocation to a static function that throws an error.
+  ///
+  /// This closes the fragment; no more nodes may be added.
+  void invokeStaticThrower(FunctionElement target, List<Primitive> arguments) {
+    invokeStatic(target, arguments);
+    put(new Unreachable());
+  }
+
+  /// Invoke a non-recursive continuation.
+  ///
+  /// This closes the fragment; no more nodes may be inserted.
+  void invokeContinuation(Continuation cont, [List<Primitive> arguments]) {
+    if (arguments == null) arguments = <Primitive>[];
+    put(new InvokeContinuation(cont, arguments));
+  }
+
+  /// Build a loop with the given loop variables and initial values.
+  /// Call [continueLoop] with the returned continuation to iterate the loop.
+  ///
+  /// The loop body becomes the new hole.
+  Continuation beginLoop([List<Parameter> loopVars,
+                          List<Primitive> initialValues]) {
+    if (initialValues == null) {
+      assert(loopVars == null);
+      loopVars = <Parameter>[];
+      initialValues = <Primitive>[];
+    }
+    Continuation cont = new Continuation(loopVars);
+    put(new LetCont(cont, new InvokeContinuation(cont, initialValues)));
+    context = cont;
+    return cont;
+  }
+
+  /// Continue a loop started by [beginLoop].
+  ///
+  /// This closes the fragment; no more nodes may be inserted.
+  void continueLoop(Continuation cont, [List<Primitive> updatedLoopVariables]) {
+    put(new InvokeContinuation(cont, updatedLoopVariables, isRecursive: true));
+  }
+
+  /// Branch on [condition].
+  ///
+  /// Returns a new fragment for the 'then' branch.
+  ///
+  /// The 'else' branch becomes the new hole.
+  CpsFragment ifTrue(Primitive condition) {
+    Continuation trueCont = new Continuation(<Parameter>[]);
+    Continuation falseCont = new Continuation(<Parameter>[]);
+    put(new LetCont.two(trueCont, falseCont,
+            new Branch(new IsTrue(condition), trueCont, falseCont)));
+    context = falseCont;
+    return new CpsFragment(sourceInformation, trueCont);
+  }
+
+  /// Branch on [condition].
+  ///
+  /// Returns a new fragment for the 'else' branch.
+  ///
+  /// The 'then' branch becomes the new hole.
+  CpsFragment ifFalse(Primitive condition) {
+    Continuation trueCont = new Continuation(<Parameter>[]);
+    Continuation falseCont = new Continuation(<Parameter>[]);
+    put(new LetCont.two(trueCont, falseCont,
+            new Branch(new IsTrue(condition), trueCont, falseCont)));
+    context = trueCont;
+    return new CpsFragment(sourceInformation, falseCont);
+  }
+
+  /// Create a new empty continuation and bind it here.
+  ///
+  /// Convenient for making a join point where multiple branches
+  /// meet later.
+  ///
+  /// The LetCont body becomes the new hole.
+  ///
+  /// Example use:
+  ///
+  ///   Continuation fail = cps.letCont();
+  ///
+  ///   // Fail if something
+  ///   cps.ifTrue(<condition>)
+  ///      ..invokeMethod(<method>)
+  ///      ..invokeContinuation(fail);
+  ///
+  ///   // Fail if something else
+  ///   cps.ifTrue(<anotherCondition>)
+  ///      ..invokeMethod(<anotherMethod>)
+  ///      ..invokeContinuation(fail);
+  ///
+  ///   // Build the fail branch
+  ///   cps.insideContinuation(fail)
+  ///      ..invokeStaticThrower(...);
+  ///
+  ///   // Go to the happy branch
+  ///   cps.invokeContinuation(cont..)
+  ///
+  Continuation letCont([List<Parameter> parameters]) {
+    if (parameters == null) parameters = <Parameter>[];
+    Continuation cont = new Continuation(parameters);
+    LetCont let = new LetCont(cont, null);
+    put(let);
+    context = let;
+    return cont;
+  }
+
+  /// Returns a fragment whose context is the body of the given continuation.
+  ///
+  /// Does not change the state of this CPS fragment.
+  ///
+  /// Useful for building the body of a continuation created using [letCont].
+  CpsFragment insideContinuation(Continuation cont) {
+    return new CpsFragment(sourceInformation, cont);
+  }
+
+  /// Puts the given fragment into this one.
+  /// 
+  /// If [other] was an open fragment, its hole becomes the new hole
+  /// in this fragment.
+  /// 
+  /// [other] is reset to an empty fragment after this.
+  void append(CpsFragment other) {
+    if (other.root == null) return;
+    put(other.root);
+    context = other.context;
+    other.context = null;
+    other.root = null;
+  }
+
+  /// Reads the value of the given mutable variable.
+  Primitive getMutable(MutableVariable variable) {
+    return letPrim(new GetMutableVariable(variable));
+  }
+
+  /// Sets the value of the given mutable variable.
+  void setMutable(MutableVariable variable, Primitive value) {
+    SetMutableVariable setter = new SetMutableVariable(variable, value);
+    put(setter);
+    context = setter;
+  }
+
+  /// Declare a new mutable variable.
+  void letMutable(MutableVariable variable, Primitive initialValue) {
+    LetMutable let = new LetMutable(variable, initialValue);
+    put(let);
+    context = let;
+  }
+}
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
index 6c324d8..cca5f7b 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
@@ -624,12 +624,13 @@
 
   ir.Primitive _buildInvokeSuper(Element target,
                                  Selector selector,
-                                 List<ir.Primitive> arguments) {
+                                 List<ir.Primitive> arguments,
+                                 SourceInformation sourceInformation) {
     assert(target.isInstanceMember);
     assert(isOpen);
     return _continueWithExpression(
         (k) => new ir.InvokeMethodDirectly(
-            buildThis(), target, selector, arguments, k));
+            buildThis(), target, selector, arguments, k, sourceInformation));
   }
 
   ir.Primitive _buildInvokeDynamic(ir.Primitive receiver,
@@ -655,9 +656,11 @@
 
 
   /// Create a [ir.Constant] from [value] and add it to the CPS term.
-  ir.Constant buildConstant(ConstantValue value) {
+  ir.Constant buildConstant(ConstantValue value,
+                            {SourceInformation sourceInformation}) {
     assert(isOpen);
-    return addPrimitive(new ir.Constant(value));
+    return addPrimitive(
+        new ir.Constant(value, sourceInformation: sourceInformation));
   }
 
   /// Create an integer constant and add it to the CPS term.
@@ -793,63 +796,74 @@
   /// Create a invocation of the [method] on the super class where the call
   /// structure is defined [callStructure] and the argument values are defined
   /// by [arguments].
-  ir.Primitive buildSuperMethodInvocation(MethodElement method,
-                                          CallStructure callStructure,
-                                          List<ir.Primitive> arguments) {
+  ir.Primitive buildSuperMethodInvocation(
+      MethodElement method,
+      CallStructure callStructure,
+      List<ir.Primitive> arguments,
+      {SourceInformation sourceInformation}) {
     // TODO(johnniwinther): This shouldn't be necessary.
     SelectorKind kind = Elements.isOperatorName(method.name)
         ? SelectorKind.OPERATOR : SelectorKind.CALL;
     Selector selector =
         new Selector(kind, method.memberName, callStructure);
-    return _buildInvokeSuper(method, selector, arguments);
+    return _buildInvokeSuper(method, selector, arguments, sourceInformation);
   }
 
   /// Create a read access of the [method] on the super class, i.e. a
   /// closurization of [method].
-  ir.Primitive buildSuperMethodGet(MethodElement method) {
+  ir.Primitive buildSuperMethodGet(MethodElement method,
+                                   {SourceInformation sourceInformation}) {
     // TODO(johnniwinther): This should have its own ir node.
     return _buildInvokeSuper(
         method,
         new Selector.getter(method.name, method.library),
-        const <ir.Primitive>[]);
+        const <ir.Primitive>[],
+        sourceInformation);
   }
 
   /// Create a getter invocation of the [getter] on the super class.
-  ir.Primitive buildSuperGetterGet(MethodElement getter) {
+  ir.Primitive buildSuperGetterGet(MethodElement getter,
+                                   SourceInformation sourceInformation) {
     // TODO(johnniwinther): This should have its own ir node.
     return _buildInvokeSuper(
         getter,
         new Selector.getter(getter.name, getter.library),
-        const <ir.Primitive>[]);
+        const <ir.Primitive>[],
+        sourceInformation);
   }
 
   /// Create an setter invocation of the [setter] on the super class with
   /// [value].
   ir.Primitive buildSuperSetterSet(MethodElement setter,
-                                          ir.Primitive value) {
+                                   ir.Primitive value,
+                                   {SourceInformation sourceInformation}) {
     // TODO(johnniwinther): This should have its own ir node.
     _buildInvokeSuper(
         setter,
         new Selector.setter(setter.name, setter.library),
-        <ir.Primitive>[value]);
+        <ir.Primitive>[value],
+        sourceInformation);
     return value;
   }
 
   /// Create an invocation of the index [method] on the super class with
   /// the provided [index].
   ir.Primitive buildSuperIndex(MethodElement method,
-                               ir.Primitive index) {
+                               ir.Primitive index,
+                               {SourceInformation sourceInformation}) {
     return _buildInvokeSuper(
-        method, new Selector.index(), <ir.Primitive>[index]);
+        method, new Selector.index(), <ir.Primitive>[index],
+        sourceInformation);
   }
 
   /// Create an invocation of the index set [method] on the super class with
   /// the provided [index] and [value].
   ir.Primitive buildSuperIndexSet(MethodElement method,
                                   ir.Primitive index,
-                                  ir.Primitive value) {
+                                  ir.Primitive value,
+                                  {SourceInformation sourceInformation}) {
     _buildInvokeSuper(method, new Selector.indexSet(),
-        <ir.Primitive>[index, value]);
+        <ir.Primitive>[index, value], sourceInformation);
     return value;
   }
 
@@ -859,8 +873,11 @@
   ir.Primitive buildDynamicInvocation(ir.Primitive receiver,
                                       Selector selector,
                                       TypeMask mask,
-                                      List<ir.Primitive> arguments) {
-    return _buildInvokeDynamic(receiver, selector, mask, arguments);
+                                      List<ir.Primitive> arguments,
+                                      {SourceInformation sourceInformation}) {
+    return _buildInvokeDynamic(
+        receiver, selector, mask, arguments,
+        sourceInformation: sourceInformation);
   }
 
   /// Create a dynamic getter invocation on [receiver] where the getter name is
@@ -925,11 +942,14 @@
   /// Create an invocation of the the [local] variable or parameter where
   /// argument structure is defined by [callStructure] and the argument values
   /// are defined by [arguments].
-  ir.Primitive buildLocalVariableInvocation(LocalVariableElement local,
-                                            CallStructure callStructure,
-                                            List<ir.Primitive> arguments) {
+  ir.Primitive buildLocalVariableInvocation(
+      LocalVariableElement local,
+      CallStructure callStructure,
+      List<ir.Primitive> arguments,
+      {SourceInformation callSourceInformation}) {
     return buildCallInvocation(
-        buildLocalVariableGet(local), callStructure, arguments);
+        buildLocalVariableGet(local), callStructure, arguments,
+        sourceInformation: callSourceInformation);
   }
 
   /// Create an invocation of the local [function] where argument structure is
@@ -938,10 +958,12 @@
   ir.Primitive buildLocalFunctionInvocation(
       LocalFunctionElement function,
       CallStructure callStructure,
-      List<ir.Primitive> arguments) {
+      List<ir.Primitive> arguments,
+      SourceInformation sourceInformation) {
     // TODO(johnniwinther): Maybe this should have its own ir node.
     return buildCallInvocation(
-        buildLocalFunctionGet(function), callStructure, arguments);
+        buildLocalFunctionGet(function), callStructure, arguments,
+        sourceInformation: sourceInformation);
   }
 
   /// Create a static invocation of [function] where argument structure is
@@ -974,7 +996,7 @@
 
   /// Create a getter invocation of the static [getter].
   ir.Primitive buildStaticGetterGet(MethodElement getter,
-                                    {SourceInformation sourceInformation}) {
+                                    SourceInformation sourceInformation) {
     Selector selector = new Selector.getter(getter.name, getter.library);
     return _buildInvokeStatic(
         getter, selector, const <ir.Primitive>[], sourceInformation);
@@ -1958,7 +1980,7 @@
         IrBuilder builder = makeDelimitedBuilder(newReturn.environment);
         ir.Primitive value = builder.environment.discard(1);
         buildFinallyBlock(builder);
-        if (builder.isOpen) builder.buildReturn(value);
+        if (builder.isOpen) builder.buildReturn(value: value);
         newReturn.continuation.body = builder._root;
         exits.add(newReturn.continuation);
       }
@@ -1973,7 +1995,7 @@
 
   /// Create a return statement `return value;` or `return;` if [value] is
   /// null.
-  void buildReturn([ir.Primitive value]) {
+  void buildReturn({ir.Primitive value, SourceInformation sourceInformation}) {
     // Build(Return(e), C) = C'[InvokeContinuation(return, x)]
     //   where (C', x) = Build(e, C)
     //
@@ -1983,7 +2005,8 @@
       value = buildNullConstant();
     }
     if (state.returnCollector == null) {
-      add(new ir.InvokeContinuation(state.returnContinuation, [value]));
+      add(new ir.InvokeContinuation(state.returnContinuation, [value],
+              sourceInformation: sourceInformation));
       _current = null;
     } else {
       // Inside the try block of try/finally, all returns go to a join-point
@@ -2305,12 +2328,15 @@
 
   /// Add [functionElement] to the environment with provided [definition].
   void declareLocalFunction(LocalFunctionElement functionElement,
-                            ClosureClassElement classElement) {
-    ir.Primitive closure = buildFunctionExpression(classElement);
+                            ClosureClassElement classElement,
+                            SourceInformation sourceInformation) {
+    ir.Primitive closure =
+         buildFunctionExpression(classElement, sourceInformation);
     declareLocalVariable(functionElement, initialValue: closure);
   }
 
-  ir.Primitive buildFunctionExpression(ClosureClassElement classElement) {
+  ir.Primitive buildFunctionExpression(ClosureClassElement classElement,
+                                       SourceInformation sourceInformation) {
     List<ir.Primitive> arguments = <ir.Primitive>[];
     for (ClosureFieldElement field in classElement.closureFields) {
       // Captured 'this' is not available as a local in the current environment,
@@ -2320,8 +2346,8 @@
           : environment.lookup(field.local);
       arguments.add(value);
     }
-    return addPrimitive(
-        new ir.CreateInstance(classElement, arguments, const <ir.Primitive>[]));
+    return addPrimitive(new ir.CreateInstance(
+        classElement, arguments, const <ir.Primitive>[], sourceInformation));
   }
 
   /// Create a read access of [local] variable or parameter.
@@ -2430,13 +2456,14 @@
 
   ir.Primitive buildInvokeDirectly(FunctionElement target,
                                    ir.Primitive receiver,
-                                   List<ir.Primitive> arguments) {
+                                   List<ir.Primitive> arguments,
+                                   {SourceInformation sourceInformation}) {
     assert(isOpen);
     Selector selector =
         new Selector.call(target.name, target.library, arguments.length);
     return _continueWithExpression(
         (k) => new ir.InvokeMethodDirectly(
-            receiver, target, selector, arguments, k));
+            receiver, target, selector, arguments, k, sourceInformation));
   }
 
   /// Loads parameters to a constructor body into the environment.
@@ -2459,10 +2486,12 @@
   /// Create a constructor invocation of [element] on [type] where the
   /// constructor name and argument structure are defined by [callStructure] and
   /// the argument values are defined by [arguments].
-  ir.Primitive buildConstructorInvocation(ConstructorElement element,
-                                          CallStructure callStructure,
-                                          DartType type,
-                                          List<ir.Primitive> arguments) {
+  ir.Primitive buildConstructorInvocation(
+      ConstructorElement element,
+      CallStructure callStructure,
+      DartType type,
+      List<ir.Primitive> arguments,
+      SourceInformation sourceInformation) {
     assert(isOpen);
     Selector selector =
         new Selector(SelectorKind.CALL, element.memberName, callStructure);
@@ -2479,8 +2508,8 @@
           ..addAll(typeArguments);
     }
     return _continueWithExpression(
-        (k) => new ir.InvokeConstructor(type, element, selector,
-            arguments, k));
+        (k) => new ir.InvokeConstructor(
+            type, element, selector, arguments, k, sourceInformation));
   }
 
   ir.Primitive buildTypeExpression(DartType type) {
@@ -2508,7 +2537,8 @@
   /// if we are currently building a constructor field initializer, from the
   /// corresponding type argument (field initializers are evaluated before the
   /// receiver object is created).
-  ir.Primitive buildTypeVariableAccess(TypeVariableType variable) {
+  ir.Primitive buildTypeVariableAccess(TypeVariableType variable,
+                                       {SourceInformation sourceInformation}) {
     // If the local exists in the environment, use that.
     // This is put here when we are inside a constructor or field initializer,
     // (or possibly a closure inside one of these).
@@ -2520,7 +2550,8 @@
     // If the type variable is not in a local, read its value from the
     // receiver object.
     ir.Primitive target = buildThis();
-    return addPrimitive(new ir.ReadTypeVariable(variable, target));
+    return addPrimitive(
+        new ir.ReadTypeVariable(variable, target, sourceInformation));
   }
 
   /// Make the given type variable accessible through the local environment
@@ -2532,9 +2563,12 @@
   }
 
   /// Reifies the value of [variable] on the current receiver object.
-  ir.Primitive buildReifyTypeVariable(TypeVariableType variable) {
-    ir.Primitive typeArgument = buildTypeVariableAccess(variable);
-    return addPrimitive(new ir.ReifyRuntimeType(typeArgument));
+  ir.Primitive buildReifyTypeVariable(TypeVariableType variable,
+                                      SourceInformation sourceInformation) {
+    ir.Primitive typeArgument =
+        buildTypeVariableAccess(variable, sourceInformation: sourceInformation);
+    return addPrimitive(
+        new ir.ReifyRuntimeType(typeArgument, sourceInformation));
   }
 
   ir.Primitive buildInvocationMirror(Selector selector,
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
index 8b81f39..2c4fa8e 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
@@ -252,6 +252,45 @@
     return null;
   }
 
+  /// Construct a method that executes the forwarding call to the target
+  /// constructor.  This is only required, if the forwarding factory
+  /// constructor can potentially be the target of a reflective call, because
+  /// the builder shortcuts calls to redirecting factories at the call site
+  /// (see [JsIrBuilderVisitor.handleConstructorInvoke]).
+  visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) {
+    ConstructorElement targetConstructor =
+        elements.getRedirectingTargetConstructor(node).implementation;
+    ConstructorElement redirectingConstructor =
+        irBuilder.state.currentElement.implementation;
+    List<ir.Primitive> arguments = <ir.Primitive>[];
+    FunctionSignature redirectingSignature =
+        redirectingConstructor.functionSignature;
+    List<String> namedParameters = <String>[];
+    redirectingSignature.forEachParameter((ParameterElement parameter) {
+      arguments.add(irBuilder.environment.lookup(parameter));
+      if (parameter.isNamed) {
+        namedParameters.add(parameter.name);
+      }
+    });
+    ClassElement cls = redirectingConstructor.enclosingClass;
+    InterfaceType targetType =
+          redirectingConstructor.computeEffectiveTargetType(cls.thisType);
+    CallStructure callStructure = new CallStructure(
+        redirectingSignature.parameterCount,
+        namedParameters);
+    arguments = normalizeStaticArguments(callStructure, targetConstructor,
+        arguments);
+    ir.Primitive instance = irBuilder.buildConstructorInvocation(
+        targetConstructor,
+        callStructure,
+        targetType,
+        arguments,
+        sourceInformationBuilder.buildNew(node));
+    irBuilder.buildReturn(
+        value: instance,
+        sourceInformation: sourceInformationBuilder.buildReturn(node));
+  }
+
   visitFor(ast.For node) {
     List<LocalElement> loopVariables = <LocalElement>[];
     if (node.initializer is ast.VariableDefinitions) {
@@ -363,7 +402,9 @@
   ir.Primitive visitReturn(ast.Return node) {
     assert(irBuilder.isOpen);
     assert(invariant(node, node.beginToken.value != 'native'));
-    irBuilder.buildReturn(build(node.expression));
+    irBuilder.buildReturn(
+        value: build(node.expression),
+        sourceInformation: sourceInformationBuilder.buildReturn(node));
     return null;
   }
 
@@ -497,9 +538,11 @@
     return irBuilder.state.constants.getConstantValueForVariable(element);
   }
 
-  ir.Primitive buildConstantExpression(ConstantExpression expression) {
+  ir.Primitive buildConstantExpression(ConstantExpression expression,
+                                       SourceInformation sourceInformation) {
     return irBuilder.buildConstant(
-        irBuilder.state.constants.getConstantValue(expression));
+        irBuilder.state.constants.getConstantValue(expression),
+        sourceInformation: sourceInformation);
   }
 
   ir.Primitive visitLiteralList(ast.LiteralList node) {
@@ -563,7 +606,7 @@
     } else {
       // The call to assert and its argument expression must be ignored
       // in production mode.
-      // Assertions can only occur in expression statements, so no value needs
+      // Assertions can onl)y occur in expression statements, so no value needs
       // to be returned.
       return null;
     }
@@ -577,13 +620,15 @@
   @override
   ir.Primitive visitExpressionInvoke(ast.Send node,
                                      ast.Node expression,
-                                     ast.NodeList arguments,
+                                     ast.NodeList argumentsNode,
                                      Selector selector, _) {
     ir.Primitive receiver = visit(expression);
     List<ir.Primitive> arguments = node.arguments.mapToList(visit);
     arguments = normalizeDynamicArguments(selector.callStructure, arguments);
     return irBuilder.buildCallInvocation(
-        receiver, selector.callStructure, arguments);
+        receiver, selector.callStructure, arguments,
+        sourceInformation:
+            sourceInformationBuilder.buildCall(node, argumentsNode));
   }
 
   /// Returns `true` if [node] is a super call.
@@ -596,7 +641,8 @@
   ir.Primitive handleConstantGet(
       ast.Node node,
       ConstantExpression constant, _) {
-    return buildConstantExpression(constant);
+    return buildConstantExpression(constant,
+        sourceInformationBuilder.buildGet(node));
   }
 
   /// If [node] is null, returns this.
@@ -635,7 +681,8 @@
       ast.Send node,
       ConstantExpression constant,
       _) {
-    return buildConstantExpression(constant);
+    return buildConstantExpression(constant,
+        sourceInformationBuilder.buildGet(node));
   }
 
   @override
@@ -644,7 +691,8 @@
       LocalVariableElement element,
       _) {
     return element.isConst
-        ? irBuilder.buildConstant(getConstantForVariable(element))
+        ? irBuilder.buildConstant(getConstantForVariable(element),
+            sourceInformation: sourceInformationBuilder.buildGet(node))
         : irBuilder.buildLocalVariableGet(element);
   }
 
@@ -681,7 +729,8 @@
       ast.Send node,
       FunctionElement getter,
       _) {
-    return irBuilder.buildStaticGetterGet(getter);
+    return irBuilder.buildStaticGetterGet(
+        getter, sourceInformationBuilder.buildGet(node));
   }
 
   @override
@@ -697,7 +746,8 @@
       ast.Send node,
       FunctionElement getter,
       _) {
-    return irBuilder.buildSuperGetterGet(getter);
+    return irBuilder.buildSuperGetterGet(
+        getter, sourceInformationBuilder.buildGet(node));
   }
 
   @override
@@ -727,14 +777,17 @@
     return irBuilder.buildThis();
   }
 
-  ir.Primitive translateTypeVariableTypeLiteral(TypeVariableElement element) {
-    return irBuilder.buildReifyTypeVariable(element.type);
+  ir.Primitive translateTypeVariableTypeLiteral(
+      TypeVariableElement element,
+      SourceInformation sourceInformation) {
+    return irBuilder.buildReifyTypeVariable(element.type, sourceInformation);
   }
 
   @override
   ir.Primitive visitTypeVariableTypeLiteralGet(ast.Send node,
                                                TypeVariableElement element, _) {
-    return translateTypeVariableTypeLiteral(element);
+    return translateTypeVariableTypeLiteral(element,
+        sourceInformationBuilder.buildGet(node));
   }
 
   ir.Primitive translateLogicalOperator(ast.Expression left,
@@ -806,7 +859,9 @@
     List<ir.Primitive> arguments = <ir.Primitive>[visit(right)];
     arguments = normalizeDynamicArguments(selector.callStructure, arguments);
     return irBuilder.buildDynamicInvocation(
-        receiver, selector, elements.getTypeMask(node), arguments);
+        receiver, selector, elements.getTypeMask(node), arguments,
+        sourceInformation:
+            sourceInformationBuilder.buildCall(node, node.selector));
   }
 
   @override
@@ -943,10 +998,12 @@
 
   ir.Primitive translateCallInvoke(ir.Primitive target,
                                    ast.NodeList arguments,
-                                   CallStructure callStructure) {
+                                   CallStructure callStructure,
+                                   SourceInformation sourceInformation) {
 
     return irBuilder.buildCallInvocation(target, callStructure,
-        translateDynamicArguments(arguments, callStructure));
+        translateDynamicArguments(arguments, callStructure),
+        sourceInformation: sourceInformation);
   }
 
   @override
@@ -956,8 +1013,10 @@
       ast.NodeList arguments,
       CallStructure callStructure,
       _) {
-    ir.Primitive target = buildConstantExpression(constant);
-    return translateCallInvoke(target, arguments, callStructure);
+    ir.Primitive target = buildConstantExpression(constant,
+        sourceInformationBuilder.buildGet(node));
+    return translateCallInvoke(target, arguments, callStructure,
+        sourceInformationBuilder.buildCall(node, arguments));
   }
 
   @override
@@ -969,7 +1028,9 @@
       _) {
     return irBuilder.buildDynamicInvocation(
         translateReceiver(receiver), selector, elements.getTypeMask(node),
-        translateDynamicArguments(arguments, selector.callStructure));
+        translateDynamicArguments(arguments, selector.callStructure),
+        sourceInformation:
+            sourceInformationBuilder.buildCall(node, node.selector));
   }
 
   @override
@@ -994,7 +1055,9 @@
       CallStructure callStructure,
       _) {
     return irBuilder.buildLocalVariableInvocation(element, callStructure,
-        translateDynamicArguments(arguments, callStructure));
+        translateDynamicArguments(arguments, callStructure),
+        callSourceInformation:
+            sourceInformationBuilder.buildCall(node, arguments));
   }
 
   @override
@@ -1005,7 +1068,8 @@
       CallStructure callStructure,
       _) {
     return irBuilder.buildLocalFunctionInvocation(function, callStructure,
-        translateDynamicArguments(arguments, callStructure));
+        translateDynamicArguments(arguments, callStructure),
+        sourceInformationBuilder.buildCall(node, arguments));
   }
 
   @override
@@ -1024,7 +1088,9 @@
     ir.Primitive target = buildStaticFieldGet(field, src);
     return irBuilder.buildCallInvocation(target,
         callStructure,
-        translateDynamicArguments(arguments, callStructure));
+        translateDynamicArguments(arguments, callStructure),
+        sourceInformation:
+            sourceInformationBuilder.buildCall(node, arguments));
   }
 
   @override
@@ -1056,10 +1122,13 @@
     if (compiler.backend.isForeign(getter)) {
       return giveup(node, 'handleStaticGetterInvoke: foreign: $getter');
     }
-    ir.Primitive target = irBuilder.buildStaticGetterGet(getter);
+    ir.Primitive target = irBuilder.buildStaticGetterGet(
+        getter, sourceInformationBuilder.buildGet(node));
     return irBuilder.buildCallInvocation(target,
         callStructure,
-        translateDynamicArguments(arguments, callStructure));
+        translateDynamicArguments(arguments, callStructure),
+        sourceInformation:
+            sourceInformationBuilder.buildCall(node, arguments));
   }
 
   @override
@@ -1072,7 +1141,9 @@
     ir.Primitive target = irBuilder.buildSuperFieldGet(field);
     return irBuilder.buildCallInvocation(target,
         callStructure,
-        translateDynamicArguments(arguments, callStructure));
+        translateDynamicArguments(arguments, callStructure),
+        sourceInformation:
+            sourceInformationBuilder.buildCall(node, arguments));
   }
 
   @override
@@ -1082,10 +1153,13 @@
       ast.NodeList arguments,
       CallStructure callStructure,
       _) {
-    ir.Primitive target = irBuilder.buildSuperGetterGet(getter);
+    ir.Primitive target = irBuilder.buildSuperGetterGet(
+        getter, sourceInformationBuilder.buildGet(node));
     return irBuilder.buildCallInvocation(target,
         callStructure,
-        translateDynamicArguments(arguments, callStructure));
+        translateDynamicArguments(arguments, callStructure),
+        sourceInformation:
+            sourceInformationBuilder.buildCall(node, arguments));
   }
 
   @override
@@ -1096,7 +1170,9 @@
       CallStructure callStructure,
       _) {
     return irBuilder.buildSuperMethodInvocation(method, callStructure,
-        translateDynamicArguments(arguments, callStructure));
+        translateDynamicArguments(arguments, callStructure),
+        sourceInformation:
+            sourceInformationBuilder.buildCall(node, node.selector));
   }
 
   @override
@@ -1129,7 +1205,11 @@
       ast.NodeList arguments,
       CallStructure callStructure,
       _) {
-    return translateCallInvoke(irBuilder.buildThis(), arguments, callStructure);
+    return translateCallInvoke(
+        irBuilder.buildThis(),
+        arguments,
+        callStructure,
+        sourceInformationBuilder.buildCall(node, arguments));
   }
 
   @override
@@ -1140,9 +1220,11 @@
       CallStructure callStructure,
       _) {
     return translateCallInvoke(
-        translateTypeVariableTypeLiteral(element),
+        translateTypeVariableTypeLiteral(
+            element, sourceInformationBuilder.buildGet(node)),
         arguments,
-        callStructure);
+        callStructure,
+        sourceInformationBuilder.buildCall(node, arguments));
   }
 
   @override
@@ -1291,7 +1373,10 @@
       CompoundRhs rhs,
       arg) {
     return translateCompounds(
-        getValue: () => buildConstantExpression(constant),
+        getValue: () {
+          return buildConstantExpression(constant,
+            sourceInformationBuilder.buildGet(node));
+        },
         rhs: rhs,
         setValue: (value) {}, // The binary operator will throw before this.
         operatorTypeMask: elements.getOperatorTypeMaskInComplexSendSet(node));
@@ -1383,7 +1468,8 @@
               SourceInformation src = sourceInformationBuilder.buildGet(node);
               return irBuilder.buildStaticFieldGet(getter, src);
             case CompoundGetter.GETTER:
-              return irBuilder.buildStaticGetterGet(getter);
+              return irBuilder.buildStaticGetterGet(
+                  getter, sourceInformationBuilder.buildGet(node));
             case CompoundGetter.METHOD:
               return irBuilder.buildStaticFunctionGet(getter);
             case CompoundGetter.UNRESOLVED:
@@ -1437,7 +1523,8 @@
             case CompoundGetter.FIELD:
               return irBuilder.buildSuperFieldGet(getter);
             case CompoundGetter.GETTER:
-              return irBuilder.buildSuperGetterGet(getter);
+              return irBuilder.buildSuperGetterGet(
+                  getter, sourceInformationBuilder.buildGet(node));
             case CompoundGetter.METHOD:
               return irBuilder.buildSuperMethodGet(getter);
             case CompoundGetter.UNRESOLVED:
@@ -1469,7 +1556,11 @@
       CompoundRhs rhs,
       arg) {
     return translateCompounds(
-        getValue: () => irBuilder.buildReifyTypeVariable(typeVariable.type),
+        getValue: () {
+          return irBuilder.buildReifyTypeVariable(
+            typeVariable.type,
+            sourceInformationBuilder.buildGet(node));
+        },
         rhs: rhs,
         setValue: (value) {}, // The binary operator will throw before this.
         operatorTypeMask: elements.getOperatorTypeMaskInComplexSendSet(node));
@@ -1585,7 +1676,9 @@
 
   ir.Primitive translateConstant(ast.Node node) {
     assert(irBuilder.isOpen);
-    return irBuilder.buildConstant(getConstantForNode(node));
+    return irBuilder.buildConstant(
+        getConstantForNode(node),
+        sourceInformation: sourceInformationBuilder.buildGet(node));
   }
 
   ir.Primitive visitThrow(ast.Throw node) {
@@ -2219,13 +2312,15 @@
   }
 
   ir.Primitive visitFunctionExpression(ast.FunctionExpression node) {
-    return irBuilder.buildFunctionExpression(makeSubFunction(node));
+    return irBuilder.buildFunctionExpression(makeSubFunction(node),
+        sourceInformationBuilder.buildCreate(node));
   }
 
   visitFunctionDeclaration(ast.FunctionDeclaration node) {
     LocalFunctionElement element = elements[node.function];
     Object inner = makeSubFunction(node.function);
-    irBuilder.declareLocalFunction(element, inner);
+    irBuilder.declareLocalFunction(element, inner,
+        sourceInformationBuilder.buildCreate(node.function));
   }
 
   Map mapValues(Map map, dynamic fn(dynamic)) {
@@ -2340,7 +2435,12 @@
     return withBuilder(builder, () {
       irBuilder.buildFunctionHeader(<Local>[]);
       ir.Primitive initialValue = visit(element.initializer);
-      irBuilder.buildReturn(initialValue);
+      ast.VariableDefinitions node = element.node;
+      ast.SendSet sendSet = node.definitions.nodes.head;
+      irBuilder.buildReturn(
+          value: initialValue,
+          sourceInformation:
+              sourceInformationBuilder.buildReturn(sendSet.assignmentOperator));
       return irBuilder.makeFunctionDefinition();
     });
   }
@@ -2465,10 +2565,16 @@
           // Native fields are initialized elsewhere.
         }
       }, includeSuperAndInjectedMembers: true);
+
       ir.Primitive instance = new ir.CreateInstance(
           classElement,
           instanceArguments,
-          typeInformation);
+          typeInformation,
+          constructor.hasNode
+              ? sourceInformationBuilder.buildCreate(constructor.node)
+              // TODO(johnniwinther): Provide source information for creation
+              // through synthetic constructors.
+              : null);
       irBuilder.add(new ir.LetPrim(instance));
 
       // --- Call constructor bodies ---
@@ -2483,7 +2589,10 @@
       }
 
       // --- step 4: return the created object ----
-      irBuilder.buildReturn(instance);
+      irBuilder.buildReturn(
+          value: instance,
+          sourceInformation:
+            sourceInformationBuilder.buildImplicitReturn(constructor));
 
       return irBuilder.makeFunctionDefinition();
     });
@@ -2938,7 +3047,8 @@
         target,
         callStructure,
         constructor.computeEffectiveTargetType(type),
-        arguments);
+        arguments,
+        sourceInformationBuilder.buildNew(node));
   }
 
   @override
@@ -2991,7 +3101,7 @@
   ir.Primitive buildStaticFieldGet(FieldElement field, SourceInformation src) {
     ConstantValue constant = getConstantForVariable(field);
     if (constant != null && !field.isAssignable) {
-      return irBuilder.buildConstant(constant);
+      return irBuilder.buildConstant(constant, sourceInformation: src);
     } else if (backend.constants.lazyStatics.contains(field)) {
       return irBuilder.buildStaticFieldLazyGet(field, src);
     } else {
@@ -3186,16 +3296,16 @@
         if (!compiler.hasIsolateSupport) {
           // If the isolate library is not used, we just generate code
           // to fetch the current isolate.
-          continue GET_CURRENT_ISOLATE;
+          continue GET_STATIC_STATE;
         }
         return buildIsolateHelperInvocation('_currentIsolate',
             CallStructure.NO_ARGS);
 
-      GET_CURRENT_ISOLATE: case 'JS_CURRENT_ISOLATE':
+      GET_STATIC_STATE: case 'JS_GET_STATIC_STATE':
         validateArgumentCount(exactly: 0);
 
         return irBuilder.buildForeignCode(
-            js.js.parseForeignJS(backend.namer.currentIsolate),
+            js.js.parseForeignJS(backend.namer.staticStateHolder),
             const <ir.Primitive>[],
             NativeBehavior.PURE);
 
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
index 29d324e..8c5bf34 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
@@ -128,6 +128,17 @@
     }
     if (next != null) next.previous = previous;
   }
+
+  /// Changes the definition referenced by this object and updates
+  /// the reference chains accordingly.
+  void changeTo(Definition<T> newDefinition) {
+    unlink();
+    previous = null;
+    definition = newDefinition;
+    next = definition.firstRef;
+    if (next != null) next.previous = this;
+    definition.firstRef = this;
+  }
 }
 
 /// Evaluates a primitive and binds it to variable: `let val x = V in E`.
@@ -344,12 +355,14 @@
   final Selector selector;
   final List<Reference<Primitive>> arguments;
   final Reference<Continuation> continuation;
+  final SourceInformation sourceInformation;
 
   InvokeMethodDirectly(Primitive receiver,
                        this.target,
                        this.selector,
                        List<Primitive> arguments,
-                       Continuation continuation)
+                       Continuation continuation,
+                       this.sourceInformation)
       : this.receiver = new Reference<Primitive>(receiver),
         this.arguments = _referenceList(arguments),
         this.continuation = new Reference<Continuation>(continuation);
@@ -378,12 +391,14 @@
   final List<Reference<Primitive>> arguments;
   final Reference<Continuation> continuation;
   final Selector selector;
+  final SourceInformation sourceInformation;
 
   InvokeConstructor(this.type,
                     this.target,
                     this.selector,
                     List<Primitive> args,
-                    Continuation cont)
+                    Continuation cont,
+                    this.sourceInformation)
       : arguments = _referenceList(args),
         continuation = new Reference<Continuation>(cont);
 
@@ -563,6 +578,7 @@
 class InvokeContinuation extends Expression {
   Reference<Continuation> continuation;
   List<Reference<Primitive>> arguments;
+  SourceInformation sourceInformation;
 
   // An invocation of a continuation is recursive if it occurs in the body of
   // the continuation itself.
@@ -574,7 +590,8 @@
 
   InvokeContinuation(Continuation cont, List<Primitive> args,
                      {this.isRecursive: false,
-                      this.isEscapingTry: false})
+                      this.isEscapingTry: false,
+                      this.sourceInformation})
       : continuation = new Reference<Continuation>(cont),
         arguments = _referenceList(args) {
     assert(cont.parameters == null || cont.parameters.length == args.length);
@@ -586,10 +603,11 @@
   ///
   /// Used as a placeholder for a jump whose target is not yet created
   /// (e.g., in the translation of break and continue).
-  InvokeContinuation.uninitialized({this.isRecursive: false, 
+  InvokeContinuation.uninitialized({this.isRecursive: false,
                                     this.isEscapingTry: false})
       : continuation = null,
-        arguments = null;
+        arguments = null,
+        sourceInformation = null;
 
   accept(Visitor visitor) => visitor.visitInvokeContinuation(this);
 }
@@ -661,6 +679,62 @@
   bool get isSafeForReordering => objectIsNotNull && field.isFinal;
 }
 
+/// Get the length of a native list.
+class GetLength extends Primitive {
+  final Reference<Primitive> object;
+
+  /// True if the object is known not to be null.
+  bool objectIsNotNull = false;
+
+  GetLength(Primitive object) : this.object = new Reference<Primitive>(object);
+
+  bool get isSafeForElimination => objectIsNotNull;
+  bool get isSafeForReordering => false;
+
+  accept(Visitor v) => v.visitGetLength(this);
+}
+
+/// Read an entry from a native list.
+///
+/// [object] must be null or a native list, and [index] must be an integer.
+class GetIndex extends Primitive {
+  final Reference<Primitive> object;
+  final Reference<Primitive> index;
+
+  /// True if the object is known not to be null.
+  bool objectIsNotNull = false;
+
+  GetIndex(Primitive object, Primitive index)
+      : this.object = new Reference<Primitive>(object),
+        this.index = new Reference<Primitive>(index);
+
+  bool get isSafeForElimination => objectIsNotNull;
+  bool get isSafeForReordering => false;
+
+  accept(Visitor v) => v.visitGetIndex(this);
+}
+
+/// Set an entry on a native list.
+///
+/// [object] must be null or a native list, and [index] must be an integer.
+///
+/// The primitive itself has no value and may not be referenced.
+class SetIndex extends Primitive {
+  final Reference<Primitive> object;
+  final Reference<Primitive> index;
+  final Reference<Primitive> value;
+
+  SetIndex(Primitive object, Primitive index, Primitive value)
+      : this.object = new Reference<Primitive>(object),
+        this.index = new Reference<Primitive>(index),
+        this.value = new Reference<Primitive>(value);
+
+  bool get isSafeForElimination => false;
+  bool get isSafeForReordering => false;
+
+  accept(Visitor v) => v.visitSetIndex(this);
+}
+
 /// Reads the value of a static field or tears off a static method.
 ///
 /// Note that lazily initialized fields should be read using GetLazyStatic.
@@ -672,7 +746,7 @@
   GetStatic(this.element, [this.sourceInformation]);
 
   accept(Visitor visitor) => visitor.visitGetStatic(this);
-  
+
   bool get isSafeForElimination {
     return true;
   }
@@ -742,8 +816,11 @@
   /// is not needed at runtime.
   final List<Reference<Primitive>> typeInformation;
 
+  final SourceInformation sourceInformation;
+
   CreateInstance(this.classElement, List<Primitive> arguments,
-      List<Primitive> typeInformation)
+      List<Primitive> typeInformation,
+      this.sourceInformation)
       : this.arguments = _referenceList(arguments),
         this.typeInformation = _referenceList(typeInformation);
 
@@ -800,8 +877,9 @@
 
 class Constant extends Primitive {
   final values.ConstantValue value;
+  final SourceInformation sourceInformation;
 
-  Constant(this.value);
+  Constant(this.value, {this.sourceInformation});
 
   accept(Visitor visitor) => visitor.visitConstant(this);
 
@@ -903,7 +981,7 @@
 
   Continuation(this.parameters, {this.isRecursive: false});
 
-  Continuation.retrn() 
+  Continuation.retrn()
     : parameters = <Parameter>[new Parameter(null)],
       isRecursive = false;
 
@@ -945,7 +1023,10 @@
   /// Reference to the internal representation of a type (as produced, for
   /// example, by [ReadTypeVariable]).
   final Reference<Primitive> value;
-  ReifyRuntimeType(Primitive value)
+
+  final SourceInformation sourceInformation;
+
+  ReifyRuntimeType(Primitive value, this.sourceInformation)
     : this.value = new Reference<Primitive>(value);
 
   @override
@@ -963,8 +1044,9 @@
 class ReadTypeVariable extends Primitive {
   final TypeVariableType variable;
   final Reference<Primitive> target;
+  final SourceInformation sourceInformation;
 
-  ReadTypeVariable(this.variable, Primitive target)
+  ReadTypeVariable(this.variable, Primitive target, this.sourceInformation)
       : this.target = new Reference<Primitive>(target);
 
   @override
@@ -1052,6 +1134,9 @@
   T visitCreateInvocationMirror(CreateInvocationMirror node);
   T visitTypeTest(TypeTest node);
   T visitApplyBuiltinOperator(ApplyBuiltinOperator node);
+  T visitGetLength(GetLength node);
+  T visitGetIndex(GetIndex node);
+  T visitSetIndex(SetIndex node);
 
   // Conditions.
   T visitIsTrue(IsTrue node);
@@ -1342,6 +1427,27 @@
   visitUnreachable(Unreachable node) {
     processUnreachable(node);
   }
+
+  processGetLength(GetLength node) {}
+  visitGetLength(GetLength node) {
+    processGetLength(node);
+    processReference(node.object);
+  }
+
+  processGetIndex(GetIndex node) {}
+  visitGetIndex(GetIndex node) {
+    processGetIndex(node);
+    processReference(node.object);
+    processReference(node.index);
+  }
+
+  processSetIndex(SetIndex node) {}
+  visitSetIndex(SetIndex node) {
+    processSetIndex(node);
+    processReference(node.object);
+    processReference(node.index);
+    processReference(node.value);
+  }
 }
 
 /// Visit a just-deleted subterm and unlink all [Reference]s in it.
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
index 528edc2..e200071 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
@@ -340,6 +340,27 @@
         : ' ${access(node.continuation)}';
     return '(JS ${node.type} ${node.codeTemplate} ($arguments)$continuation)';
   }
+
+  @override
+  String visitGetLength(GetLength node) {
+    String object = access(node.object);
+    return '(GetLength $object)';
+  }
+
+  @override
+  String visitGetIndex(GetIndex node) {
+    String object = access(node.object);
+    String index = access(node.index);
+    return '(GetIndex $object $index)';
+  }
+
+  @override
+  String visitSetIndex(SetIndex node) {
+    String object = access(node.object);
+    String index = access(node.index);
+    String value = access(node.value);
+    return '(SetIndex $object $index $value)';
+  }
 }
 
 class ConstantStringifier extends ConstantValueVisitor<String, Null> {
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
index 1c5adcf..0064b6b 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
@@ -110,10 +110,8 @@
   visitLetCont(cps_ir.LetCont node) {
     if (IR_TRACE_LET_CONT) {
       String dummy = names.name(node);
-      for (cps_ir.Continuation continuation in node.continuations) {
-        String id = names.name(continuation);
-        printStmt(dummy, "LetCont $id = <$id>");
-      }
+      String ids = node.continuations.map(names.name).join(', ');
+      printStmt(dummy, "LetCont $ids");
     }
     visit(node.body);
   }
@@ -192,20 +190,18 @@
   }
 
   visitLiteralList(cps_ir.LiteralList node) {
-    String dummy = names.name(node);
     String values = node.values.map(formatReference).join(', ');
-    printStmt(dummy, "LiteralList ($values)");
+    return "LiteralList ($values)";
   }
 
   visitLiteralMap(cps_ir.LiteralMap node) {
-    String dummy = names.name(node);
     List<String> entries = new List<String>();
     for (cps_ir.LiteralMapEntry entry in node.entries) {
       String key = formatReference(entry.key);
       String value = formatReference(entry.value);
       entries.add("$key: $value");
     }
-    printStmt(dummy, "LiteralMap (${entries.join(', ')})");
+    return "LiteralMap (${entries.join(', ')})";
   }
 
   visitTypeCast(cps_ir.TypeCast node) {
@@ -374,6 +370,24 @@
     printStmt(id, "ForeignCode ${node.type} ${node.codeTemplate.source} "
         "$arguments $continuation");
   }
+
+  visitGetLength(cps_ir.GetLength node) {
+    String object = formatReference(node.object);
+    return 'GetLength $object';
+  }
+
+  visitGetIndex(cps_ir.GetIndex node) {
+    String object = formatReference(node.object);
+    String index = formatReference(node.index);
+    return 'GetIndex $object $index';
+  }
+
+  visitSetIndex(cps_ir.SetIndex node) {
+    String object = formatReference(node.object);
+    String index = formatReference(node.index);
+    String value = formatReference(node.value);
+    return 'SetIndex $object $index $value';
+  }
 }
 
 /**
@@ -633,6 +647,18 @@
     unexpectedNode(node);
   }
 
+  visitGetLength(cps_ir.GetLength node) {
+    unexpectedNode(node);
+  }
+
+  visitGetIndex(cps_ir.GetIndex node) {
+    unexpectedNode(node);
+  }
+
+  visitSetIndex(cps_ir.SetIndex node) {
+    unexpectedNode(node);
+  }
+
   @override
   visitForeignCode(cps_ir.ForeignCode node) {
     if (node.continuation != null) {
diff --git a/pkg/compiler/lib/src/cps_ir/optimizers.dart b/pkg/compiler/lib/src/cps_ir/optimizers.dart
index c80dfb0..3b48349 100644
--- a/pkg/compiler/lib/src/cps_ir/optimizers.dart
+++ b/pkg/compiler/lib/src/cps_ir/optimizers.dart
@@ -5,9 +5,11 @@
 library dart2js.cps_ir.optimizers;
 
 import 'cps_ir_nodes.dart';
+import '../constants/values.dart';
 
 export 'type_propagation.dart' show TypePropagator;
 export 'redundant_phi.dart' show RedundantPhiEliminator;
+export 'redundant_join.dart' show RedundantJoinEliminator;
 export 'shrinking_reductions.dart' show ShrinkingReducer, ParentVisitor;
 
 /// An optimization pass over the CPS IR.
@@ -17,3 +19,15 @@
 
   String get passName;
 }
+
+// Shared code between optimizations
+
+/// Returns true if [value] is false, null, 0, -0, NaN, or the empty string.
+bool isFalsyConstant(ConstantValue value) {
+  return value.isFalse ||
+      value.isNull  ||
+      value.isZero ||
+      value.isMinusZero ||
+      value.isNaN ||
+      value is StringConstantValue && value.primitiveValue.isEmpty;
+}
diff --git a/pkg/compiler/lib/src/cps_ir/redundant_join.dart b/pkg/compiler/lib/src/cps_ir/redundant_join.dart
new file mode 100644
index 0000000..92bd51b
--- /dev/null
+++ b/pkg/compiler/lib/src/cps_ir/redundant_join.dart
@@ -0,0 +1,276 @@
+// 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.
+
+library dart2js.cps_ir.redundant_join_elimination;
+
+import 'cps_ir_nodes.dart';
+import 'optimizers.dart';
+
+/// Eliminates redundant join points.
+/// 
+/// A redundant join point is a continuation that immediately branches
+/// based on one of its parameters, and that parameter is a constant value
+/// at every invocation. Each invocation is redirected to jump directly
+/// to the branch target.
+/// 
+/// Internally in this pass, parameters are treated as names with lexical
+/// scoping, and a given parameter "name" may be declared by more than
+/// one continuation. The reference chains for parameters are therefore 
+/// meaningless during this pass, until repaired by [AlphaRenamer] at
+/// the end.
+class RedundantJoinEliminator extends RecursiveVisitor implements Pass {
+  String get passName => 'Redundant join elimination';
+
+  final Set<Branch> workSet = new Set<Branch>();
+
+  void rewrite(FunctionDefinition node) {
+    visit(node);
+
+    while (workSet.isNotEmpty) {
+      Branch branch = workSet.first;
+      workSet.remove(branch);
+      rewriteBranch(branch);
+    }
+
+    new AlphaRenamer().visit(node);
+  }
+
+  void processBranch(Branch node) {
+    workSet.add(node);
+  }
+
+  /// Returns the body of [node], ignoring all LetCont nodes.
+  Expression getEffectiveBody(InteriorNode node) {
+    while (true) {
+      Expression body = node.body;
+      if (body is LetCont) {
+        node = body;
+      } else {
+        return body;
+      }
+    }
+  }
+
+  /// Returns the parent of [node], ignoring all LetCont nodes.
+  InteriorNode getEffectiveParent(Expression node) {
+    while (true) {
+      Node parent = node.parent;
+      if (parent is LetCont) {
+        node = parent;
+      } else {
+        return parent;
+      }
+    }
+  }
+
+  /// Removes [movedNode] from its current position and inserts it
+  /// before [target].
+  void moveToBefore(Expression target, LetCont movedNode) {
+    if (movedNode.parent != null) {
+      movedNode.parent.body = movedNode.body;
+      movedNode.body.parent = movedNode.parent;
+    }
+    InteriorNode parent = target.parent;
+    parent.body = movedNode;
+    movedNode.body = target;
+    target.parent = movedNode;
+    movedNode.parent = parent;
+  }
+
+  void rewriteBranch(Branch branch) {
+    InteriorNode parent = getEffectiveParent(branch);
+    if (parent is! Continuation) return;
+    Continuation branchCont = parent;
+
+    // Other optimizations take care of single-use continuations.
+    if (!branchCont.hasMultipleUses) return;
+
+    // It might be beneficial to rewrite calls to recursive continuations,
+    // but we currently do not support this.
+    if (branchCont.isRecursive) return;
+
+    // Check that the branching condition is a parameter on the
+    // enclosing continuation.
+    // Note: Do not use the parent pointer for this check, because parameters
+    // are temporarily shared between different continuations during this pass.
+    IsTrue isTrue = branch.condition;
+    Primitive condition = isTrue.value.definition;
+    int parameterIndex = branchCont.parameters.indexOf(condition);
+    if (parameterIndex == -1) return;
+
+    // Check that all callers hit a fixed branch, and count the number
+    // of times each branch is hit.
+    // We know all callers are InvokeContinuations because they are the only
+    // valid uses of a multi-use continuation.
+    int trueHits = 0, falseHits = 0;
+    InvokeContinuation trueCall, falseCall;
+    for (Reference ref = branchCont.firstRef; ref != null; ref = ref.next) {
+      InvokeContinuation invoke = ref.parent;
+      Primitive argument = invoke.arguments[parameterIndex].definition;
+      if (argument is! Constant) return; // Branching condition is unknown.
+      Constant constant = argument;
+      if (isFalsyConstant(constant.value)) {
+        ++falseHits;
+        falseCall = invoke;
+      } else {
+        ++trueHits;
+        trueCall = invoke;
+      }
+    }
+
+    // The optimization is now known to be safe, but it only pays off if
+    // one of the callers can inline its target, since otherwise we end up
+    // replacing a boolean variable with a labeled break.
+    // TODO(asgerf): The labeled break might be better? Evaluate.
+    if (!(trueHits == 1 && !trueCall.isEscapingTry ||
+          falseHits == 1 && !falseCall.isEscapingTry)) {
+      return;
+    }
+
+    // Lift any continuations bound inside branchCont so they are in scope at 
+    // the call sites. When lifting, the parameters of branchCont fall out of
+    // scope, so they are added as parameters on each lifted continuation.
+    // Schematically:
+    // 
+    //   (LetCont (branchCont (x1, x2, x3) =
+    //        (LetCont (innerCont (y) = ...) in
+    //        [... innerCont(y') ...]))
+    //
+    //     =>
+    //
+    //   (LetCont (innerCont (y, x1, x2, x3) = ...) in
+    //   (LetCont (branchCont (x1, x2, x3) =
+    //        [... innerCont(y', x1, x2, x3) ...])
+    // 
+    // Parameter objects become shared between branchCont and the lifted 
+    // continuations. [AlphaRenamer] will clean up at the end of this pass.
+    LetCont outerLetCont = branchCont.parent;
+    while (branchCont.body is LetCont) {
+      LetCont innerLetCont = branchCont.body;
+      for (Continuation innerCont in innerLetCont.continuations) {
+        innerCont.parameters.addAll(branchCont.parameters);
+        for (Reference ref = innerCont.firstRef; ref != null; ref = ref.next) {
+          Expression use = ref.parent;
+          if (use is InvokeContinuation) {
+            for (Parameter param in branchCont.parameters) {
+              use.arguments.add(new Reference<Primitive>(param));
+            }
+          } else {
+            // The branch will be eliminated, so don't worry about updating it.
+            assert(use == branch);
+          }
+        }
+      }
+      moveToBefore(outerLetCont, innerLetCont);
+    }
+
+    assert(branchCont.body == branch);
+
+    Continuation trueCont = branch.trueContinuation.definition;
+    Continuation falseCont = branch.falseContinuation.definition;
+
+    assert(branchCont != trueCont);
+    assert(branchCont != falseCont);
+
+    // Rewrite every invocation of branchCont to call either the true or false
+    // branch directly. Since these were lifted out above branchCont, they are
+    // now in scope.
+    // Since trueCont and falseCont were branch targets, they originally
+    // had no parameters, and so after the lifting, their parameters are
+    // exactly the same as those accepted by branchCont.
+    while (branchCont.firstRef != null) {
+      Reference reference = branchCont.firstRef;
+      InvokeContinuation invoke = branchCont.firstRef.parent;
+      Constant condition = invoke.arguments[parameterIndex].definition;
+      if (isFalsyConstant(condition.value)) {
+        invoke.continuation.changeTo(falseCont);
+      } else {
+        invoke.continuation.changeTo(trueCont);
+      }
+      assert(branchCont.firstRef != reference);
+    }
+
+    // Remove the now-unused branchCont continuation.
+    assert(branchCont.hasNoUses);
+    branch.trueContinuation.unlink();
+    branch.falseContinuation.unlink();
+    outerLetCont.continuations.remove(branchCont);
+    if (outerLetCont.continuations.isEmpty) {
+      InteriorNode parent = outerLetCont.parent;
+      parent.body = outerLetCont.body;
+      outerLetCont.body.parent = parent;
+    }
+
+    // We may have created new redundant join points in the two branches.
+    enqueueContinuation(trueCont);
+    enqueueContinuation(falseCont);
+  }
+
+  void enqueueContinuation(Continuation cont) {
+    Expression body = getEffectiveBody(cont);
+    if (body is Branch) {
+      workSet.add(body);
+    }
+  }
+}
+
+/// Ensures parameter objects are not shared between different continuations,
+/// akin to alpha-renaming variables so every variable is named uniquely.
+/// For example:
+/// 
+///   LetCont (k1 x = (return x)) in
+///   LetCont (k2 x = (InvokeContinuation k3 x)) in ...
+///     => 
+///   LetCont (k1 x = (return x)) in
+///   LetCont (k2 x' = (InvokeContinuation k3 x')) in ...
+/// 
+/// After lifting LetConts in the main pass above, parameter objects can have
+/// multiple bindings. Each reference implicitly refers to the binding that
+/// is currently in scope.
+/// 
+/// This returns the IR to its normal form after redundant joins have been
+/// eliminated.
+class AlphaRenamer extends RecursiveVisitor {
+  Map<Parameter, Parameter> renaming = <Parameter, Parameter>{};
+
+  visitContinuation(Continuation cont) {
+    if (cont.isReturnContinuation) return;
+
+    List<Parameter> shadowedKeys = <Parameter>[];
+    List<Parameter> shadowedValues = <Parameter>[];
+
+    // Create new parameters and update the environment.
+    for (int i = 0; i < cont.parameters.length; ++i) {
+      Parameter param = cont.parameters[i];
+      shadowedKeys.add(param);
+      shadowedValues.add(renaming.remove(param));
+      // If the parameter appears to belong to another continuation,
+      // create a new parameter object for this continuation.
+      if (param.parent != cont) {
+        Parameter newParam = new Parameter(param.hint);
+        renaming[param] = newParam;
+        cont.parameters[i] = newParam;
+        newParam.parent = cont;
+      }
+    }
+
+    // Visit the body with the updated environment.
+    visit(cont.body);
+
+    // Restore the original environment.
+    for (int i = 0; i < cont.parameters.length; ++i) {
+      renaming.remove(cont.parameters[i]);
+      if (shadowedValues[i] != null) {
+        renaming[shadowedKeys[i]] = shadowedValues[i];
+      }
+    }
+  }
+
+  processReference(Reference ref) {
+    Parameter target = renaming[ref.definition];
+    if (target != null) {
+      ref.changeTo(target);
+    }
+  }
+}
diff --git a/pkg/compiler/lib/src/cps_ir/redundant_phi.dart b/pkg/compiler/lib/src/cps_ir/redundant_phi.dart
index 1f40c03..e678a96 100644
--- a/pkg/compiler/lib/src/cps_ir/redundant_phi.dart
+++ b/pkg/compiler/lib/src/cps_ir/redundant_phi.dart
@@ -152,7 +152,7 @@
       // invokes, and all such invokes must be within the scope of
       // [uniqueDefinition]. Note that this is linear in the depth of
       // the binding of [uniqueDefinition].
-      assert(letCont != null);
+      letCont = _makeUniqueBinding(cont);
       _moveIntoScopeOf(letCont, uniqueDefinition);
     }
 
@@ -201,3 +201,19 @@
   binding.body = letCont;
   letCont.parent = binding;
 }
+
+/// Ensures [continuation] has its own LetCont binding by creating
+/// a new LetCont below its current binding, if necessary.
+/// 
+/// Returns the LetCont that now binds [continuation].
+LetCont _makeUniqueBinding(Continuation continuation) {
+  LetCont letCont = continuation.parent;
+  if (letCont.continuations.length == 1) return letCont;
+  letCont.continuations.remove(continuation);
+  LetCont newBinding = new LetCont(continuation, letCont.body);
+  newBinding.body.parent = newBinding;
+  newBinding.parent = letCont;
+  letCont.body = newBinding;
+  continuation.parent = newBinding;
+  return newBinding;
+}
diff --git a/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart b/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
index fb62a72..f1970de 100644
--- a/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
+++ b/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
@@ -676,6 +676,21 @@
     }
     node.arguments.forEach((Reference ref) => ref.parent = node);
   }
+
+  processGetLength(GetLength node) {
+    node.object.parent = node;
+  }
+
+  processGetIndex(GetIndex node) {
+    node.object.parent = node;
+    node.index.parent = node;
+  }
+
+  processSetIndex(SetIndex node) {
+    node.object.parent = node;
+    node.index.parent = node;
+    node.value.parent = node;
+  }
 }
 
 class _ReductionKind {
diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
index 091ca53..50b77b1 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -2,7 +2,7 @@
 // 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 'optimizers.dart' show Pass, ParentVisitor;
+import 'optimizers.dart';
 
 import '../constants/constant_system.dart';
 import '../resolution/operators.dart';
@@ -17,6 +17,8 @@
 import '../dart2jslib.dart' show ClassWorld, World;
 import '../universe/universe.dart';
 import '../js_backend/js_backend.dart' show JavaScriptBackend;
+import '../io/source_information.dart' show SourceInformation;
+import 'cps_fragment.dart';
 
 enum AbstractBool {
   True, False, Maybe, Nothing
@@ -25,6 +27,7 @@
 class TypeMaskSystem {
   final TypesTask inferrer;
   final World classWorld;
+  final JavaScriptBackend backend;
 
   TypeMask get dynamicType => inferrer.dynamicType;
   TypeMask get typeType => inferrer.typeType;
@@ -37,13 +40,15 @@
   TypeMask get listType => inferrer.listType;
   TypeMask get mapType => inferrer.mapType;
   TypeMask get nonNullType => inferrer.nonNullType;
+  TypeMask get mutableNativeListType => backend.mutableArrayType;
 
   TypeMask numStringBoolType;
 
   // TODO(karlklose): remove compiler here.
   TypeMaskSystem(dart2js.Compiler compiler)
     : inferrer = compiler.typesTask,
-      classWorld = compiler.world {
+      classWorld = compiler.world,
+      backend = compiler.backend {
     numStringBoolType =
       new TypeMask.unionOf(<TypeMask>[numType, stringType, boolType],
                            classWorld);
@@ -137,6 +142,26 @@
     return areDisjoint(t, doubleType);
   }
 
+  bool isDefinitelyInt(TypeMask t, {bool allowNull: false}) {
+    if (!allowNull && t.isNullable) return false;
+    return t.satisfies(backend.jsIntClass, classWorld);
+  }
+
+  bool isDefinitelyNativeList(TypeMask t, {bool allowNull: false}) {
+    if (!allowNull && t.isNullable) return false;
+    return t.satisfies(backend.jsArrayClass, classWorld);
+  }
+
+  bool isDefinitelyMutableNativeList(TypeMask t, {bool allowNull: false}) {
+    if (!allowNull && t.isNullable) return false;
+    return t.satisfies(backend.jsMutableArrayClass, classWorld);
+  }
+
+  bool isDefinitelyFixedNativeList(TypeMask t, {bool allowNull: false}) {
+    if (!allowNull && t.isNullable) return false;
+    return t.satisfies(backend.jsFixedArrayClass, classWorld);
+  }
+
   bool areDisjoint(TypeMask leftType, TypeMask rightType) {
     TypeMask intersection = leftType.intersection(rightType, classWorld);
     return intersection.isEmpty && !intersection.isNullable;
@@ -265,6 +290,32 @@
       typeSystem.isDefinitelyNotNonIntegerDouble(value.type);
   }
 
+  bool isDefinitelyInt(AbstractValue value,
+                       {bool allowNull: false}) {
+    return value.isNothing ||
+        typeSystem.isDefinitelyInt(value.type, allowNull: allowNull);
+  }
+
+  bool isDefinitelyNativeList(AbstractValue value,
+                              {bool allowNull: false}) {
+    return value.isNothing ||
+        typeSystem.isDefinitelyNativeList(value.type, allowNull: allowNull);
+  }
+
+  bool isDefinitelyMutableNativeList(AbstractValue value,
+                                     {bool allowNull: false}) {
+    return value.isNothing ||
+         typeSystem.isDefinitelyMutableNativeList(value.type,
+                                                  allowNull: allowNull);
+  }
+
+  bool isDefinitelyFixedNativeList(AbstractValue value,
+                                   {bool allowNull: false}) {
+    return value.isNothing ||
+        typeSystem.isDefinitelyFixedNativeList(value.type,
+                                               allowNull: allowNull);
+  }
+
   /// Returns whether the given [value] is an instance of [type].
   ///
   /// Since [value] and [type] are not always known, [AbstractBool.Maybe] is
@@ -357,7 +408,19 @@
       if (result == null) return anything;
       return constant(result);
     }
-    return null; // TODO(asgerf): Look up type?
+    // TODO(asgerf): Handle remaining operators and the UIntXX types.
+    switch (operator.kind) {
+      case BinaryOperatorKind.ADD:
+      case BinaryOperatorKind.SUB:
+      case BinaryOperatorKind.MUL:
+        if (isDefinitelyInt(left) && isDefinitelyInt(right)) {
+          return nonConstant(typeSystem.intType);
+        }
+        return null;
+
+      default:
+        return null; // The caller will use return type from type inference.
+    }
   }
 
   AbstractValue stringConstant(String value) {
@@ -380,22 +443,13 @@
     }
   }
 
-  bool isEmptyString(ConstantValue value) {
-    return value is StringConstantValue && value.primitiveValue.isEmpty;
-  }
-
   /// Returns whether [value] is one of the falsy values: false, 0, -0, NaN,
   /// the empty string, or null.
   AbstractBool boolify(AbstractValue value) {
     if (value.isNothing) return AbstractBool.Nothing;
     if (value.isConstant) {
       ConstantValue constantValue = value.constant;
-      if (constantValue.isFalse ||
-          constantValue.isNull  ||
-          constantValue.isZero ||
-          constantValue.isMinusZero ||
-          constantValue.isNaN ||
-          isEmptyString(constantValue)) {
+      if (isFalsyConstant(constantValue)) {
         return AbstractBool.False;
       } else {
         return AbstractBool.True;
@@ -544,6 +598,30 @@
     reanalyze(replacement);
   }
 
+  /// Inserts [insertedCode] before [node].
+  /// 
+  /// [node] will end up in the hole of [insertedCode], and [insertedCode]
+  /// will become rooted where [node] was.
+  void insertBefore(Expression node, CpsFragment insertedCode) {
+    if (insertedCode.isEmpty) return; // Nothing to do.
+    assert(insertedCode.isOpen);
+    InteriorNode parent = node.parent;
+    InteriorNode context = insertedCode.context;
+
+    parent.body = insertedCode.root;
+    insertedCode.root.parent = parent;
+
+    // We want to recompute the types for [insertedCode] without
+    // traversing the entire subtree of [node]. Temporarily close the
+    // term with a dummy node while recomputing types.
+    context.body = new Unreachable(); 
+    new ParentVisitor().visit(insertedCode.root);
+    reanalyze(insertedCode.root);
+
+    context.body = node;
+    node.parent = context;
+  }
+
   /// Make a constant primitive for [constant] and set its entry in [values].
   Constant makeConstantPrimitive(ConstantValue constant) {
     Constant primitive = new Constant(constant);
@@ -764,6 +842,339 @@
     }
   }
 
+  /// Create a check that throws if [index] is not a valid index on [list].
+  /// 
+  /// This function assumes that [index] is an integer.
+  ///
+  /// Returns a CPS fragment whose context is the branch where no error
+  /// was thrown.
+  CpsFragment makeBoundsCheck(Primitive list,
+                              Primitive index,
+                              SourceInformation sourceInfo) {
+    CpsFragment cps = new CpsFragment(sourceInfo);
+    Continuation fail = cps.letCont();
+    Primitive isTooSmall = cps.applyBuiltin(
+        BuiltinOperator.NumLt,
+        <Primitive>[index, cps.makeZero()]);
+    cps.ifTrue(isTooSmall).invokeContinuation(fail);
+    Primitive isTooLarge = cps.applyBuiltin(
+        BuiltinOperator.NumGe,
+        <Primitive>[index, cps.letPrim(new GetLength(list))]);
+    cps.ifTrue(isTooLarge).invokeContinuation(fail);
+    cps.insideContinuation(fail).invokeStaticThrower(
+        backend.getThrowIndexOutOfBoundsError(),
+        <Primitive>[list, index]);
+    return cps;
+  }
+
+  /// Create a check that throws if the length of [list] is not equal to
+  /// [originalLength].
+  ///
+  /// Returns a CPS fragment whose context is the branch where no error
+  /// was thrown.
+  CpsFragment makeConcurrentModificationCheck(Primitive list,
+                                              Primitive originalLength,
+                                              SourceInformation sourceInfo) {
+    CpsFragment cps = new CpsFragment(sourceInfo);
+    Primitive lengthChanged = cps.applyBuiltin(
+        BuiltinOperator.StrictNeq,
+        <Primitive>[originalLength, cps.letPrim(new GetLength(list))]);
+    cps.ifTrue(lengthChanged).invokeStaticThrower(
+        backend.getThrowConcurrentModificationError(),
+        <Primitive>[list]);
+    return cps;
+  }
+
+  /// Counts number of index accesses on [list] and determines based on
+  /// that number if we should try to inline them.
+  ///
+  /// This is a short-term solution to avoid inserting a lot of bounds checks,
+  /// since there is currently no optimization for eliminating them.
+  bool hasTooManyIndexAccesses(Primitive list) {
+    int count = 0;
+    for (Reference ref = list.firstRef; ref != null; ref = ref.next) {
+      Node use = ref.parent;
+      if (use is InvokeMethod && 
+          (use.selector.isIndex || use.selector.isIndexSet) &&
+          getDartReceiver(use) == list) {
+        ++count;
+      } else if (use is GetIndex && use.object.definition == list) {
+        ++count;
+      } else if (use is SetIndex && use.object.definition == list) {
+        ++count;
+      }
+      if (count > 2) return true;
+    }
+    return false;
+  }
+
+  /// Tries to replace [node] with one or more direct array access operations.
+  ///
+  /// Returns `true` if the node was replaced.
+  bool specializeArrayAccess(InvokeMethod node) {
+    Primitive list = getDartReceiver(node);
+    AbstractValue listValue = getValue(list);
+    // Ensure that the object is a native list or null.
+    if (!lattice.isDefinitelyNativeList(listValue, allowNull: true)) {
+      return false;
+    }
+    bool isFixedLength = 
+        lattice.isDefinitelyFixedNativeList(listValue, allowNull: true);
+    bool isMutable =
+        lattice.isDefinitelyMutableNativeList(listValue, allowNull: true);
+    SourceInformation sourceInfo = node.sourceInformation;
+    Continuation cont = node.continuation.definition;
+    switch (node.selector.name) {
+      case 'length':
+        if (!node.selector.isGetter) return false;
+        CpsFragment cps = new CpsFragment(sourceInfo);
+        cps.invokeContinuation(cont, [cps.letPrim(new GetLength(list))]);
+        replaceSubtree(node, cps.result);
+        visit(cps.result);
+        return true;
+
+      case '[]':
+        if (listValue.isNullable) return false;
+        if (hasTooManyIndexAccesses(list)) return false;
+        Primitive index = getDartArgument(node, 0);
+        if (!lattice.isDefinitelyInt(getValue(index))) return false;
+        CpsFragment cps = makeBoundsCheck(list, index, sourceInfo);
+        GetIndex get = cps.letPrim(new GetIndex(list, index));
+        cps.invokeContinuation(cont, [get]);
+        replaceSubtree(node, cps.result);
+        visit(cps.result);
+        return true;
+
+      case '[]=':
+        if (listValue.isNullable) return false;
+        if (hasTooManyIndexAccesses(list)) return false;
+        Primitive index = getDartArgument(node, 0);
+        Primitive value = getDartArgument(node, 1);
+        if (!isMutable) return false;
+        if (!lattice.isDefinitelyInt(getValue(index))) return false;
+        CpsFragment cps = makeBoundsCheck(list, index, sourceInfo);
+        cps.letPrim(new SetIndex(list, index, value));
+        assert(cont.parameters.single.hasNoUses);
+        cont.parameters.clear();
+        cps.invokeContinuation(cont, []);
+        replaceSubtree(node, cps.result);
+        visit(cps.result);
+        return true;
+
+      case 'forEach':
+        if (!node.selector.isCall ||
+            node.selector.positionalArgumentCount != 1 ||
+            node.selector.namedArgumentCount != 0) {
+          return false;
+        }
+        Primitive callback = getDartArgument(node, 0);
+        // Rewrite to:
+        //   var originalLength = array.length, i = 0;
+        //   while (i < array.length) {
+        //     callback(array[i]);
+        //     if (array.length !== originalLength) throw;
+        //     i = i + 1;
+        //   }
+        CpsFragment cps = new CpsFragment(sourceInfo);
+        Primitive originalLength = cps.letPrim(new GetLength(list));
+        originalLength.hint = new OriginalLengthEntity();
+
+        // Build a loop.
+        Parameter loopIndex = new Parameter(new LoopIndexEntity());
+        Continuation loop = cps.beginLoop(
+            <Parameter>[loopIndex], [cps.makeZero()]);
+
+        // Check for loop exit.
+        Primitive loopCondition = cps.applyBuiltin(
+            BuiltinOperator.NumLt,
+            [loopIndex, cps.letPrim(new GetLength(list))]);
+        CpsFragment exitBranch = cps.ifFalse(loopCondition);
+        exitBranch.invokeContinuation(cont, [exitBranch.makeNull()]);
+
+        // Invoke the callback.
+        Primitive arrayItem = cps.letPrim(new GetIndex(list, loopIndex));
+        cps.invokeMethod(callback,
+                         new Selector.callClosure(1),
+                         getValue(callback).type,
+                         [arrayItem]);
+
+        // Check for concurrent modification, unless the list is fixed-length.
+        if (!isFixedLength) {
+          cps.append(
+            makeConcurrentModificationCheck(list, originalLength, sourceInfo));
+        }
+
+        // Increment i and continue the loop.
+        Primitive addOne = cps.applyBuiltin(
+            BuiltinOperator.NumAdd,
+            [loopIndex, cps.makeOne()]);
+        cps.continueLoop(loop, [addOne]);
+
+        replaceSubtree(node, cps.result);
+        visit(cps.result);
+        return true;
+
+      case 'iterator':
+        if (!node.selector.isGetter) return false;
+        Primitive iterator = cont.parameters.single;
+        Continuation iteratorCont = cont;
+
+        // Check that all uses of the iterator are 'moveNext' and 'current'.
+        Selector moveNextSelector = new Selector.call('moveNext', null, 0);
+        Selector currentSelector = new Selector.getter('current', null);
+        assert(!isInterceptedSelector(moveNextSelector));
+        assert(!isInterceptedSelector(currentSelector));
+        for (Reference ref = iterator.firstRef; ref != null; ref = ref.next) {
+          if (ref.parent is! InvokeMethod) return false;
+          InvokeMethod use = ref.parent;
+          if (ref != use.receiver) return false;
+          if (use.selector != moveNextSelector &&
+              use.selector != currentSelector) {
+            return false;
+          }
+        }
+
+        // Rewrite the iterator variable to 'current' and 'index' variables.
+        Primitive originalLength = new GetLength(list);
+        originalLength.hint = new OriginalLengthEntity();
+        MutableVariable index = new MutableVariable(new LoopIndexEntity());
+        MutableVariable current = new MutableVariable(new LoopItemEntity());
+
+        // Rewrite all uses of the iterator.
+        while (iterator.firstRef != null) { 
+          InvokeMethod use = iterator.firstRef.parent;
+          Continuation useCont = use.continuation.definition;
+          if (use.selector == currentSelector) { 
+            // Rewrite iterator.current to a use of the 'current' variable.
+            Parameter result = useCont.parameters.single;
+            if (result.hint != null) {
+              // If 'current' was originally moved into a named variable, use
+              // that variable name for the mutable variable.
+              current.hint = result.hint; 
+            }
+            LetPrim let = 
+                makeLetPrimInvoke(new GetMutableVariable(current), useCont);
+            replaceSubtree(use, let);
+          } else {
+            assert (use.selector == moveNextSelector);
+            // Rewrite iterator.moveNext() to: 
+            //
+            //   if (index < list.length) {
+            //     current = null;
+            //     continuation(false);
+            //   } else {
+            //     current = list[index];
+            //     index = index + 1;
+            //     continuation(true);
+            //   }
+            //
+            // (The above does not show concurrent modification checks)
+
+            // [cps] contains the code we insert instead of moveNext().
+            CpsFragment cps = new CpsFragment(node.sourceInformation);
+
+            // We must check for concurrent modification when calling moveNext.
+            // When moveNext is used as a loop condition, the check prevents
+            // `index < list.length` from becoming the loop condition, and we 
+            // get code like this:
+            //
+            //    while (true) {
+            //      if (originalLength !== list.length) throw;
+            //      if (index < list.length) { 
+            //        ...
+            //      } else { 
+            //        ... 
+            //        break; 
+            //      }
+            //    }
+            //
+            // For loops, we therefore check for concurrent modification before
+            // invoking the recursive continuation, so the loop becomes:
+            //
+            //    if (originalLength !== list.length) throw;
+            //    while (index < list.length) {
+            //      ...
+            //      if (originalLength !== list.length) throw;
+            //    }
+            //
+            // The check before the loop can often be eliminated because it 
+            // follows immediately after the 'iterator' call.
+            InteriorNode parent = getEffectiveParent(use);
+            if (!isFixedLength) {
+              if (parent is Continuation && parent.isRecursive) {
+                // Check for concurrent modification before every invocation
+                // of the continuation.
+                // TODO(asgerf): Do this in a continuation so multiple 
+                //               continues can share the same code.
+                for (Reference ref = parent.firstRef; 
+                     ref != null; 
+                     ref = ref.next) {
+                  Expression invocationCaller = ref.parent;
+                  if (getEffectiveParent(invocationCaller) == iteratorCont) {
+                    // No need to check for concurrent modification immediately
+                    // after the call to 'iterator'.
+                    continue;
+                  }
+                  CpsFragment check = makeConcurrentModificationCheck(
+                      list, originalLength, sourceInfo);
+                  insertBefore(invocationCaller, check);
+                }
+              } else {
+                cps.append(makeConcurrentModificationCheck(
+                    list, originalLength, sourceInfo));
+              }
+            }
+
+            // Check if there are more elements.
+            Primitive hasMore = cps.applyBuiltin(
+                BuiltinOperator.NumLt,
+                [cps.getMutable(index), cps.letPrim(new GetLength(list))]);
+
+            // Return false if there are no more.
+            CpsFragment falseBranch = cps.ifFalse(hasMore);
+            falseBranch
+              ..setMutable(current, falseBranch.makeNull())
+              ..invokeContinuation(useCont, [falseBranch.makeFalse()]);
+
+            // Return true if there are more element.
+            cps.setMutable(current, 
+                cps.letPrim(new GetIndex(list, cps.getMutable(index))));
+            cps.setMutable(index, cps.applyBuiltin(
+                BuiltinOperator.NumAdd,
+                [cps.getMutable(index), cps.makeOne()]));
+            cps.invokeContinuation(useCont, [cps.makeTrue()]);
+
+            // Replace the moveNext() call. It will be visited later.
+            replaceSubtree(use, cps.result);
+          }
+        }
+
+        // Rewrite the iterator call to initializers for 'index' and 'current'.
+        CpsFragment cps = new CpsFragment();
+        cps.letMutable(index, cps.makeZero());
+        cps.letMutable(current, cps.makeNull());
+        cps.letPrim(originalLength);
+
+        // Insert this fragment before the continuation body and replace the
+        // iterator call with a call to the continuation without arguments.
+        // For scoping reasons, the variables must be bound inside the
+        // continuation, not at the invocation-site.
+        iteratorCont.parameters.clear();
+        insertBefore(iteratorCont.body, cps);
+        InvokeContinuation invoke = new InvokeContinuation(iteratorCont, []);
+        replaceSubtree(node, invoke);
+        visit(invoke);
+        // TODO(asgerf): A procedure for rewriting mutables into parameters
+        //               might enable further optimizations after this.
+        return true;
+
+      // TODO(asgerf): Rewrite 'add', 'removeLast', ...
+
+      default:
+        return false;
+    }
+  }
+
   /// If [prim] is the parameter to a call continuation, returns the
   /// corresponding call.
   Invoke getInvocationWithResult(Primitive prim) {
@@ -779,29 +1190,17 @@
     return null;
   }
 
-  /// True if any side effect immediately before [current] can safely be
-  /// postponed until immediately before [target].
-  ///
-  /// An expression `e` can be moved right before [target] if
-  /// `canPostponeSideEffects(e.body, target)` is true and no reference
-  /// falls out of scope.
-  ///
-  /// A more sophisticated analysis would track side-effect dependencies
-  /// between `e` and the expressions between `e` and the target.
-  bool canPostponeSideEffects(Expression current, Expression target) {
-    Expression exp = current;
-    while (exp != target) {
-      if (exp is LetPrim && exp.primitive.isSafeForReordering) {
-        LetPrim let = exp;
-        exp = let.body;
-      } else if (exp is LetCont) {
-        LetCont let = exp;
-        exp = let.body;
+  /// Returns the first parent of [node] that is not a pure expression.
+  InteriorNode getEffectiveParent(Expression node) {
+    while (true) {
+      Node parent = node.parent;
+      if (parent is LetCont ||
+          parent is LetPrim && parent.primitive.isSafeForReordering) {
+        node = parent;
       } else {
-        return false;
+        return parent;
       }
     }
-    return true;
   }
 
   /// Rewrites an invocation of a torn-off method into a method call directly
@@ -847,6 +1246,10 @@
     Invoke tearOffInvoke = getInvocationWithResult(tearOff);
     if (tearOffInvoke is InvokeMethod && tearOffInvoke.selector.isGetter) {
       Selector getter = tearOffInvoke.selector;
+
+      // TODO(asgerf): Support torn-off intercepted methods.
+      if (isInterceptedSelector(getter)) return false;
+
       Continuation getterCont = tearOffInvoke.continuation.definition;
 
       // TODO(asgerf): Support torn-off intercepted methods.
@@ -868,7 +1271,7 @@
       if (!isPure && tearOff.hasMultipleUses) return false;
 
       // If the getter call is impure, we risk reordering side effects.
-      if (!isPure && !canPostponeSideEffects(getterCont.body, node)) {
+      if (!isPure && getEffectiveParent(node) != getterCont) {
         return false;
       }
 
@@ -905,6 +1308,7 @@
     if (constifyExpression(node)) return;
     if (specializeOperatorCall(node)) return;
     if (specializeFieldAccess(node)) return;
+    if (specializeArrayAccess(node)) return;
     if (specializeClosureCall(node)) return;
 
     AbstractValue receiver = getValue(node.receiver.definition);
@@ -1075,6 +1479,10 @@
     node.objectIsNotNull = getValue(node.object.definition).isDefinitelyNotNull;
   }
 
+  void visitGetLength(GetLength node) {
+    node.objectIsNotNull = getValue(node.object.definition).isDefinitelyNotNull;
+  }
+
   void visitLetPrim(LetPrim node) {
     AbstractValue value = getValue(node.primitive);
     if (node.primitive is! Constant && value.isConstant) {
@@ -1127,6 +1535,7 @@
         !cont.isRecursive &&
         !node.isEscapingTry) {
       for (int i = 0; i < node.arguments.length; ++i) {
+        node.arguments[i].definition.useElementAsHint(cont.parameters[i].hint);
         node.arguments[i].definition.substituteFor(cont.parameters[i]);
         node.arguments[i].unlink();
       }
@@ -1471,7 +1880,13 @@
       case BuiltinOperator.NumAnd:
       case BuiltinOperator.NumOr:
       case BuiltinOperator.NumXor:
-        setValue(node, nonConstant(typeSystem.numType));
+        AbstractValue left = getValue(node.arguments[0].definition);
+        AbstractValue right = getValue(node.arguments[1].definition);
+        if (lattice.isDefinitelyInt(left) && lattice.isDefinitelyInt(right)) {
+          setValue(node, nonConstant(typeSystem.intType));
+        } else {
+          setValue(node, nonConstant(typeSystem.numType));
+        }
         break;
 
       case BuiltinOperator.NumLt:
@@ -1599,7 +2014,7 @@
   void visitLiteralList(LiteralList node) {
     // Constant lists are translated into (Constant ListConstant(...)) IR nodes,
     // and thus LiteralList nodes are NonConst.
-    setValue(node, nonConstant(typeSystem.listType));
+    setValue(node, nonConstant(typeSystem.mutableNativeListType));
   }
 
   void visitLiteralMap(LiteralMap node) {
@@ -1756,6 +2171,21 @@
       setValue(returnValue, nonConstant(node.type));
     }
   }
+
+  @override
+  void visitGetLength(GetLength node) {
+    setValue(node, nonConstant(typeSystem.intType));
+  }
+
+  @override
+  void visitGetIndex(GetIndex node) {
+    setValue(node, nonConstant());
+  }
+
+  @override
+  void visitSetIndex(SetIndex node) {
+    setValue(node, nonConstant());
+  }
 }
 
 /// Represents the abstract value of a primitive value at some point in the
@@ -1787,8 +2217,16 @@
   AbstractValue.constantValue(ConstantValue constant, TypeMask type)
       : this._internal(CONSTANT, constant, type);
 
-  AbstractValue.nonConstant(TypeMask type)
-      : this._internal(NONCONST, null, type);
+  factory AbstractValue.nonConstant(TypeMask type) {
+    if (type.isEmpty) {
+      if (type.isNullable)
+        return new AbstractValue.constantValue(new NullConstantValue(), type);
+      else
+        return new AbstractValue.nothing();
+    } else {
+      return new AbstractValue._internal(NONCONST, null, type);
+    }
+  }
 
   bool get isNothing  => (kind == NOTHING);
   bool get isConstant => (kind == CONSTANT);
@@ -1825,6 +2263,22 @@
   static const String Stringify = 'S';
 }
 
+/// Suggested name for a synthesized loop index.
+class LoopIndexEntity extends Entity {
+  String get name => 'i';
+}
+
+/// Suggested name for the current element of a list being iterated.
+class LoopItemEntity extends Entity {
+  String get name => 'current';
+}
+
+/// Suggested name for the original length of a list, for use in checks
+/// for concurrent modification.
+class OriginalLengthEntity extends Entity {
+  String get name => 'length';
+}
+
 class ResetAnalysisInfo extends RecursiveVisitor {
   Set<Node> reachableNodes;
   Map<Definition, AbstractValue> values;
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index 2cbaf31..51cdae4 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -359,7 +359,12 @@
           "Async-await is supported by default.",
           api.Diagnostic.HINT);
     }),
-    new OptionHandler('--enable-null-aware-operators', passThrough),
+    new OptionHandler('--enable-null-aware-operators',  (_) {
+      diagnosticHandler.info(
+          "Option '--enable-null-aware-operators' is no longer needed. "
+          "Null aware operators are supported by default.",
+          api.Diagnostic.HINT);
+    }),
     new OptionHandler('--enable-enum', (_) {
       diagnosticHandler.info(
           "Option '--enable-enum' is no longer needed. "
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index 3e4cda2..2524fb1 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -21,6 +21,7 @@
 import 'types/types.dart' show TypeMask;
 import 'deferred_load.dart' show OutputUnit;
 import 'js_backend/js_backend.dart' show JavaScriptBackend;
+import 'js_emitter/full_emitter/emitter.dart' as full show Emitter;
 import 'js/js.dart' as jsAst;
 import 'universe/universe.dart' show Selector, UniverseSelector;
 import 'util/util.dart' show NO_LOCATION_SPANNABLE;
@@ -596,6 +597,9 @@
         new List<Map<String, dynamic>>();
 
     JavaScriptBackend backend = compiler.backend;
+    // Dump-info currently only works with the full emitter. If another
+    // emitter is used it will fail here.
+    full.Emitter fullEmitter = backend.emitter.emitter;
 
     for (OutputUnit outputUnit in
         infoCollector.mapper._outputUnit._elementToId.keys) {
@@ -603,7 +607,7 @@
       outputUnits.add(<String, dynamic> {
         'id': id,
         'name': outputUnit.name,
-        'size': backend.emitter.oldEmitter.outputBuffers[outputUnit].length,
+        'size': fullEmitter.outputBuffers[outputUnit].length,
       });
     }
 
diff --git a/pkg/compiler/lib/src/helpers/helpers.dart b/pkg/compiler/lib/src/helpers/helpers.dart
index bcfa12c..9f7e284 100644
--- a/pkg/compiler/lib/src/helpers/helpers.dart
+++ b/pkg/compiler/lib/src/helpers/helpers.dart
@@ -93,3 +93,52 @@
   compiler.reportInfo(node,
       MessageKind.GENERIC, {'text': 'HERE: $debugMessage'});
 }
+
+/// Set of tracked objects used by [track] and [ifTracked].
+var _trackedObjects = new Set();
+
+/// Global default value for the `printTrace` option of [track] and [ifTracked].
+bool trackWithTrace = false;
+
+/// If [doTrack] is `true`, add [object] to the set of tracked objects.
+///
+/// If tracked, [message] is printed along the hash code and toString of
+/// [object]. If [printTrace] is `true` a trace printed additionally.
+/// If [printTrace] is `null`, [trackWithTrace] determines whether a trace is
+/// printed.
+///
+/// [object] is returned as the result of the method.
+track(bool doTrack, Object object, String message, {bool printTrace}) {
+  if (!doTrack) return object;
+  _trackedObjects.add(object);
+  String msg = 'track: ${object.hashCode}:$object:$message';
+  if (printTrace == null) printTrace = trackWithTrace;
+  if (printTrace) {
+    trace(msg);
+  } else {
+    debugPrint(msg);
+  }
+  return object;
+}
+
+/// Returns `true` if [object] is in the set of tracked objects.
+///
+/// If [message] is provided it is printed along the hash code and toString of
+/// [object]. If [printTrace] is `true` a trace printed additionally. If
+/// [printTrace] is `null`, [trackWithTrace] determines whether a trace is
+/// printed.
+bool ifTracked(Object object, {String message, bool printTrace}) {
+  if (_trackedObjects.contains(object)) {
+    if (message != null) {
+      String msg = 'tracked: ${object.hashCode}:$object:$message';
+      if (printTrace == null) printTrace = trackWithTrace;
+      if (printTrace) {
+        trace(msg);
+      } else {
+        debugPrint(msg);
+      }
+    }
+    return true;
+  }
+  return false;
+}
diff --git a/pkg/compiler/lib/src/inferrer/concrete_types_inferrer.dart b/pkg/compiler/lib/src/inferrer/concrete_types_inferrer.dart
index 9369d1d..19bcab4 100644
--- a/pkg/compiler/lib/src/inferrer/concrete_types_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/concrete_types_inferrer.dart
@@ -557,12 +557,12 @@
 
   @override
   ConcreteType nonNullSubclass(ClassElement cls) {
-    return nonNullSubX(cls, compiler.world.subclassesOf);
+    return nonNullSubX(cls, compiler.world.strictSubclassesOf);
   }
 
   @override
   ConcreteType nonNullSubtype(ClassElement cls) {
-    return nonNullSubX(cls, compiler.world.subtypesOf);
+    return nonNullSubX(cls, compiler.world.strictSubtypesOf);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/inferrer/node_tracer.dart b/pkg/compiler/lib/src/inferrer/node_tracer.dart
index b037c2f..4bd3b4c 100644
--- a/pkg/compiler/lib/src/inferrer/node_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/node_tracer.dart
@@ -19,9 +19,7 @@
     'isEmpty',
     'isNotEmpty',
     'length',
-    'any',
     'contains',
-    'every',
     'join',
 
     // From List.
diff --git a/pkg/compiler/lib/src/io/position_information.dart b/pkg/compiler/lib/src/io/position_information.dart
index 9b91cab1..416d7ea 100644
--- a/pkg/compiler/lib/src/io/position_information.dart
+++ b/pkg/compiler/lib/src/io/position_information.dart
@@ -149,6 +149,9 @@
   SourceInformation buildGeneric(Node node) => buildBegin(node);
 
   @override
+  SourceInformation buildCreate(Node node) => buildBegin(node);
+
+  @override
   SourceInformation buildReturn(Node node) => buildBegin(node);
 
   @override
diff --git a/pkg/compiler/lib/src/io/source_information.dart b/pkg/compiler/lib/src/io/source_information.dart
index 3c4ea20..09d1ca9 100644
--- a/pkg/compiler/lib/src/io/source_information.dart
+++ b/pkg/compiler/lib/src/io/source_information.dart
@@ -61,6 +61,10 @@
   @deprecated
   SourceInformation buildGeneric(Node node) => null;
 
+  /// Generate [SourceInformation] for an instantiation of a class using [node]
+  /// for the source position.
+  SourceInformation buildCreate(Node node) => null;
+
   /// Generate [SourceInformation] for the return [node].
   SourceInformation buildReturn(Node node) => null;
 
diff --git a/pkg/compiler/lib/src/io/start_end_information.dart b/pkg/compiler/lib/src/io/start_end_information.dart
index b76a217..4547fca 100644
--- a/pkg/compiler/lib/src/io/start_end_information.dart
+++ b/pkg/compiler/lib/src/io/start_end_information.dart
@@ -203,9 +203,10 @@
   }
 
   @override
-  SourceInformation buildReturn(Node node) {
-    return buildGeneric(node);
-  }
+  SourceInformation buildCreate(Node node) => buildGeneric(node);
+
+  @override
+  SourceInformation buildReturn(Node node) => buildGeneric(node);
 
   @override
   SourceInformation buildGet(Node node) => buildGeneric(node);
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index c48fed1..bbe0c3b 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -850,7 +850,7 @@
     Iterable<MixinApplicationElement> uses = classWorld.mixinUsesOf(mixin);
     Set<ClassElement> result = null;
     for (MixinApplicationElement use in uses) {
-      Iterable<ClassElement> subclasses = classWorld.subclassesOf(use);
+      Iterable<ClassElement> subclasses = classWorld.strictSubclassesOf(use);
       for (ClassElement subclass in subclasses) {
         if (Elements.isNativeOrExtendsNative(subclass)) {
           if (result == null) result = new Set<ClassElement>();
@@ -1737,6 +1737,10 @@
     return findHelper('throwConcurrentModificationError');
   }
 
+  Element getThrowIndexOutOfBoundsError() {
+    return findHelper('ioore');
+  }
+
   Element getStringInterpolationHelper() {
     return findHelper('S');
   }
@@ -2333,8 +2337,8 @@
           }
         });
         // 4) all overriding members of subclasses/subtypes (should be resolved)
-        if (compiler.world.hasAnySubtype(cls)) {
-          for (ClassElement subcls in compiler.world.subtypesOf(cls)) {
+        if (compiler.world.hasAnyStrictSubtype(cls)) {
+          for (ClassElement subcls in compiler.world.strictSubtypesOf(cls)) {
             subcls.forEachClassMember((Member member) {
               if (memberNames.contains(member.name)) {
                 // TODO(20993): find out why this assertion fails.
diff --git a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
index 1447173..e0388d2 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
@@ -48,6 +48,12 @@
 
   final tree_ir.FallthroughStack fallthrough = new tree_ir.FallthroughStack();
 
+  /// Stacks whose top element is the current target of an unlabeled break
+  /// or continue. For continues, this is the loop node itself.
+  final tree_ir.FallthroughStack shortBreak = new tree_ir.FallthroughStack();
+  final tree_ir.FallthroughStack shortContinue =
+      new tree_ir.FallthroughStack();
+
   Set<tree_ir.Label> usedLabels = new Set<tree_ir.Label>();
 
   List<js.Statement> accumulator = new List<js.Statement>();
@@ -177,14 +183,18 @@
         visitExpression(node.elseExpression));
   }
 
-  js.Expression buildConstant(ConstantValue constant) {
+  js.Expression buildConstant(ConstantValue constant,
+                              {SourceInformation sourceInformation}) {
     registry.registerCompileTimeConstant(constant);
-    return glue.constantReference(constant);
+    return glue.constantReference(constant)
+        .withSourceInformation(sourceInformation);
   }
 
   @override
   js.Expression visitConstant(tree_ir.Constant node) {
-    return buildConstant(node.value);
+    return buildConstant(
+        node.value,
+        sourceInformation: node.sourceInformation);
   }
 
   js.Expression compileConstant(ParameterElement parameter) {
@@ -207,7 +217,8 @@
     registry.registerInstantiatedType(node.type);
     FunctionElement target = node.target;
     List<js.Expression> arguments = visitExpressionList(node.arguments);
-    return buildStaticInvoke(target, arguments);
+    return buildStaticInvoke(
+        target, arguments, sourceInformation: node.sourceInformation);
   }
 
   void registerMethodInvoke(tree_ir.InvokeMethod node) {
@@ -234,7 +245,8 @@
     registerMethodInvoke(node);
     return js.propertyCall(visitExpression(node.receiver),
                            glue.invocationName(node.selector),
-                           visitExpressionList(node.arguments));
+                           visitExpressionList(node.arguments))
+        .withSourceInformation(node.sourceInformation);
   }
 
   @override
@@ -254,13 +266,15 @@
       return js.js('#.#(#)',
           [visitExpression(node.receiver),
            glue.instanceMethodName(node.target),
-           visitExpressionList(node.arguments)]);
+           visitExpressionList(node.arguments)])
+          .withSourceInformation(node.sourceInformation);
     }
     return js.js('#.#.call(#, #)',
         [glue.prototypeAccess(node.target.enclosingClass),
          glue.invocationName(node.selector),
          visitExpression(node.receiver),
-         visitExpressionList(node.arguments)]);
+         visitExpressionList(node.arguments)])
+        .withSourceInformation(node.sourceInformation);
   }
 
   @override
@@ -390,27 +404,36 @@
   @override
   void visitContinue(tree_ir.Continue node) {
     tree_ir.Statement next = fallthrough.target;
-    if (node.target.binding == next) {
-      // Fall through to continue target
+    if (node.target.binding == next ||
+        next is tree_ir.Continue && node.target == next.target) {
+      // Fall through to continue target or to equivalent continue.
       fallthrough.use();
-    } else if (next is tree_ir.Continue && next.target == node.target) {
-      // Fall through to equivalent continue
-      fallthrough.use();
+    } else if (node.target.binding == shortContinue.target) {
+      // The target is the immediately enclosing loop.
+      shortContinue.use();
+      accumulator.add(new js.Continue(null));
     } else {
       usedLabels.add(node.target);
       accumulator.add(new js.Continue(node.target.name));
     }
   }
 
+  /// True if [other] is the target of [node] or is a [Break] with the same
+  /// target. This means jumping to [other] is equivalent to executing [node].
+  bool isEffectiveBreakTarget(tree_ir.Break node, tree_ir.Statement other) {
+    return node.target.binding.next == other ||
+           other is tree_ir.Break && node.target == other.target;
+  }
+
   @override
   void visitBreak(tree_ir.Break node) {
-    tree_ir.Statement next = fallthrough.target;
-    if (node.target.binding.next == next) {
-      // Fall through to break target
+    if (isEffectiveBreakTarget(node, fallthrough.target)) {
+      // Fall through to break target or to equivalent break.
       fallthrough.use();
-    } else if (next is tree_ir.Break && next.target == node.target) {
-      // Fall through to equivalent break
-      fallthrough.use();
+    } else if (isEffectiveBreakTarget(node, shortBreak.target)) {
+      // Unlabeled break to the break target or to an equivalent break.
+      shortBreak.use();
+      accumulator.add(new js.Break(null));
     } else {
       usedLabels.add(node.target);
       accumulator.add(new js.Break(node.target.name));
@@ -443,22 +466,20 @@
 
   @override
   void visitLabeledStatement(tree_ir.LabeledStatement node) {
-    accumulator.add(buildLabeled(() => buildBodyStatement(node.body),
-                                 node.label,
-                                 node.next));
+    fallthrough.push(node.next);
+    js.Statement body = buildBodyStatement(node.body);
+    fallthrough.pop();
+    accumulator.add(insertLabel(node.label, body));
     visitStatement(node.next);
   }
 
-  js.Statement buildLabeled(js.Statement buildBody(),
-                            tree_ir.Label label,
-                            tree_ir.Statement fallthroughStatement) {
-    fallthrough.push(fallthroughStatement);
-    js.Statement result = buildBody();
+  /// Wraps a node in a labeled statement unless the label is unused.
+  js.Statement insertLabel(tree_ir.Label label, js.Statement node) {
     if (usedLabels.remove(label)) {
-      result = new js.LabeledStatement(label.name, result);
+      return new js.LabeledStatement(label.name, node);
+    } else {
+      return node;
     }
-    fallthrough.pop();
-    return result;
   }
 
   /// Returns the current [accumulator] wrapped in a block if neccessary.
@@ -491,29 +512,36 @@
     return result;
   }
 
-  js.Statement buildWhile(js.Expression condition,
-                          tree_ir.Statement body,
-                          tree_ir.Label label,
-                          tree_ir.Statement fallthroughStatement) {
-    return buildLabeled(() => new js.While(condition, buildBodyStatement(body)),
-                        label,
-                        fallthroughStatement);
-  }
-
   @override
   void visitWhileCondition(tree_ir.WhileCondition node) {
-    accumulator.add(
-        buildWhile(visitExpression(node.condition),
-                   node.body,
-                   node.label,
-                   node));
+    js.Expression condition = visitExpression(node.condition);
+    shortBreak.push(node.next);
+    shortContinue.push(node);
+    fallthrough.push(node);
+    js.Statement jsBody = buildBodyStatement(node.body);
+    fallthrough.pop();
+    shortContinue.pop();
+    shortBreak.pop();
+    accumulator.add(insertLabel(node.label, new js.While(condition, jsBody)));
     visitStatement(node.next);
   }
 
   @override
   void visitWhileTrue(tree_ir.WhileTrue node) {
-    accumulator.add(
-        buildWhile(new js.LiteralBool(true), node.body, node.label, node));
+    js.Expression condition = new js.LiteralBool(true);
+    // A short break in the while will jump to the current fallthrough target.
+    shortBreak.push(fallthrough.target);
+    shortContinue.push(node);
+    fallthrough.push(node);
+    js.Statement jsBody = buildBodyStatement(node.body);
+    fallthrough.pop();
+    shortContinue.pop();
+    if (shortBreak.useCount > 0) {
+      // Short breaks use the current fallthrough target.
+      fallthrough.use();
+    }
+    shortBreak.pop();
+    accumulator.add(insertLabel(node.label, new js.While(condition, jsBody)));
   }
 
   bool isNull(tree_ir.Expression node) {
@@ -527,7 +555,8 @@
       registry.registerCompileTimeConstant(new NullConstantValue());
       fallthrough.use();
     } else {
-      accumulator.add(new js.Return(visitExpression(node.value)));
+      accumulator.add(new js.Return(visitExpression(node.value))
+            .withSourceInformation(node.sourceInformation));
     }
   }
 
@@ -576,7 +605,8 @@
     }
     js.Expression instance = new js.New(
         glue.constructorAccess(classElement),
-        visitExpressionList(node.arguments));
+        visitExpressionList(node.arguments))
+        .withSourceInformation(node.sourceInformation);
 
     List<tree_ir.Expression> typeInformation = node.typeInformation;
     assert(typeInformation.isEmpty ||
@@ -586,7 +616,8 @@
       js.Expression typeArguments = new js.ArrayInitializer(
           visitExpressionList(typeInformation));
       return buildStaticHelperInvocation(helper,
-          <js.Expression>[instance, typeArguments]);
+          <js.Expression>[instance, typeArguments],
+          sourceInformation: node.sourceInformation);
     } else {
       return instance;
     }
@@ -664,19 +695,45 @@
     return new js.Assignment(field, value);
   }
 
-  js.Expression buildStaticHelperInvocation(FunctionElement helper,
-                                            List<js.Expression> arguments) {
+  @override
+  js.Expression visitGetLength(tree_ir.GetLength node) {
+    return new js.PropertyAccess.field(visitExpression(node.object), 'length');
+  }
+
+  @override
+  js.Expression visitGetIndex(tree_ir.GetIndex node) {
+    return new js.PropertyAccess(
+        visitExpression(node.object),
+        visitExpression(node.index));
+  }
+
+  @override
+  js.Expression visitSetIndex(tree_ir.SetIndex node) {
+    return js.js('#[#] = #',
+        [visitExpression(node.object),
+         visitExpression(node.index),
+         visitExpression(node.value)]);
+  }
+
+  js.Expression buildStaticHelperInvocation(
+      FunctionElement helper,
+      List<js.Expression> arguments,
+      {SourceInformation sourceInformation}) {
     registry.registerStaticUse(helper);
-    return buildStaticInvoke(helper, arguments);
+    return buildStaticInvoke(
+        helper, arguments, sourceInformation: sourceInformation);
   }
 
   @override
   js.Expression visitReifyRuntimeType(tree_ir.ReifyRuntimeType node) {
-    FunctionElement createType = glue.getCreateRuntimeType();
-    FunctionElement typeToString = glue.getRuntimeTypeToString();
-    return buildStaticHelperInvocation(createType,
-        [buildStaticHelperInvocation(typeToString,
-            [visitExpression(node.value)])]);
+    js.Expression typeToString = buildStaticHelperInvocation(
+        glue.getRuntimeTypeToString(),
+        [visitExpression(node.value)],
+        sourceInformation: node.sourceInformation);
+    return buildStaticHelperInvocation(
+        glue.getCreateRuntimeType(),
+        [typeToString],
+        sourceInformation: node.sourceInformation);
   }
 
   @override
@@ -687,11 +744,13 @@
       js.Expression typeName = glue.getRuntimeTypeName(context);
       return buildStaticHelperInvocation(
           glue.getRuntimeTypeArgument(),
-          [visitExpression(node.target), typeName, index]);
+          [visitExpression(node.target), typeName, index],
+          sourceInformation: node.sourceInformation);
     } else {
       return buildStaticHelperInvocation(
           glue.getTypeArgumentByIndex(),
-          [visitExpression(node.target), index]);
+          [visitExpression(node.target), index],
+          sourceInformation: node.sourceInformation);
     }
   }
 
diff --git a/pkg/compiler/lib/src/js_backend/codegen/task.dart b/pkg/compiler/lib/src/js_backend/codegen/task.dart
index 9ed2829..9c4658c 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/task.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/task.dart
@@ -181,9 +181,12 @@
       assert(checkCpsIntegrity(cpsNode));
     }
 
+    applyCpsPass(new RedundantPhiEliminator());
     TypePropagator typePropagator = new TypePropagator(compiler);
     applyCpsPass(typePropagator);
     dumpTypedIR(cpsNode, typePropagator);
+    applyCpsPass(new ShrinkingReducer());
+    applyCpsPass(new RedundantJoinEliminator());
     applyCpsPass(new RedundantPhiEliminator());
     applyCpsPass(new ShrinkingReducer());
 
diff --git a/pkg/compiler/lib/src/js_backend/minify_namer.dart b/pkg/compiler/lib/src/js_backend/minify_namer.dart
index dd01a92..b781bc0 100644
--- a/pkg/compiler/lib/src/js_backend/minify_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/minify_namer.dart
@@ -342,9 +342,11 @@
     String prefix = selector.isGetter
         ? r"$get"
         : selector.isSetter ? r"$set" : "";
-    String arity = selector.isCall ? "${selector.argumentCount}" : "";
+    String callSuffix =
+        selector.isCall ? callSuffixForStructure(selector.callStructure).join()
+                        : "";
     String suffix = suffixForGetInterceptor(classes);
-    String fullName = "\$intercepted$prefix\$$root$arity\$$suffix";
+    String fullName = "\$intercepted$prefix\$$root$callSuffix\$$suffix";
     return _disambiguateInternalGlobal(fullName);
   }
 }
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 9ce0b81..ad7f725 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -321,7 +321,7 @@
   }
 
   final String asyncPrefix = r"$async$";
-  final String currentIsolate = r'$';
+  final String staticStateHolder = r'$';
   final String getterPrefix = r'get$';
   final String lazyGetterPrefix = r'$get$';
   final String setterPrefix = r'set$';
@@ -1313,17 +1313,19 @@
         : globalPropertyName(method);
   }
 
-  /// Returns true if [element] is stored on current isolate ('$').  We intend
-  /// to store only mutable static state in [currentIsolate], constants are
-  /// stored in 'C', and functions, accessors, classes, etc. are stored in one
-  /// of the other objects in [reservedGlobalObjectNames].
-  bool isPropertyOfCurrentIsolate(Element element) {
+  /// Returns true if [element] is stored in the static state holder
+  /// ([staticStateHolder]).  We intend to store only mutable static state
+  /// there, whereas constants are stored in 'C'. Functions, accessors,
+  /// classes, etc. are stored in one of the other objects in
+  /// [reservedGlobalObjectNames].
+  bool _isPropertyOfStaticStateHolder(Element element) {
     // TODO(ahe): Make sure this method's documentation is always true and
     // remove the word "intend".
     return
         // TODO(ahe): Re-write these tests to be positive (so it only returns
         // true for static/top-level mutable fields). Right now, a number of
-        // other elements, such as bound closures also live in [currentIsolate].
+        // other elements, such as bound closures also live in
+        // [staticStateHolder].
         !element.isAccessor &&
         !element.isClass &&
         !element.isTypedef &&
@@ -1332,9 +1334,9 @@
         !element.isLibrary;
   }
 
-  /// Returns [currentIsolate] or one of [reservedGlobalObjectNames].
+  /// Returns [staticStateHolder] or one of [reservedGlobalObjectNames].
   String globalObjectFor(Element element) {
-    if (isPropertyOfCurrentIsolate(element)) return currentIsolate;
+    if (_isPropertyOfStaticStateHolder(element)) return staticStateHolder;
     LibraryElement library = element.library;
     if (library == backend.interceptorsLibrary) return 'J';
     if (library.isInternalLibrary) return 'H';
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 66be56a..d6f02eb 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -134,7 +134,7 @@
       classesNeedingRti.add(cls);
 
       // TODO(ngeoffray): This should use subclasses, not subtypes.
-      Iterable<ClassElement> classes = compiler.world.subtypesOf(cls);
+      Iterable<ClassElement> classes = compiler.world.strictSubtypesOf(cls);
       classes.forEach((ClassElement sub) {
         potentiallyAddForRti(sub);
       });
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 b8fa032..0b9cdb2 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -18,46 +18,29 @@
   final TypeTestRegistry typeTestRegistry;
   NativeEmitter nativeEmitter;
   MetadataCollector metadataCollector;
-  OldEmitter oldEmitter;
   Emitter emitter;
 
-  final Set<ClassElement> neededClasses = new Set<ClassElement>();
-  Set<ClassElement> classesOnlyNeededForRti;
-  final Map<OutputUnit, List<ClassElement>> outputClassLists =
-      new Map<OutputUnit, List<ClassElement>>();
-  final Map<OutputUnit, List<ConstantValue>> outputConstantLists =
-      new Map<OutputUnit, List<ConstantValue>>();
-  final Map<OutputUnit, List<Element>> outputStaticLists =
-      new Map<OutputUnit, List<Element>>();
-  final Map<OutputUnit, List<VariableElement>> outputStaticNonFinalFieldLists =
-      new Map<OutputUnit, List<VariableElement>>();
-  final Map<OutputUnit, Set<LibraryElement>> outputLibraryLists =
-      new Map<OutputUnit, Set<LibraryElement>>();
-
-  /// True, if the output contains a constant list.
-  ///
-  /// This flag is updated in [computeNeededConstants].
-  bool outputContainsConstantList = false;
-
-  final List<ClassElement> nativeClassesAndSubclasses = <ClassElement>[];
-
   /// Records if a type variable is read dynamically for type tests.
   final Set<TypeVariableElement> readTypeVariables =
       new Set<TypeVariableElement>();
 
-  List<TypedefElement> typedefsNeededForReflection;
-
   JavaScriptBackend get backend => compiler.backend;
 
+  @deprecated
+  // This field should be removed. It's currently only needed for dump-info and
+  // tests.
+  // The field is set after the program has been emitted.
+  /// Contains a list of all classes that are emitted.
+  Set<ClassElement> neededClasses;
+
   CodeEmitterTask(Compiler compiler, Namer namer, bool generateSourceMap)
       : super(compiler),
         this.namer = namer,
         this.typeTestRegistry = new TypeTestRegistry(compiler) {
     nativeEmitter = new NativeEmitter(this);
-    oldEmitter = new OldEmitter(compiler, namer, generateSourceMap, this);
     emitter = USE_LAZY_EMITTER
         ? new lazy_js_emitter.Emitter(compiler, namer, nativeEmitter)
-        : oldEmitter;
+        : new full_js_emitter.Emitter(compiler, namer, generateSourceMap, this);
     metadataCollector = new MetadataCollector(compiler, emitter);
   }
 
@@ -134,277 +117,25 @@
     readTypeVariables.add(element);
   }
 
-  Set<ClassElement> computeInterceptorsReferencedFromConstants() {
-    Set<ClassElement> classes = new Set<ClassElement>();
-    JavaScriptConstantCompiler handler = backend.constants;
-    List<ConstantValue> constants = handler.getConstantsForEmission();
-    for (ConstantValue constant in constants) {
-      if (constant is InterceptorConstantValue) {
-        InterceptorConstantValue interceptorConstant = constant;
-        classes.add(interceptorConstant.dispatchedType.element);
-      }
-    }
-    return classes;
-  }
-
-  /**
-   * Return a function that returns true if its argument is a class
-   * that needs to be emitted.
-   */
-  Function computeClassFilter() {
-    if (backend.isTreeShakingDisabled) return (ClassElement cls) => true;
-
-    Set<ClassElement> unneededClasses = new Set<ClassElement>();
-    // The [Bool] class is not marked as abstract, but has a factory
-    // constructor that always throws. We never need to emit it.
-    unneededClasses.add(compiler.boolClass);
-
-    // Go over specialized interceptors and then constants to know which
-    // interceptors are needed.
-    Set<ClassElement> needed = new Set<ClassElement>();
-    backend.specializedGetInterceptors.forEach(
-        (_, Iterable<ClassElement> elements) {
-          needed.addAll(elements);
-        }
-    );
-
-    // Add interceptors referenced by constants.
-    needed.addAll(computeInterceptorsReferencedFromConstants());
-
-    // Add unneeded interceptors to the [unneededClasses] set.
-    for (ClassElement interceptor in backend.interceptedClasses) {
-      if (!needed.contains(interceptor)
-          && interceptor != compiler.objectClass) {
-        unneededClasses.add(interceptor);
-      }
-    }
-
-    // These classes are just helpers for the backend's type system.
-    unneededClasses.add(backend.jsMutableArrayClass);
-    unneededClasses.add(backend.jsFixedArrayClass);
-    unneededClasses.add(backend.jsExtendableArrayClass);
-    unneededClasses.add(backend.jsUInt32Class);
-    unneededClasses.add(backend.jsUInt31Class);
-    unneededClasses.add(backend.jsPositiveIntClass);
-
-    return (ClassElement cls) => !unneededClasses.contains(cls);
-  }
-
-  /**
-   * Compute all the constants that must be emitted.
-   */
-  void computeNeededConstants() {
-    // Make sure we retain all metadata of all elements. This could add new
-    // constants to the handler.
-    if (backend.mustRetainMetadata) {
-      // TODO(floitsch): verify that we don't run through the same elements
-      // multiple times.
-      for (Element element in backend.generatedCode.keys) {
-        if (backend.isAccessibleByReflection(element)) {
-          bool shouldRetainMetadata = backend.retainMetadataOf(element);
-          if (shouldRetainMetadata &&
-              (element.isFunction || element.isConstructor ||
-               element.isSetter)) {
-            FunctionElement function = element;
-            function.functionSignature.forEachParameter(
-                backend.retainMetadataOf);
-          }
-        }
-      }
-      for (ClassElement cls in neededClasses) {
-        final onlyForRti = classesOnlyNeededForRti.contains(cls);
-        if (!onlyForRti) {
-          backend.retainMetadataOf(cls);
-          oldEmitter.classEmitter.visitFields(cls, false,
-              (Element member,
-               jsAst.Name name,
-               jsAst.Name accessorName,
-               bool needsGetter,
-               bool needsSetter,
-               bool needsCheckedSetter) {
-            bool needsAccessor = needsGetter || needsSetter;
-            if (needsAccessor && backend.isAccessibleByReflection(member)) {
-              backend.retainMetadataOf(member);
-            }
-          });
-        }
-      }
-      typedefsNeededForReflection.forEach(backend.retainMetadataOf);
-    }
-
-    JavaScriptConstantCompiler handler = backend.constants;
-    List<ConstantValue> constants = handler.getConstantsForEmission(
-        compiler.hasIncrementalSupport ? null : emitter.compareConstants);
-    for (ConstantValue constant in constants) {
-      if (emitter.isConstantInlinedOrAlreadyEmitted(constant)) continue;
-
-      if (constant.isList) outputContainsConstantList = true;
-
-      OutputUnit constantUnit =
-          compiler.deferredLoadTask.outputUnitForConstant(constant);
-      if (constantUnit == null) {
-        // The back-end introduces some constants, like "InterceptorConstant" or
-        // some list constants. They are emitted in the main output-unit.
-        // TODO(sigurdm): We should track those constants.
-        constantUnit = compiler.deferredLoadTask.mainOutputUnit;
-      }
-      outputConstantLists.putIfAbsent(
-          constantUnit, () => new List<ConstantValue>()).add(constant);
-    }
-  }
-
-  /// Compute all the classes and typedefs that must be emitted.
-  void computeNeededDeclarations(Set<ClassElement> rtiNeededClasses) {
-    // Compute needed typedefs.
-    typedefsNeededForReflection = Elements.sortedByPosition(
-        compiler.world.allTypedefs
-            .where(backend.isAccessibleByReflection)
-            .toList());
-
-    // Compute needed classes.
-    Set<ClassElement> instantiatedClasses =
-        compiler.codegenWorld.directlyInstantiatedClasses
-            .where(computeClassFilter()).toSet();
-
-    void addClassWithSuperclasses(ClassElement cls) {
-      neededClasses.add(cls);
-      for (ClassElement superclass = cls.superclass;
-          superclass != null;
-          superclass = superclass.superclass) {
-        neededClasses.add(superclass);
-      }
-    }
-
-    void addClassesWithSuperclasses(Iterable<ClassElement> classes) {
-      for (ClassElement cls in classes) {
-        addClassWithSuperclasses(cls);
-      }
-    }
-
-    // 1. We need to generate all classes that are instantiated.
-    addClassesWithSuperclasses(instantiatedClasses);
-
-    // 2. Add all classes used as mixins.
-    Set<ClassElement> mixinClasses = neededClasses
-        .where((ClassElement element) => element.isMixinApplication)
-        .map(computeMixinClass)
-        .toSet();
-    neededClasses.addAll(mixinClasses);
-
-    // 3. Find all classes needed for rti.
-    // It is important that this is the penultimate step, at this point,
-    // neededClasses must only contain classes that have been resolved and
-    // codegen'd. The rtiNeededClasses may contain additional classes, but
-    // these are thought to not have been instantiated, so we neeed to be able
-    // to identify them later and make sure we only emit "empty shells" without
-    // fields, etc.
-    classesOnlyNeededForRti = rtiNeededClasses.difference(neededClasses);
-
-    neededClasses.addAll(classesOnlyNeededForRti);
-
-    // TODO(18175, floitsch): remove once issue 18175 is fixed.
-    if (neededClasses.contains(backend.jsIntClass)) {
-      neededClasses.add(compiler.intClass);
-    }
-    if (neededClasses.contains(backend.jsDoubleClass)) {
-      neededClasses.add(compiler.doubleClass);
-    }
-    if (neededClasses.contains(backend.jsNumberClass)) {
-      neededClasses.add(compiler.numClass);
-    }
-    if (neededClasses.contains(backend.jsStringClass)) {
-      neededClasses.add(compiler.stringClass);
-    }
-    if (neededClasses.contains(backend.jsBoolClass)) {
-      neededClasses.add(compiler.boolClass);
-    }
-    if (neededClasses.contains(backend.jsArrayClass)) {
-      neededClasses.add(compiler.listClass);
-    }
-
-    // 4. Finally, sort the classes.
-    List<ClassElement> sortedClasses = Elements.sortedByPosition(neededClasses);
-
-    for (ClassElement element in sortedClasses) {
-      if (Elements.isNativeOrExtendsNative(element) &&
-          !classesOnlyNeededForRti.contains(element)) {
-        // For now, native classes and related classes cannot be deferred.
-        nativeClassesAndSubclasses.add(element);
-        assert(invariant(element,
-                         !compiler.deferredLoadTask.isDeferred(element)));
-        outputClassLists.putIfAbsent(compiler.deferredLoadTask.mainOutputUnit,
-            () => new List<ClassElement>()).add(element);
-      } else {
-        outputClassLists.putIfAbsent(
-            compiler.deferredLoadTask.outputUnitForElement(element),
-            () => new List<ClassElement>())
-            .add(element);
-      }
-    }
-  }
-
-  void computeNeededStatics() {
-    bool isStaticFunction(Element element) =>
-        !element.isInstanceMember && !element.isField;
-
-    Iterable<Element> elements =
-        backend.generatedCode.keys.where(isStaticFunction);
-
-    for (Element element in Elements.sortedByPosition(elements)) {
-      List<Element> list = outputStaticLists.putIfAbsent(
-          compiler.deferredLoadTask.outputUnitForElement(element),
-          () => new List<Element>());
-      list.add(element);
-    }
-  }
-
-  void computeNeededStaticNonFinalFields() {
-    JavaScriptConstantCompiler handler = backend.constants;
-    Iterable<VariableElement> staticNonFinalFields = handler
-        .getStaticNonFinalFieldsForEmission()
-        .where(compiler.codegenWorld.allReferencedStaticFields.contains);
-    for (Element element in Elements.sortedByPosition(staticNonFinalFields)) {
-      List<VariableElement> list = outputStaticNonFinalFieldLists.putIfAbsent(
-            compiler.deferredLoadTask.outputUnitForElement(element),
-            () => new List<VariableElement>());
-      list.add(element);
-    }
-  }
-
-  void computeNeededLibraries() {
-    void addSurroundingLibraryToSet(Element element) {
-      OutputUnit unit = compiler.deferredLoadTask.outputUnitForElement(element);
-      LibraryElement library = element.library;
-      outputLibraryLists.putIfAbsent(unit, () => new Set<LibraryElement>())
-          .add(library);
-    }
-
-    backend.generatedCode.keys.forEach(addSurroundingLibraryToSet);
-    neededClasses.forEach(addSurroundingLibraryToSet);
-  }
-
-  void computeAllNeededEntities() {
+  Set<ClassElement> _finalizeRti() {
     // Compute the required type checks to know which classes need a
     // 'is$' method.
     typeTestRegistry.computeRequiredTypeChecks();
     // Compute the classes needed by RTI.
-    Set<ClassElement> rtiClasses = typeTestRegistry.computeRtiNeededClasses();
-
-    computeNeededDeclarations(rtiClasses);
-    computeNeededConstants();
-    computeNeededStatics();
-    computeNeededStaticNonFinalFields();
-    computeNeededLibraries();
+    return typeTestRegistry.computeRtiNeededClasses();
   }
 
   int assembleProgram() {
     return measure(() {
       emitter.invalidateCaches();
 
-      computeAllNeededEntities();
-
-      ProgramBuilder programBuilder = new ProgramBuilder(compiler, namer, this);
-      return emitter.emitProgram(programBuilder);
+      Set<ClassElement> rtiNeededClasses = _finalizeRti();
+      ProgramBuilder programBuilder = new ProgramBuilder(
+          compiler, namer, this, emitter, rtiNeededClasses);
+      int size = emitter.emitProgram(programBuilder);
+      // TODO(floitsch): we shouldn't need the `neededClasses` anymore.
+      neededClasses = programBuilder.collector.neededClasses;
+      return size;
     });
   }
 }
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/class_builder.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/class_builder.dart
index 4d69d92..6220c4e 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/class_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/class_builder.dart
@@ -2,7 +2,7 @@
 // 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 dart2js.js_emitter;
+part of dart2js.js_emitter.full_emitter;
 
 /**
  * A data structure for collecting fragments of a class definition.
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 3a7ab57..c12637c 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
@@ -2,7 +2,7 @@
 // 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 dart2js.js_emitter;
+part of dart2js.js_emitter.full_emitter;
 
 class ClassEmitter extends CodeEmitterHelper {
 
@@ -358,103 +358,6 @@
     }
   }
 
-  /**
-   * Invokes [f] for each of the fields of [element].
-   *
-   * [element] must be a [ClassElement] or a [LibraryElement].
-   *
-   * If [element] is a [ClassElement], the static fields of the class are
-   * visited if [visitStatics] is true and the instance fields are visited if
-   * [visitStatics] is false.
-   *
-   * If [element] is a [LibraryElement], [visitStatics] must be true.
-   *
-   * When visiting the instance fields of a class, the fields of its superclass
-   * are also visited if the class is instantiated.
-   *
-   * Invariant: [element] must be a declaration element.
-   */
-  void visitFields(Element element, bool visitStatics, AcceptField f) {
-    assert(invariant(element, element.isDeclaration));
-
-    bool isClass = false;
-    bool isLibrary = false;
-    if (element.isClass) {
-      isClass = true;
-    } else if (element.isLibrary) {
-      isLibrary = true;
-      assert(invariant(element, visitStatics));
-    } else {
-      throw new SpannableAssertionFailure(
-          element, 'Expected a ClassElement or a LibraryElement.');
-    }
-
-    // If the class is never instantiated we still need to set it up for
-    // inheritance purposes, but we can simplify its JavaScript constructor.
-    bool isInstantiated =
-        compiler.codegenWorld.directlyInstantiatedClasses.contains(element);
-
-    void visitField(Element holder, FieldElement field) {
-      assert(invariant(element, field.isDeclaration));
-
-      // Keep track of whether or not we're dealing with a field mixin
-      // into a native class.
-      bool isMixinNativeField =
-          isClass && element.isNative && holder.isMixinApplication;
-
-      // See if we can dynamically create getters and setters.
-      // We can only generate getters and setters for [element] since
-      // the fields of super classes could be overwritten with getters or
-      // setters.
-      bool needsGetter = false;
-      bool needsSetter = false;
-      if (isLibrary || isMixinNativeField || holder == element) {
-        needsGetter = fieldNeedsGetter(field);
-        needsSetter = fieldNeedsSetter(field);
-      }
-
-      if ((isInstantiated && !holder.isNative)
-          || needsGetter
-          || needsSetter) {
-        jsAst.Name accessorName = namer.fieldAccessorName(field);
-        jsAst.Name fieldName = namer.fieldPropertyName(field);
-        bool needsCheckedSetter = false;
-        if (compiler.enableTypeAssertions
-            && needsSetter
-            && !canAvoidGeneratedCheckedSetter(field)) {
-          needsCheckedSetter = true;
-          needsSetter = false;
-        }
-        // Getters and setters with suffixes will be generated dynamically.
-        f(field, fieldName, accessorName, needsGetter, needsSetter,
-          needsCheckedSetter);
-      }
-    }
-
-    if (isLibrary) {
-      LibraryElement library = element;
-      library.implementation.forEachLocalMember((Element member) {
-        if (member.isField) visitField(library, member);
-      });
-    } else if (visitStatics) {
-      ClassElement cls = element;
-      cls.implementation.forEachStaticField(visitField);
-    } else {
-      ClassElement cls = element;
-      // TODO(kasperl): We should make sure to only emit one version of
-      // overridden fields. Right now, we rely on the ordering so the
-      // fields pulled in from mixins are replaced with the fields from
-      // the class definition.
-
-      // If a class is not instantiated then we add the field just so we can
-      // generate the field getter/setter dynamically. Since this is only
-      // allowed on fields that are in [element] we don't need to visit
-      // superclasses for non-instantiated classes.
-      cls.implementation.forEachInstanceField(
-          visitField, includeSuperAndInjectedMembers: isInstantiated);
-    }
-  }
-
   void recordMangledField(Element member,
                           jsAst.Name accessorName,
                           String memberName) {
@@ -473,39 +376,6 @@
                      message: '$previousName != ${memberName}'));
   }
 
-  bool fieldNeedsGetter(VariableElement field) {
-    assert(field.isField);
-    if (fieldAccessNeverThrows(field)) return false;
-    if (backend.shouldRetainGetter(field)) return true;
-    return field.isClassMember &&
-           compiler.codegenWorld.hasInvokedGetter(field, compiler.world);
-  }
-
-  bool fieldNeedsSetter(VariableElement field) {
-    assert(field.isField);
-    if (fieldAccessNeverThrows(field)) return false;
-    if (field.isFinal || field.isConst) return false;
-    if (backend.shouldRetainSetter(field)) return true;
-    return field.isClassMember &&
-           compiler.codegenWorld.hasInvokedSetter(field, compiler.world);
-  }
-
-  static bool fieldAccessNeverThrows(VariableElement field) {
-    return
-        // We never access a field in a closure (a captured variable) without
-        // knowing that it is there.  Therefore we don't need to use a getter
-        // (that will throw if the getter method is missing), but can always
-        // access the field directly.
-        field is ClosureFieldElement;
-  }
-
-  bool canAvoidGeneratedCheckedSetter(VariableElement member) {
-    // We never generate accessors for top-level/static fields.
-    if (!member.isInstanceMember) return true;
-    DartType type = member.type;
-    return type.treatAsDynamic || (type.element == compiler.objectClass);
-  }
-
   void generateCheckedSetter(Element member,
                              jsAst.Name fieldName,
                              jsAst.Name accessorName,
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 568e2515..f777014 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
@@ -2,10 +2,10 @@
 // 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 dart2js.js_emitter;
+part of dart2js.js_emitter.full_emitter;
 
 class CodeEmitterHelper {
-  OldEmitter emitter;
+  Emitter emitter;
 
   Namer get namer => emitter.namer;
 
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/container_builder.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/container_builder.dart
index eeff7d5..b0a94ce 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/container_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/container_builder.dart
@@ -2,7 +2,7 @@
 // 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 dart2js.js_emitter;
+part of dart2js.js_emitter.full_emitter;
 
 /// This class should morph into something that makes it easy to build
 /// JavaScript representations of libraries, class-sides, and instance-sides.
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/declarations.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/declarations.dart
index 833abeb..01fda29 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/declarations.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/declarations.dart
@@ -2,7 +2,7 @@
 // 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 dart2js.js_emitter;
+part of dart2js.js_emitter.full_emitter;
 
 /// Enables debugging of fast/slow objects using V8-specific primitives.
 const DEBUG_FAST_OBJECTS = false;
@@ -13,37 +13,6 @@
 typedef jsAst.Property AddPropertyFunction(jsAst.Name name,
                                            jsAst.Expression value);
 
-/**
- * [member] is a field (instance, static, or top level).
- *
- * [name] is the field name that the [Namer] has picked for this field's
- * storage, that is, the JavaScript property name.
- *
- * [accessorName] is the name of the accessor. For instance fields this is
- * mostly the same as [name] except when [member] is shadowing a field in its
- * superclass.  For other fields, they are rarely the same.
- *
- * [needsGetter] and [needsSetter] represent if a getter or a setter
- * respectively is needed.  There are many factors in this, for example, if the
- * accessor can be inlined.
- *
- * [needsCheckedSetter] indicates that a checked getter is needed, and in this
- * case, [needsSetter] is always false. [needsCheckedSetter] is only true when
- * type assertions are enabled (checked mode).
- */
-typedef void AcceptField(VariableElement member,
-                         jsAst.Name name,
-                         jsAst.Name accessorName,
-                         bool needsGetter,
-                         bool needsSetter,
-                         bool needsCheckedSetter);
-
-// Function signatures used in the generation of runtime type information.
-typedef void FunctionTypeSignatureEmitter(Element method,
-                                          FunctionType methodType);
-
-typedef void SubstitutionEmitter(Element element, {bool emitNull});
-
 const String GENERATED_BY = """
 // Generated by dart2js, the Dart to JavaScript compiler.
 """;
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/deferred_output_unit_hash.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/deferred_output_unit_hash.dart
new file mode 100644
index 0000000..8c79a8b
--- /dev/null
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/deferred_output_unit_hash.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2013, 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 dart2js.js_emitter.full_emitter;
+
+class _DeferredOutputUnitHash extends jsAst.DeferredString {
+  String _hash;
+  final OutputUnit _outputUnit;
+
+  _DeferredOutputUnitHash(this._outputUnit);
+
+  void setHash(String hash) {
+    assert(_hash == null);
+    _hash = hash;
+  }
+
+  String get value {
+    assert(_hash != null);
+    return '"$_hash"';
+  }
+
+  String toString() => "HashCode for ${_outputUnit} [$_hash]";
+}
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 ac0bd3a..278e356 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
@@ -2,13 +2,102 @@
 // 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 dart2js.js_emitter;
+library dart2js.js_emitter.full_emitter;
+
+import 'dart:convert';
+import 'dart:collection' show HashMap;
+
+import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames;
+import 'package:js_runtime/shared/embedded_names.dart' show JsBuiltin;
+
+import '../js_emitter.dart' hide Emitter;
+import '../js_emitter.dart' as js_emitter show Emitter;
+
+import '../model.dart';
+import '../program_builder/program_builder.dart';
+
+import '../../common.dart';
+
+import '../../constants/values.dart';
+
+import '../../deferred_load.dart' show OutputUnit;
+
+import '../../elements/elements.dart' show
+    ConstructorBodyElement,
+    ElementKind,
+    FieldElement,
+    ParameterElement,
+    TypeVariableElement,
+    MethodElement,
+    MemberElement;
+
+import '../../hash/sha1.dart' show Hasher;
+
+import '../../io/code_output.dart';
+
+import '../../io/line_column_provider.dart' show
+    LineColumnCollector,
+    LineColumnProvider;
+
+import '../../io/source_map_builder.dart' show
+    SourceMapBuilder;
+
+import '../../js/js.dart' as jsAst;
+import '../../js/js.dart' show js;
+
+import '../../js_backend/js_backend.dart' show
+    CheckedModeHelper,
+    CompoundName,
+    ConstantEmitter,
+    CustomElementsAnalysis,
+    GetterName,
+    JavaScriptBackend,
+    JavaScriptConstantCompiler,
+    Namer,
+    RuntimeTypes,
+    SetterName,
+    Substitution,
+    TypeCheck,
+    TypeChecks,
+    TypeVariableHandler;
+
+import '../../util/characters.dart' show
+    $$,
+    $A,
+    $HASH,
+    $PERIOD,
+    $Z,
+    $a,
+    $z;
+
+import '../../util/uri_extras.dart' show
+    relativize;
+
+import '../../util/util.dart' show
+    NO_LOCATION_SPANNABLE,
+    equalElements;
+
+part 'class_builder.dart';
+part 'class_emitter.dart';
+part 'code_emitter_helper.dart';
+part 'container_builder.dart';
+part 'declarations.dart';
+part 'deferred_output_unit_hash.dart';
+part 'interceptor_emitter.dart';
+part 'nsm_emitter.dart';
+part 'setup_program_builder.dart';
 
 
-class OldEmitter implements Emitter {
+class Emitter implements js_emitter.Emitter {
   final Compiler compiler;
   final CodeEmitterTask task;
 
+  // The following fields will be set to copies of the program-builder's
+  // collector.
+  Map<OutputUnit, List<VariableElement>> outputStaticNonFinalFieldLists;
+  Map<OutputUnit, Set<LibraryElement>> outputLibraryLists;
+  List<TypedefElement> typedefsNeededForReflection;
+
   final ContainerBuilder containerBuilder = new ContainerBuilder();
   final ClassEmitter classEmitter = new ClassEmitter();
   final NsmEmitter nsmEmitter = new NsmEmitter();
@@ -44,9 +133,6 @@
       new HashMap<jsAst.Name, String>();
   final Set<jsAst.Name> recordedMangledNames = new Set<jsAst.Name>();
 
-  List<TypedefElement> get typedefsNeededForReflection =>
-      task.typedefsNeededForReflection;
-
   JavaScriptBackend get backend => compiler.backend;
   TypeVariableHandler get typeVariableHandler => backend.typeVariableHandler;
 
@@ -83,7 +169,7 @@
 
   final bool generateSourceMap;
 
-  OldEmitter(Compiler compiler, Namer namer, this.generateSourceMap, this.task)
+  Emitter(Compiler compiler, Namer namer, this.generateSourceMap, this.task)
       : this.compiler = compiler,
         this.namer = namer,
         cachedEmittedConstants = compiler.cacheStrategy.newSet(),
@@ -524,8 +610,7 @@
       OutputUnit outputUnit) {
     jsAst.Statement buildInitialization(Element element,
                                        jsAst.Expression initialValue) {
-      // Note: `namer.currentIsolate` refers to the isolate properties here.
-      return js.statement('${namer.currentIsolate}.# = #',
+      return js.statement('${namer.staticStateHolder}.# = #',
                           [namer.globalPropertyName(element), initialValue]);
     }
 
@@ -533,7 +618,7 @@
     JavaScriptConstantCompiler handler = backend.constants;
     List<jsAst.Statement> parts = <jsAst.Statement>[];
 
-    Iterable<Element> fields = task.outputStaticNonFinalFieldLists[outputUnit];
+    Iterable<Element> fields = outputStaticNonFinalFieldLists[outputUnit];
     // If the outputUnit does not contain any static non-final fields, then
     // [fields] is `null`.
     if (fields != null) {
@@ -545,10 +630,10 @@
       }
     }
 
-    if (inMainUnit && task.outputStaticNonFinalFieldLists.length > 1) {
+    if (inMainUnit && outputStaticNonFinalFieldLists.length > 1) {
       // In the main output-unit we output a stub initializer for deferred
       // variables, so that `isolateProperties` stays a fast object.
-      task.outputStaticNonFinalFieldLists.forEach(
+      outputStaticNonFinalFieldLists.forEach(
           (OutputUnit fieldsOutputUnit, Iterable<VariableElement> fields) {
         if (fieldsOutputUnit == outputUnit) return;  // Skip the main unit.
         for (Element element in fields) {
@@ -710,8 +795,8 @@
     return js('${namer.isolateName}.#(#)', [makeConstListProperty, array]);
   }
 
-  jsAst.Statement buildMakeConstantList() {
-    if (task.outputContainsConstantList) {
+  jsAst.Statement buildMakeConstantList(bool outputContainsConstantList) {
+    if (outputContainsConstantList) {
       return js.statement(r'''
           // Functions are stored in the hidden class and not as properties in
           // the object. We never actually look at the value, but only want
@@ -758,7 +843,7 @@
     return new jsAst.Block(parts);
   }
 
-  jsAst.Statement buildInitFunction() {
+  jsAst.Statement buildInitFunction(bool outputContainsConstantList) {
     jsAst.Expression allClassesAccess =
         generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES);
     jsAst.Expression getTypeFromNameAccess =
@@ -892,7 +977,7 @@
             'needsLazyInitializer': needsLazyInitializer,
             'lazies': laziesAccess, 'cyclicThrow': cyclicThrow,
             'isolatePropertiesName': namer.isolatePropertiesName,
-            'outputContainsConstantList': task.outputContainsConstantList,
+            'outputContainsConstantList': outputContainsConstantList,
             'makeConstListProperty': makeConstListProperty,
             'functionThatReturnsNullProperty':
                 backend.rti.getFunctionThatReturnsNullName,
@@ -1277,8 +1362,7 @@
 
     checkEverythingEmitted(descriptors.keys);
 
-    Iterable<LibraryElement> libraries =
-        task.outputLibraryLists[mainOutputUnit];
+    Iterable<LibraryElement> libraries = outputLibraryLists[mainOutputUnit];
     if (libraries == null) libraries = <LibraryElement>[];
 
     List<jsAst.Expression> parts = <jsAst.Expression>[];
@@ -1381,7 +1465,7 @@
        // We abuse the short name used for the isolate here to store
        // the isolate properties. This is safe as long as the real isolate
        // object does not exist yet.
-       var ${namer.currentIsolate} = #isolatePropertiesName;
+       var ${namer.staticStateHolder} = #isolatePropertiesName;
 
        // Constants in checked mode call into RTI code to set type information
        // which may need getInterceptor (and one-shot interceptor) methods, so
@@ -1393,7 +1477,7 @@
        // constants to be set up.
        #staticNonFinalInitializers;
 
-       ${namer.currentIsolate} = null;
+       ${namer.staticStateHolder} = null;
 
        #deferredBoilerPlate;
 
@@ -1403,7 +1487,7 @@
 
        #isolateName = $finishIsolateConstructorName(#isolateName);
 
-       ${namer.currentIsolate} = new #isolateName();
+       ${namer.staticStateHolder} = new #isolateName();
 
        #metadata;
 
@@ -1438,7 +1522,8 @@
       "cspPrecompiledFunctions": buildCspPrecompiledFunctionFor(mainOutputUnit),
       "getInterceptorMethods": interceptorEmitter.buildGetInterceptorMethods(),
       "oneShotInterceptors": interceptorEmitter.buildOneShotInterceptors(),
-      "makeConstantList": buildMakeConstantList(),
+      "makeConstantList":
+          buildMakeConstantList(program.outputContainsConstantList),
       "compileTimeConstants":  buildCompileTimeConstants(mainFragment.constants,
                                                          isMainFragment: true),
       "deferredBoilerPlate": buildDeferredBoilerPlate(deferredLoadHashes),
@@ -1453,7 +1538,7 @@
       "convertGlobalObjectsToFastObjects":
           buildConvertGlobalObjectToFastObjects(),
       "debugFastObjects": buildDebugFastObjectCode(),
-      "init": buildInitFunction(),
+      "init": buildInitFunction(program.outputContainsConstantList),
       "main": buildMain(mainFragment.invokeMain)
     }));
 
@@ -1623,8 +1708,7 @@
       Map<Element, ClassBuilder> descriptors = elementDescriptors[fragment];
 
       if (descriptors != null && descriptors.isNotEmpty) {
-        Iterable<LibraryElement> libraries =
-            task.outputLibraryLists[outputUnit];
+        Iterable<LibraryElement> libraries = outputLibraryLists[outputUnit];
         if (libraries == null) libraries = [];
 
         // TODO(johnniwinther): Avoid creating [CodeBuffer]s.
@@ -1654,8 +1738,14 @@
   }
 
   int emitProgram(ProgramBuilder programBuilder) {
-    Program program = programBuilder.buildProgram(
-        storeFunctionTypesInMetadata: true);
+    Program program =
+        programBuilder.buildProgram(storeFunctionTypesInMetadata: true);
+
+    outputStaticNonFinalFieldLists =
+        programBuilder.collector.outputStaticNonFinalFieldLists;
+    outputLibraryLists = programBuilder.collector.outputLibraryLists;
+    typedefsNeededForReflection =
+       programBuilder.collector.typedefsNeededForReflection;
 
     assembleProgram(program);
 
@@ -1710,7 +1800,6 @@
 
   ClassBuilder getElementDescriptor(Element element, Fragment fragment) {
     Element owner = element.library;
-    bool isClass = false;
     if (!element.isLibrary && !element.isTopLevel && !element.isNative) {
       // For static (not top level) elements, record their code in a buffer
       // specific to the class. For now, not supported for native classes and
@@ -1753,7 +1842,7 @@
           // Function for initializing a loaded hunk, given its hash.
           #initializeLoadedHunk = function(hunkHash) {
             $deferredInitializers[hunkHash](
-            #globalsHolder, ${namer.currentIsolate});
+            #globalsHolder, ${namer.staticStateHolder});
             #deferredInitialized[hunkHash] = true;
           };
         }
@@ -1862,9 +1951,9 @@
           ..add(js.statement('${typesAccess}.push.apply(${typesAccess}, '
                              '${namer.deferredTypesName});'));
 
-      // Set the currentIsolate variable to the current isolate (which is
-      // provided as second argument).
-      body.add(js.statement("${namer.currentIsolate} = arguments[1];"));
+      // Sets the static state variable to the state of the current isolate
+      // (which is provided as second argument).
+      body.add(js.statement("${namer.staticStateHolder} = arguments[1];"));
 
       body.add(buildCompileTimeConstants(fragment.constants,
                                          isMainFragment: false));
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 5605aa5..c9132ed 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
@@ -2,7 +2,7 @@
 // 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 dart2js.js_emitter;
+part of dart2js.js_emitter.full_emitter;
 
 class InterceptorEmitter extends CodeEmitterHelper {
   final Set<jsAst.Name> interceptorInvocationNames =
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 5d7df35..7aa34bd 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
@@ -2,7 +2,7 @@
 // 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 dart2js.js_emitter;
+part of dart2js.js_emitter.full_emitter;
 
 class NsmEmitter extends CodeEmitterHelper {
   final List<Selector> trivialNsmHandlers = <Selector>[];
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
index 115ec4f..aa30bd9 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
@@ -2,7 +2,7 @@
 // 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 dart2js.js_emitter;
+part of dart2js.js_emitter.full_emitter;
 
 // TODO(ahe): Share these with js_helper.dart.
 const FUNCTION_INDEX = 0;
@@ -29,7 +29,7 @@
 jsAst.Statement buildSetupProgram(Program program, Compiler compiler,
                                 JavaScriptBackend backend,
                                 Namer namer,
-                                OldEmitter emitter) {
+                                Emitter emitter) {
 
   jsAst.Expression typeInformationAccess =
       emitter.generateEmbeddedGlobalAccess(embeddedNames.TYPE_INFORMATION);
@@ -111,7 +111,7 @@
      'inCspMode': compiler.useContentSecurityPolicy,
      'deferredAction': namer.deferredAction,
      'hasIsolateSupport': program.hasIsolateSupport,
-     'fieldNamesProperty': js.string(OldEmitter.FIELD_NAMES_PROPERTY_NAME),
+     'fieldNamesProperty': js.string(Emitter.FIELD_NAMES_PROPERTY_NAME),
      'hasIncrementalSupport': compiler.hasIncrementalSupport,
      'incrementalHelper': namer.accessIncrementalHelper,
      'createNewIsolateFunction': createNewIsolateFunctionAccess,
diff --git a/pkg/compiler/lib/src/js_emitter/helpers.dart b/pkg/compiler/lib/src/js_emitter/helpers.dart
index a5591ac..017094b 100644
--- a/pkg/compiler/lib/src/js_emitter/helpers.dart
+++ b/pkg/compiler/lib/src/js_emitter/helpers.dart
@@ -12,22 +12,3 @@
   }
   return mixin;
 }
-
-class _DeferredOutputUnitHash extends jsAst.DeferredString {
-  String _hash;
-  final OutputUnit _outputUnit;
-
-  _DeferredOutputUnitHash(this._outputUnit);
-
-  void setHash(String hash) {
-    assert(_hash == null);
-    _hash = hash;
-  }
-
-  String get value {
-    assert(_hash != null);
-    return '"$_hash"';
-  }
-
-  String toString() => "HashCode for ${_outputUnit} [$_hash]";
-}
\ No newline at end of file
diff --git a/pkg/compiler/lib/src/js_emitter/js_emitter.dart b/pkg/compiler/lib/src/js_emitter/js_emitter.dart
index 4049f43..4c642eb 100644
--- a/pkg/compiler/lib/src/js_emitter/js_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/js_emitter.dart
@@ -4,9 +4,6 @@
 
 library dart2js.js_emitter;
 
-import 'dart:convert';
-import 'dart:collection' show HashMap;
-
 import '../common.dart';
 
 import '../constants/values.dart';
@@ -20,8 +17,6 @@
 import '../dart_types.dart' show
     TypedefType;
 
-import '../io/code_output.dart';
-
 import '../elements/elements.dart' show
     ConstructorBodyElement,
     ElementKind,
@@ -31,8 +26,6 @@
     MethodElement,
     MemberElement;
 
-import '../hash/sha1.dart' show Hasher;
-
 import '../js/js.dart' as jsAst;
 import '../js/js.dart' show js;
 
@@ -58,37 +51,16 @@
 import 'program_builder/program_builder.dart';
 
 import 'lazy_emitter/emitter.dart' as lazy_js_emitter;
-
-import '../io/line_column_provider.dart' show
-    LineColumnCollector,
-    LineColumnProvider;
-
-import '../io/source_map_builder.dart' show
-    SourceMapBuilder;
+import 'full_emitter/emitter.dart' as full_js_emitter;
 
 import '../universe/universe.dart' show
     TypeMaskSet,
     TypedSelector;
 
-import '../util/characters.dart' show
-    $$,
-    $A,
-    $HASH,
-    $PERIOD,
-    $Z,
-    $a,
-    $z;
-
 import '../util/util.dart' show
     NO_LOCATION_SPANNABLE,
     Setlet;
 
-import '../util/uri_extras.dart' show
-    relativize;
-
-import '../util/util.dart' show
-    equalElements;
-
 import '../deferred_load.dart' show
     OutputUnit;
 
@@ -96,6 +68,7 @@
 import 'package:js_runtime/shared/embedded_names.dart' show JsBuiltin;
 
 import '../native/native.dart' as native;
+
 part 'class_stub_generator.dart';
 part 'code_emitter_task.dart';
 part 'helpers.dart';
@@ -107,13 +80,3 @@
 part 'parameter_stub_generator.dart';
 part 'runtime_type_generator.dart';
 part 'type_test_registry.dart';
-
-part 'full_emitter/class_builder.dart';
-part 'full_emitter/class_emitter.dart';
-part 'full_emitter/code_emitter_helper.dart';
-part 'full_emitter/container_builder.dart';
-part 'full_emitter/declarations.dart';
-part 'full_emitter/emitter.dart';
-part 'full_emitter/interceptor_emitter.dart';
-part 'full_emitter/nsm_emitter.dart';
-part 'full_emitter/setup_program_builder.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 0c3ae73..e8b7a5d 100644
--- a/pkg/compiler/lib/src/js_emitter/lazy_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/lazy_emitter/emitter.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library dart2js.new_js_emitter.emitter;
+library dart2js.js_emitter.lazy_emitter;
 
 import 'package:js_runtime/shared/embedded_names.dart' show
     JsBuiltin,
@@ -47,13 +47,13 @@
     return _emitter.emitProgram(program);
   }
 
-  // TODO(floitsch): copied from OldEmitter. Adjust or share.
+  // TODO(floitsch): copied from full emitter. Adjust or share.
   @override
   bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) {
     return _emitter.isConstantInlinedOrAlreadyEmitted(constant);
   }
 
-  // TODO(floitsch): copied from OldEmitter. Adjust or share.
+  // TODO(floitsch): copied from full emitter. Adjust or share.
   @override
   int compareConstants(ConstantValue a, ConstantValue b) {
     return _emitter.compareConstants(a, b);
diff --git a/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart
index 6a05e29..ee7030e 100644
--- a/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library dart2js.new_js_emitter.model_emitter;
+library dart2js.js_emitter.lazy_emitter.model_emitter;
 
 import '../../constants/values.dart' show ConstantValue, FunctionConstantValue;
 import '../../dart2jslib.dart' show Compiler;
@@ -83,7 +83,7 @@
     return false;
   }
 
-  // TODO(floitsch): copied from OldEmitter. Adjust or share.
+  // TODO(floitsch): copied from full emitter. Adjust or share.
   int compareConstants(ConstantValue a, ConstantValue b) {
     // Inlined constants don't affect the order and sometimes don't even have
     // names.
@@ -305,7 +305,7 @@
     }
 
     if (program.hasIsolateSupport) {
-      String isolateName = namer.currentIsolate;
+      String isolateName = namer.staticStateHolder;
       globals.add(
           new js.Property(js.string(CREATE_NEW_ISOLATE),
                           js.js('function () { return $isolateName; }')));
diff --git a/pkg/compiler/lib/src/js_emitter/model.dart b/pkg/compiler/lib/src/js_emitter/model.dart
index 6b06eec..b43c51c 100644
--- a/pkg/compiler/lib/src/js_emitter/model.dart
+++ b/pkg/compiler/lib/src/js_emitter/model.dart
@@ -83,7 +83,9 @@
 class Holder {
   final String name;
   final int index;
-  Holder(this.name, this.index);
+  final bool isStaticStateHolder;
+
+  Holder(this.name, this.index, {this.isStaticStateHolder: false});
 }
 
 /**
diff --git a/pkg/compiler/lib/src/js_emitter/native_emitter.dart b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
index 56bb8de..0d90d2f 100644
--- a/pkg/compiler/lib/src/js_emitter/native_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
@@ -6,7 +6,8 @@
 
 class NativeEmitter {
 
-  final Map<Element, ClassBuilder> cachedBuilders;
+  // TODO(floitsch): the native-emitter should not know about ClassBuilders.
+  final Map<Element, full_js_emitter.ClassBuilder> cachedBuilders;
 
   final CodeEmitterTask emitterTask;
 
@@ -61,8 +62,16 @@
    *
    * [classes] contains native classes, mixin applications, and user subclasses
    * of native classes.
+   *
+   * [interceptorClassesNeededByConstants] contains the interceptors that are
+   * referenced by constants.
+   *
+   * [classesModifiedByEmitRTISupport] contains the list of classes that must
+   * exist, because runtime-type support adds information to the class.
    */
-  Set<Class> prepareNativeClasses(List<Class> classes) {
+  Set<Class> prepareNativeClasses(List<Class> classes,
+      Set<ClassElement> interceptorClassesNeededByConstants,
+      Set<ClassElement> classesModifiedByEmitRTISupport) {
     assert(classes.every((Class cls) => cls != null));
 
     hasNativeClasses = classes.isNotEmpty;
@@ -103,11 +112,6 @@
 
     neededClasses.add(objectClass);
 
-    Set<ClassElement> neededByConstant = emitterTask
-        .computeInterceptorsReferencedFromConstants();
-    Set<ClassElement> modifiedClasses = emitterTask.typeTestRegistry
-        .computeClassesModifiedByEmitRuntimeTypeSupport();
-
     for (Class cls in preOrder.reversed) {
       ClassElement classElement = cls.element;
       // Post-order traversal ensures we visit the subclasses before their
@@ -121,9 +125,9 @@
         needed = true;
       } else if (!isTrivialClass(cls)) {
         needed = true;
-      } else if (neededByConstant.contains(classElement)) {
+      } else if (interceptorClassesNeededByConstants.contains(classElement)) {
         needed = true;
-      } else if (modifiedClasses.contains(classElement)) {
+      } else if (classesModifiedByEmitRTISupport.contains(classElement)) {
         // TODO(9556): Remove this test when [emitRuntimeTypeSupport] no longer
         // adds information to a class prototype or constructor.
         needed = true;
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
new file mode 100644
index 0000000..62ba314
--- /dev/null
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
@@ -0,0 +1,313 @@
+// 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.
+
+part of dart2js.js_emitter.program_builder;
+
+/**
+ * Generates the code for all used classes in the program. Static fields (even
+ * in classes) are ignored, since they can be treated as non-class elements.
+ *
+ * The code for the containing (used) methods must exist in the `universe`.
+ */
+class Collector {
+  // TODO(floitsch): the code-emitter task should not need a namer.
+  final Namer namer;
+  final Compiler compiler;
+  final Set<ClassElement> rtiNeededClasses;
+  final Emitter emitter;
+
+  final Set<ClassElement> neededClasses = new Set<ClassElement>();
+  // This field is set in [computeNeededDeclarations].
+  Set<ClassElement> classesOnlyNeededForRti;
+  final Map<OutputUnit, List<ClassElement>> outputClassLists =
+      new Map<OutputUnit, List<ClassElement>>();
+  final Map<OutputUnit, List<ConstantValue>> outputConstantLists =
+      new Map<OutputUnit, List<ConstantValue>>();
+  final Map<OutputUnit, List<Element>> outputStaticLists =
+      new Map<OutputUnit, List<Element>>();
+  final Map<OutputUnit, List<VariableElement>> outputStaticNonFinalFieldLists =
+      new Map<OutputUnit, List<VariableElement>>();
+  final Map<OutputUnit, Set<LibraryElement>> outputLibraryLists =
+      new Map<OutputUnit, Set<LibraryElement>>();
+
+  /// True, if the output contains a constant list.
+  ///
+  /// This flag is updated in [computeNeededConstants].
+  bool outputContainsConstantList = false;
+
+  final List<ClassElement> nativeClassesAndSubclasses = <ClassElement>[];
+
+  List<TypedefElement> typedefsNeededForReflection;
+
+  JavaScriptBackend get backend => compiler.backend;
+
+  Collector(this.compiler, this.namer, this.rtiNeededClasses, this.emitter);
+
+  Set<ClassElement> computeInterceptorsReferencedFromConstants() {
+    Set<ClassElement> classes = new Set<ClassElement>();
+    JavaScriptConstantCompiler handler = backend.constants;
+    List<ConstantValue> constants = handler.getConstantsForEmission();
+    for (ConstantValue constant in constants) {
+      if (constant is InterceptorConstantValue) {
+        InterceptorConstantValue interceptorConstant = constant;
+        classes.add(interceptorConstant.dispatchedType.element);
+      }
+    }
+    return classes;
+  }
+
+  /**
+   * Return a function that returns true if its argument is a class
+   * that needs to be emitted.
+   */
+  Function computeClassFilter() {
+    if (backend.isTreeShakingDisabled) return (ClassElement cls) => true;
+
+    Set<ClassElement> unneededClasses = new Set<ClassElement>();
+    // The [Bool] class is not marked as abstract, but has a factory
+    // constructor that always throws. We never need to emit it.
+    unneededClasses.add(compiler.boolClass);
+
+    // Go over specialized interceptors and then constants to know which
+    // interceptors are needed.
+    Set<ClassElement> needed = new Set<ClassElement>();
+    backend.specializedGetInterceptors.forEach(
+        (_, Iterable<ClassElement> elements) {
+          needed.addAll(elements);
+        }
+    );
+
+    // Add interceptors referenced by constants.
+    needed.addAll(computeInterceptorsReferencedFromConstants());
+
+    // Add unneeded interceptors to the [unneededClasses] set.
+    for (ClassElement interceptor in backend.interceptedClasses) {
+      if (!needed.contains(interceptor)
+          && interceptor != compiler.objectClass) {
+        unneededClasses.add(interceptor);
+      }
+    }
+
+    // These classes are just helpers for the backend's type system.
+    unneededClasses.add(backend.jsMutableArrayClass);
+    unneededClasses.add(backend.jsFixedArrayClass);
+    unneededClasses.add(backend.jsExtendableArrayClass);
+    unneededClasses.add(backend.jsUInt32Class);
+    unneededClasses.add(backend.jsUInt31Class);
+    unneededClasses.add(backend.jsPositiveIntClass);
+
+    return (ClassElement cls) => !unneededClasses.contains(cls);
+  }
+
+  /**
+   * Compute all the constants that must be emitted.
+   */
+  void computeNeededConstants() {
+    // Make sure we retain all metadata of all elements. This could add new
+    // constants to the handler.
+    if (backend.mustRetainMetadata) {
+      // TODO(floitsch): verify that we don't run through the same elements
+      // multiple times.
+      for (Element element in backend.generatedCode.keys) {
+        if (backend.isAccessibleByReflection(element)) {
+          bool shouldRetainMetadata = backend.retainMetadataOf(element);
+          if (shouldRetainMetadata &&
+              (element.isFunction || element.isConstructor ||
+               element.isSetter)) {
+            FunctionElement function = element;
+            function.functionSignature.forEachParameter(
+                backend.retainMetadataOf);
+          }
+        }
+      }
+      for (ClassElement cls in neededClasses) {
+        final onlyForRti = classesOnlyNeededForRti.contains(cls);
+        if (!onlyForRti) {
+          backend.retainMetadataOf(cls);
+          new FieldVisitor(compiler, namer).visitFields(cls, false,
+              (Element member,
+               js.Name name,
+               js.Name accessorName,
+               bool needsGetter,
+               bool needsSetter,
+               bool needsCheckedSetter) {
+            bool needsAccessor = needsGetter || needsSetter;
+            if (needsAccessor && backend.isAccessibleByReflection(member)) {
+              backend.retainMetadataOf(member);
+            }
+          });
+        }
+      }
+      typedefsNeededForReflection.forEach(backend.retainMetadataOf);
+    }
+
+    JavaScriptConstantCompiler handler = backend.constants;
+    List<ConstantValue> constants = handler.getConstantsForEmission(
+        compiler.hasIncrementalSupport ? null : emitter.compareConstants);
+    for (ConstantValue constant in constants) {
+      if (emitter.isConstantInlinedOrAlreadyEmitted(constant)) continue;
+
+      if (constant.isList) outputContainsConstantList = true;
+
+      OutputUnit constantUnit =
+          compiler.deferredLoadTask.outputUnitForConstant(constant);
+      if (constantUnit == null) {
+        // The back-end introduces some constants, like "InterceptorConstant" or
+        // some list constants. They are emitted in the main output-unit.
+        // TODO(sigurdm): We should track those constants.
+        constantUnit = compiler.deferredLoadTask.mainOutputUnit;
+      }
+      outputConstantLists.putIfAbsent(
+          constantUnit, () => new List<ConstantValue>()).add(constant);
+    }
+  }
+
+  /// Compute all the classes and typedefs that must be emitted.
+  void computeNeededDeclarations() {
+    // Compute needed typedefs.
+    typedefsNeededForReflection = Elements.sortedByPosition(
+        compiler.world.allTypedefs
+            .where(backend.isAccessibleByReflection)
+            .toList());
+
+    // Compute needed classes.
+    Set<ClassElement> instantiatedClasses =
+        compiler.codegenWorld.directlyInstantiatedClasses
+            .where(computeClassFilter()).toSet();
+
+    void addClassWithSuperclasses(ClassElement cls) {
+      neededClasses.add(cls);
+      for (ClassElement superclass = cls.superclass;
+          superclass != null;
+          superclass = superclass.superclass) {
+        neededClasses.add(superclass);
+      }
+    }
+
+    void addClassesWithSuperclasses(Iterable<ClassElement> classes) {
+      for (ClassElement cls in classes) {
+        addClassWithSuperclasses(cls);
+      }
+    }
+
+    // 1. We need to generate all classes that are instantiated.
+    addClassesWithSuperclasses(instantiatedClasses);
+
+    // 2. Add all classes used as mixins.
+    Set<ClassElement> mixinClasses = neededClasses
+        .where((ClassElement element) => element.isMixinApplication)
+        .map(computeMixinClass)
+        .toSet();
+    neededClasses.addAll(mixinClasses);
+
+    // 3. Find all classes needed for rti.
+    // It is important that this is the penultimate step, at this point,
+    // neededClasses must only contain classes that have been resolved and
+    // codegen'd. The rtiNeededClasses may contain additional classes, but
+    // these are thought to not have been instantiated, so we neeed to be able
+    // to identify them later and make sure we only emit "empty shells" without
+    // fields, etc.
+    classesOnlyNeededForRti = rtiNeededClasses.difference(neededClasses);
+
+    neededClasses.addAll(classesOnlyNeededForRti);
+
+    // TODO(18175, floitsch): remove once issue 18175 is fixed.
+    if (neededClasses.contains(backend.jsIntClass)) {
+      neededClasses.add(compiler.intClass);
+    }
+    if (neededClasses.contains(backend.jsDoubleClass)) {
+      neededClasses.add(compiler.doubleClass);
+    }
+    if (neededClasses.contains(backend.jsNumberClass)) {
+      neededClasses.add(compiler.numClass);
+    }
+    if (neededClasses.contains(backend.jsStringClass)) {
+      neededClasses.add(compiler.stringClass);
+    }
+    if (neededClasses.contains(backend.jsBoolClass)) {
+      neededClasses.add(compiler.boolClass);
+    }
+    if (neededClasses.contains(backend.jsArrayClass)) {
+      neededClasses.add(compiler.listClass);
+    }
+
+    // 4. Finally, sort the classes.
+    List<ClassElement> sortedClasses = Elements.sortedByPosition(neededClasses);
+
+    for (ClassElement element in sortedClasses) {
+      if (Elements.isNativeOrExtendsNative(element) &&
+          !classesOnlyNeededForRti.contains(element)) {
+        // For now, native classes and related classes cannot be deferred.
+        nativeClassesAndSubclasses.add(element);
+        assert(invariant(element,
+                         !compiler.deferredLoadTask.isDeferred(element)));
+        outputClassLists.putIfAbsent(compiler.deferredLoadTask.mainOutputUnit,
+            () => new List<ClassElement>()).add(element);
+      } else {
+        outputClassLists.putIfAbsent(
+            compiler.deferredLoadTask.outputUnitForElement(element),
+            () => new List<ClassElement>())
+            .add(element);
+      }
+    }
+  }
+
+  void computeNeededStatics() {
+    bool isStaticFunction(Element element) =>
+        !element.isInstanceMember && !element.isField;
+
+    Iterable<Element> elements =
+        backend.generatedCode.keys.where(isStaticFunction);
+
+    for (Element element in Elements.sortedByPosition(elements)) {
+      List<Element> list = outputStaticLists.putIfAbsent(
+          compiler.deferredLoadTask.outputUnitForElement(element),
+          () => new List<Element>());
+      list.add(element);
+    }
+  }
+
+  void computeNeededStaticNonFinalFields() {
+    JavaScriptConstantCompiler handler = backend.constants;
+    addToOutputUnit(Element element) {
+      List<VariableElement> list = outputStaticNonFinalFieldLists.putIfAbsent(
+          compiler.deferredLoadTask.outputUnitForElement(element),
+              () => new List<VariableElement>());
+      list.add(element);
+    }
+
+    Iterable<VariableElement> staticNonFinalFields = handler
+        .getStaticNonFinalFieldsForEmission()
+        .where(compiler.codegenWorld.allReferencedStaticFields.contains);
+
+    Elements.sortedByPosition(staticNonFinalFields).forEach(addToOutputUnit);
+
+    // We also need to emit static const fields if they are available for
+    // reflection.
+    compiler.codegenWorld.allReferencedStaticFields
+        .where((FieldElement field) => field.isConst)
+        .where(backend.isAccessibleByReflection)
+        .forEach(addToOutputUnit);
+  }
+
+  void computeNeededLibraries() {
+    void addSurroundingLibraryToSet(Element element) {
+      OutputUnit unit = compiler.deferredLoadTask.outputUnitForElement(element);
+      LibraryElement library = element.library;
+      outputLibraryLists.putIfAbsent(unit, () => new Set<LibraryElement>())
+          .add(library);
+    }
+
+    backend.generatedCode.keys.forEach(addSurroundingLibraryToSet);
+    neededClasses.forEach(addSurroundingLibraryToSet);
+  }
+
+  void collect() {
+    computeNeededDeclarations();
+    computeNeededConstants();
+    computeNeededStatics();
+    computeNeededStaticNonFinalFields();
+    computeNeededLibraries();
+  }
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..0388bc9
--- /dev/null
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
@@ -0,0 +1,170 @@
+// 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.
+
+part of dart2js.js_emitter.program_builder;
+
+/**
+ * [member] is a field (instance, static, or top level).
+ *
+ * [name] is the field name that the [Namer] has picked for this field's
+ * storage, that is, the JavaScript property name.
+ *
+ * [accessorName] is the name of the accessor. For instance fields this is
+ * mostly the same as [name] except when [member] is shadowing a field in its
+ * superclass.  For other fields, they are rarely the same.
+ *
+ * [needsGetter] and [needsSetter] represent if a getter or a setter
+ * respectively is needed.  There are many factors in this, for example, if the
+ * accessor can be inlined.
+ *
+ * [needsCheckedSetter] indicates that a checked getter is needed, and in this
+ * case, [needsSetter] is always false. [needsCheckedSetter] is only true when
+ * type assertions are enabled (checked mode).
+ */
+typedef void AcceptField(VariableElement member,
+                         js.Name name,
+                         js.Name accessorName,
+                         bool needsGetter,
+                         bool needsSetter,
+                         bool needsCheckedSetter);
+
+
+class FieldVisitor {
+  final Compiler compiler;
+  final Namer namer;
+
+  JavaScriptBackend get backend => compiler.backend;
+
+  FieldVisitor(this.compiler, this.namer);
+
+  /**
+   * Invokes [f] for each of the fields of [element].
+   *
+   * [element] must be a [ClassElement] or a [LibraryElement].
+   *
+   * If [element] is a [ClassElement], the static fields of the class are
+   * visited if [visitStatics] is true and the instance fields are visited if
+   * [visitStatics] is false.
+   *
+   * If [element] is a [LibraryElement], [visitStatics] must be true.
+   *
+   * When visiting the instance fields of a class, the fields of its superclass
+   * are also visited if the class is instantiated.
+   *
+   * Invariant: [element] must be a declaration element.
+   */
+  void visitFields(Element element, bool visitStatics, AcceptField f) {
+    assert(invariant(element, element.isDeclaration));
+
+    bool isClass = false;
+    bool isLibrary = false;
+    if (element.isClass) {
+      isClass = true;
+    } else if (element.isLibrary) {
+      isLibrary = true;
+      assert(invariant(element, visitStatics));
+    } else {
+      throw new SpannableAssertionFailure(
+          element, 'Expected a ClassElement or a LibraryElement.');
+    }
+
+    // If the class is never instantiated we still need to set it up for
+    // inheritance purposes, but we can simplify its JavaScript constructor.
+    bool isInstantiated =
+        compiler.codegenWorld.directlyInstantiatedClasses.contains(element);
+
+    void visitField(Element holder, FieldElement field) {
+      assert(invariant(element, field.isDeclaration));
+
+      // Keep track of whether or not we're dealing with a field mixin
+      // into a native class.
+      bool isMixinNativeField =
+          isClass && element.isNative && holder.isMixinApplication;
+
+      // See if we can dynamically create getters and setters.
+      // We can only generate getters and setters for [element] since
+      // the fields of super classes could be overwritten with getters or
+      // setters.
+      bool needsGetter = false;
+      bool needsSetter = false;
+      if (isLibrary || isMixinNativeField || holder == element) {
+        needsGetter = fieldNeedsGetter(field);
+        needsSetter = fieldNeedsSetter(field);
+      }
+
+      if ((isInstantiated && !holder.isNative)
+          || needsGetter
+          || needsSetter) {
+        js.Name accessorName = namer.fieldAccessorName(field);
+        js.Name fieldName = namer.fieldPropertyName(field);
+        bool needsCheckedSetter = false;
+        if (compiler.enableTypeAssertions
+            && needsSetter
+            && !canAvoidGeneratedCheckedSetter(field)) {
+          needsCheckedSetter = true;
+          needsSetter = false;
+        }
+        // Getters and setters with suffixes will be generated dynamically.
+        f(field, fieldName, accessorName, needsGetter, needsSetter,
+            needsCheckedSetter);
+      }
+    }
+
+    if (isLibrary) {
+      LibraryElement library = element;
+      library.implementation.forEachLocalMember((Element member) {
+        if (member.isField) visitField(library, member);
+      });
+    } else if (visitStatics) {
+      ClassElement cls = element;
+      cls.implementation.forEachStaticField(visitField);
+    } else {
+      ClassElement cls = element;
+      // TODO(kasperl): We should make sure to only emit one version of
+      // overridden fields. Right now, we rely on the ordering so the
+      // fields pulled in from mixins are replaced with the fields from
+      // the class definition.
+
+      // If a class is not instantiated then we add the field just so we can
+      // generate the field getter/setter dynamically. Since this is only
+      // allowed on fields that are in [element] we don't need to visit
+      // superclasses for non-instantiated classes.
+      cls.implementation.forEachInstanceField(
+          visitField, includeSuperAndInjectedMembers: isInstantiated);
+    }
+  }
+
+  bool fieldNeedsGetter(VariableElement field) {
+    assert(field.isField);
+    if (fieldAccessNeverThrows(field)) return false;
+    if (backend.shouldRetainGetter(field)) return true;
+    return field.isClassMember &&
+    compiler.codegenWorld.hasInvokedGetter(field, compiler.world);
+  }
+
+  bool fieldNeedsSetter(VariableElement field) {
+    assert(field.isField);
+    if (fieldAccessNeverThrows(field)) return false;
+    if (field.isFinal || field.isConst) return false;
+    if (backend.shouldRetainSetter(field)) return true;
+    return field.isClassMember &&
+    compiler.codegenWorld.hasInvokedSetter(field, compiler.world);
+  }
+
+  static bool fieldAccessNeverThrows(VariableElement field) {
+    return
+      // We never access a field in a closure (a captured variable) without
+      // knowing that it is there.  Therefore we don't need to use a getter
+      // (that will throw if the getter method is missing), but can always
+      // access the field directly.
+      field is ClosureFieldElement;
+  }
+
+  bool canAvoidGeneratedCheckedSetter(VariableElement member) {
+    // We never generate accessors for top-level/static fields.
+    if (!member.isInstanceMember) return true;
+    DartType type = member.type;
+    return type.treatAsDynamic || (type.element == compiler.objectClass);
+  }
+}
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 b4a9c37..deadcb7 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
@@ -4,10 +4,11 @@
 
 library dart2js.js_emitter.program_builder;
 
-import '../js_emitter.dart' show computeMixinClass;
+import '../js_emitter.dart' show computeMixinClass, Emitter;
 import '../model.dart';
 
 import '../../common.dart';
+import '../../closure.dart' show ClosureFieldElement;
 import '../../js/js.dart' as js;
 
 import '../../js_backend/js_backend.dart' show
@@ -24,12 +25,17 @@
     RuntimeTypeGenerator,
     TypeTestProperties;
 
-import '../../elements/elements.dart' show ParameterElement, MethodElement;
+import '../../elements/elements.dart' show
+    FieldElement,
+    MethodElement,
+    ParameterElement;
 
 import '../../universe/universe.dart' show Universe, TypeMaskSet;
 import '../../deferred_load.dart' show DeferredLoadTask, OutputUnit;
 
+part 'collector.dart';
 part 'registry.dart';
+part 'field_visitor.dart';
 
 /// Builds a self-contained representation of the program that can then be
 /// emitted more easily by the individual emitters.
@@ -38,15 +44,27 @@
   final Namer namer;
   final CodeEmitterTask _task;
 
+  /// Contains the collected information the program builder used to build
+  /// the model.
+  // The collector will be filled on the first call to `buildProgram`.
+  // It is stored and publicly exposed for backwards compatibility. New code
+  // (and in particular new emitters) should not use it.
+  final Collector collector;
+
   final Registry _registry;
 
   /// True if the program should store function types in the metadata.
   bool _storeFunctionTypesInMetadata = false;
 
   ProgramBuilder(Compiler compiler,
-                 this.namer,
-                 this._task)
+                 Namer namer,
+                 this._task,
+                 Emitter emitter,
+                 Set<ClassElement> rtiNeededClasses)
       : this._compiler = compiler,
+        this.namer = namer,
+        this.collector =
+            new Collector(compiler, namer, rtiNeededClasses, emitter),
         this._registry = new Registry(compiler);
 
   JavaScriptBackend get backend => _compiler.backend;
@@ -67,25 +85,28 @@
   Set<Class> _unneededNativeClasses;
 
   Program buildProgram({bool storeFunctionTypesInMetadata: false}) {
+    collector.collect();
+
     this._storeFunctionTypesInMetadata = storeFunctionTypesInMetadata;
     // Note: In rare cases (mostly tests) output units can be empty. This
     // happens when the deferred code is dead-code eliminated but we still need
     // to check that the library has been loaded.
     _compiler.deferredLoadTask.allOutputUnits.forEach(
         _registry.registerOutputUnit);
-    _task.outputClassLists.forEach(_registry.registerElements);
-    _task.outputStaticLists.forEach(_registry.registerElements);
-    _task.outputConstantLists.forEach(_registerConstants);
-    _task.outputStaticNonFinalFieldLists.forEach(_registry.registerElements);
+    collector.outputClassLists.forEach(_registry.registerElements);
+    collector.outputStaticLists.forEach(_registry.registerElements);
+    collector.outputConstantLists.forEach(_registerConstants);
+    collector.outputStaticNonFinalFieldLists.forEach(
+        _registry.registerElements);
 
-    // TODO(kasperl): There's code that implicitly needs access to the special
-    // $ holder so we have to register that. Can we track if we have to?
-    _registry.registerHolder(r'$');
+    // We always add the current isolate holder.
+    _registry.registerHolder(
+        namer.staticStateHolder, isStaticStateHolder: true);
 
     // We need to run the native-preparation before we build the output. The
     // preparation code, in turn needs the classes to be set up.
     // We thus build the classes before building their containers.
-    _task.outputClassLists.forEach((OutputUnit _, List<ClassElement> classes) {
+    collector.outputClassLists.forEach((OutputUnit _, List<ClassElement> classes) {
       classes.forEach(_buildClass);
     });
 
@@ -101,12 +122,19 @@
       }
     });
 
-    List<Class> nativeClasses = _task.nativeClassesAndSubclasses
+    List<Class> nativeClasses = collector.nativeClassesAndSubclasses
         .map((ClassElement classElement) => _classes[classElement])
         .toList();
 
-    _unneededNativeClasses =
-        _task.nativeEmitter.prepareNativeClasses(nativeClasses);
+    Set<ClassElement> interceptorClassesNeededByConstants =
+        collector.computeInterceptorsReferencedFromConstants();
+    Set<ClassElement> classesModifiedByEmitRTISupport =
+        _task.typeTestRegistry.computeClassesModifiedByEmitRuntimeTypeSupport();
+
+
+    _unneededNativeClasses = _task.nativeEmitter.prepareNativeClasses(
+        nativeClasses, interceptorClassesNeededByConstants,
+        classesModifiedByEmitRTISupport);
 
     MainFragment mainFragment = _buildMainFragment(_registry.mainLibrariesMap);
     Iterable<Fragment> deferredFragments =
@@ -139,7 +167,7 @@
         _task.metadataCollector,
         finalizers,
         needsNativeSupport: needsNativeSupport,
-        outputContainsConstantList: _task.outputContainsConstantList,
+        outputContainsConstantList: collector.outputContainsConstantList,
         hasIsolateSupport: _compiler.hasIsolateSupport);
   }
 
@@ -200,7 +228,7 @@
 
   List<Constant> _buildConstants(LibrariesMap librariesMap) {
     List<ConstantValue> constantValues =
-        _task.outputConstantLists[librariesMap.outputUnit];
+        collector.outputConstantLists[librariesMap.outputUnit];
     if (constantValues == null) return const <Constant>[];
     return constantValues.map((ConstantValue value) => _constants[value])
         .toList(growable: false);
@@ -208,7 +236,7 @@
 
   List<StaticField> _buildStaticNonFinalFields(LibrariesMap librariesMap) {
     List<VariableElement> staticNonFinalFields =
-         _task.outputStaticNonFinalFieldLists[librariesMap.outputUnit];
+         collector.outputStaticNonFinalFieldLists[librariesMap.outputUnit];
     if (staticNonFinalFields == null) return const <StaticField>[];
 
     return staticNonFinalFields
@@ -325,7 +353,7 @@
   }
 
   Class _buildClass(ClassElement element) {
-    bool onlyForRti = _task.classesOnlyNeededForRti.contains(element);
+    bool onlyForRti = collector.classesOnlyNeededForRti.contains(element);
 
     List<Method> methods = [];
     List<StubMethod> callStubs = <StubMethod>[];
@@ -638,7 +666,7 @@
 
   List<Field> _buildFields(Element holder, bool visitStatics) {
     List<Field> fields = <Field>[];
-    _task.oldEmitter.classEmitter.visitFields(
+    new FieldVisitor(_compiler, namer).visitFields(
         holder, visitStatics, (VariableElement field,
                                js.Name name,
                                js.Name accessorName,
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/registry.dart b/pkg/compiler/lib/src/js_emitter/program_builder/registry.dart
index ab7aa52..2fe3e12 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/registry.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/registry.dart
@@ -113,9 +113,10 @@
     // Ignore for now.
   }
 
-  Holder registerHolder(String name) {
-    return _holdersMap.putIfAbsent(
-        name,
-        () => new Holder(name, _holdersMap.length));
+  Holder registerHolder(String name, {bool isStaticStateHolder: false}) {
+    return _holdersMap.putIfAbsent(name, () {
+      return new Holder(name, _holdersMap.length,
+          isStaticStateHolder: isStaticStateHolder);
+    });
   }
 }
diff --git a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
index 52c4352..b5e1a57 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -4,6 +4,12 @@
 
 part of dart2js.js_emitter;
 
+// Function signatures used in the generation of runtime type information.
+typedef void FunctionTypeSignatureEmitter(Element method,
+                                          FunctionType methodType);
+
+typedef void SubstitutionEmitter(Element element, {bool emitNull});
+
 class TypeTestProperties {
   /// The index of the function type into the metadata.
   ///
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index 9719345..96961f3 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -46,7 +46,12 @@
   Scope scope;
   ClassElement currentClass;
   ExpressionStatement currentExpressionStatement;
+
+  /// `true` if a [Send] or [SendSet] is visited as the prefix of member access.
+  /// For instance `Class` in `Class.staticField` or `prefix.Class` in
+  /// `prefix.Class.staticMethod()`.
   bool sendIsMemberAccess = false;
+
   StatementScope statementScope;
   int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION
       | ElementCategory.IMPLIES_TYPE;
@@ -1332,7 +1337,7 @@
       if (leftResult.isConstant && rightResult.isConstant) {
         bool isValidConstant;
         ConstantExpression leftConstant = leftResult.constant;
-        ConstantExpression rightConstant = leftResult.constant;
+        ConstantExpression rightConstant = rightResult.constant;
         DartType knownLeftType = leftConstant.getKnownType(coreTypes);
         DartType knownRightType = rightConstant.getKnownType(coreTypes);
         switch (operator.kind) {
@@ -1770,16 +1775,197 @@
     }
   }
 
+  /// Handle access to a type literal of type variable [element]. Like `T` or
+  /// `T()` where 'T' is type variable.
+  // TODO(johnniwinther): Remove [name] when [Selector] is not required for the
+  // the [GetStructure].
+  // TODO(johnniwinther): Remove [element] when it is no longer needed for
+  // evaluating constants.
+  ResolutionResult handleTypeVariableTypeLiteralAccess(
+      Send node,
+      Name name,
+      TypeVariableElement element) {
+    if (!Elements.hasAccessToTypeVariables(enclosingElement)) {
+      compiler.reportError(node,
+          MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
+          {'typeVariableName': node.selector});
+      // TODO(johnniwinther): Add another access semantics for this.
+    }
+    registry.registerClassUsingVariableExpression(element.enclosingClass);
+    registry.registerTypeVariableExpression();
+
+    AccessSemantics semantics =
+        new StaticAccess.typeParameterTypeLiteral(element);
+    registry.useElement(node, element);
+    registry.registerTypeLiteral(node, element.type);
+
+    if (node.isCall) {
+      CallStructure callStructure =
+          resolveArguments(node.argumentsNode).callStructure;
+      Selector selector = callStructure.callSelector;
+      // TODO(johnniwinther): Remove this when all information goes through
+      // the [SendStructure].
+      registry.setSelector(node, selector);
+
+      registry.registerSendStructure(node,
+          new InvokeStructure(semantics, selector));
+    } else {
+      // TODO(johnniwinther): Avoid the need for a [Selector] here.
+      registry.registerSendStructure(node,
+          new GetStructure(semantics,
+              new Selector(SelectorKind.GETTER, name, CallStructure.NO_ARGS)));
+    }
+    return const NoneResult();
+  }
+
+  /// Handle access to a constant type literal of [type].
+  // TODO(johnniwinther): Remove [name] when [Selector] is not required for the
+  // the [GetStructure].
+  // TODO(johnniwinther): Remove [element] when it is no longer needed for
+  // evaluating constants.
+  ResolutionResult handleConstantTypeLiteralAccess(
+      Send node,
+      Name name,
+      TypeDeclarationElement element,
+      DartType type,
+      ConstantAccess semantics) {
+    registry.useElement(node, element);
+    registry.registerTypeLiteral(node, type);
+
+    if (node.isCall) {
+      CallStructure callStructure =
+          resolveArguments(node.argumentsNode).callStructure;
+      Selector selector = callStructure.callSelector;
+      // TODO(johnniwinther): Remove this when all information goes through
+      // the [SendStructure].
+      registry.setSelector(node, selector);
+
+      // The node itself is not a constant but we register the selector (the
+      // identifier that refers to the class/typedef) as a constant.
+      registry.useElement(node.selector, element);
+      analyzeConstantDeferred(node.selector, enforceConst: false);
+
+      registry.registerSendStructure(node,
+          new InvokeStructure(semantics, selector));
+      return const NoneResult();
+    } else {
+      analyzeConstantDeferred(node, enforceConst: false);
+
+      // TODO(johnniwinther): Avoid the need for a [Selector] here.
+      registry.registerSendStructure(node,
+          new GetStructure(semantics,
+              new Selector(SelectorKind.GETTER, name, CallStructure.NO_ARGS)));
+      return new ConstantResult(node, semantics.constant);
+    }
+  }
+
+  /// Handle access to a type literal of a typedef. Like `F` or
+  /// `F()` where 'F' is typedef.
+  ResolutionResult handleTypedefTypeLiteralAccess(
+      Send node,
+      Name name,
+      TypedefElement typdef) {
+    typdef.ensureResolved(compiler);
+    DartType type = typdef.rawType;
+    ConstantExpression constant = new TypeConstantExpression(type);
+    AccessSemantics semantics = new ConstantAccess.typedefTypeLiteral(constant);
+    return handleConstantTypeLiteralAccess(node, name, typdef, type, semantics);
+  }
+
+  /// Handle access to a type literal of the type 'dynamic'. Like `dynamic` or
+  /// `dynamic()`.
+  ResolutionResult handleDynamicTypeLiteralAccess(Send node) {
+    DartType type = const DynamicType();
+    ConstantExpression constant = new TypeConstantExpression(
+        // TODO(johnniwinther): Use [type] when evaluation of constants is done
+        // directly on the constant expressions.
+        node.isCall ? coreTypes.typeType : type);
+    AccessSemantics semantics = new ConstantAccess.dynamicTypeLiteral(constant);
+    return handleConstantTypeLiteralAccess(
+        node, const PublicName('dynamic'), compiler.typeClass, type, semantics);
+  }
+
+  /// Handle access to a type literal of a class. Like `C` or
+  /// `C()` where 'C' is class.
+  ResolutionResult handleClassTypeLiteralAccess(
+      Send node,
+      Name name,
+      ClassElement cls) {
+    DartType type = cls.rawType;
+    ConstantExpression constant = new TypeConstantExpression(type);
+    AccessSemantics semantics = new ConstantAccess.classTypeLiteral(constant);
+    return handleConstantTypeLiteralAccess(node, name, cls, type, semantics);
+  }
+
+  /// Handle a [Send] that resolves to a [prefix]. Like `prefix` in
+  /// `prefix.Class` or `prefix` in `prefix()`, the latter being a compile time
+  /// error.
+  ResolutionResult handleClassSend(
+      Send node,
+      Name name,
+      ClassElement cls) {
+    cls.ensureResolved(compiler);
+    if (sendIsMemberAccess) {
+      registry.useElement(node, cls);
+      return new ElementResult(cls);
+    } else {
+      // `C` or `C()` where 'C' is a class.
+      return handleClassTypeLiteralAccess(node, name, cls);
+    }
+  }
+
+  /// Handle qualified [Send] where the receiver resolves to a [prefix],
+  /// like `prefix.toplevelFunction()` or `prefix.Class.staticField` where
+  /// `prefix` is a library prefix.
+  ResolutionResult handleLibraryPrefixSend(
+      Send node, PrefixElement prefix, Name name) {
+    Element member = prefix.lookupLocalMember(name.text);
+    if (member == null) {
+      registry.registerThrowNoSuchMethod();
+      Element error = reportAndCreateErroneousElement(
+          node, name.text, MessageKind.NO_SUCH_LIBRARY_MEMBER,
+          {'libraryName': prefix.name, 'memberName': name});
+      registry.useElement(node, error);
+      return new ElementResult(error);
+    } else {
+      return handleResolvedSend(node, name, member);
+    }
+  }
+
+  /// Handle a [Send] that resolves to a [prefix]. Like `prefix` in
+  /// `prefix.Class` or `prefix` in `prefix()`, the latter being a compile time
+  /// error.
+  ResolutionResult handleLibraryPrefix(
+      Send node,
+      Name name,
+      PrefixElement prefix) {
+    if ((ElementCategory.PREFIX & allowedCategory) == 0) {
+      compiler.reportError(
+          node,
+          MessageKind.PREFIX_AS_EXPRESSION,
+          {'prefix': name});
+      return const NoneResult();
+    }
+    if (prefix.isDeferred) {
+      // TODO(johnniwinther): Remove this when deferred access is detected
+      // through a [SendStructure].
+      registry.useElement(node.selector, prefix);
+    }
+    registry.useElement(node, prefix);
+    return new ElementResult(prefix);
+  }
+
   /// Handle qualified [Send] where the receiver resolves to an [Element], like
   /// `a.b` where `a` is a local, field, class, or prefix, etc.
   ResolutionResult handleResolvedQualifiedSend(
       Send node, Name name, Element element) {
     if (element.isPrefix) {
-      return oldVisitSend(node);
+      return handleLibraryPrefixSend(node, element, name);
     } else if (element.isClass) {
       return handleStaticMemberAccess(node, name, element);
     }
-    return oldVisitSend(node);
+    // TODO(johnniwinther): Use the [element].
+    return handleDynamicPropertyAccess(node, name);
   }
 
   /// Handle dynamic access of [semantics].
@@ -1909,15 +2095,13 @@
       Name name,
       AmbiguousElement element) {
 
-    compiler.reportError(
-        node, element.messageKind, element.messageArguments);
-    element.diagnose(enclosingElement, compiler);
-
-    ErroneousElement error = new ErroneousElementX(
-        element.messageKind,
-        element.messageArguments,
+    ErroneousElement error = reportAndCreateErroneousElement(
+        node,
         name.text,
-        enclosingElement);
+        element.messageKind,
+        element.messageArguments);
+    element.diagnose(enclosingElement, compiler);
+    registry.registerThrowNoSuchMethod();
 
     // TODO(johnniwinther): Support ambiguous access as an [AccessSemantics].
     AccessSemantics accessSemantics = new StaticAccess.unresolved(error);
@@ -2055,6 +2239,15 @@
     // of parse errors to make [element] erroneous. Fix this!
     member.computeType(compiler);
 
+
+    if (member == compiler.mirrorSystemGetNameFunction &&
+        !compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) {
+      compiler.reportHint(
+          node.selector, MessageKind.STATIC_FUNCTION_BLOAT,
+          {'class': compiler.mirrorSystemClass.name,
+           'name': compiler.mirrorSystemGetNameFunction.name});
+    }
+
     Selector selector;
     AccessSemantics semantics =
         computeStaticOrTopLevelAccessSemantics(node, member);
@@ -2187,12 +2380,16 @@
         return handleStaticInstanceSend(node, name, element);
       }
     }
-    if (element.isClass || element.isTypedef) {
-      return oldVisitSend(node);
+    if (element.isClass) {
+      // `C`, `C()`, or 'C.b` where 'C' is a class.
+      return handleClassSend(node, name, element);
+    } else if (element.isTypedef) {
+      // `F` or `F()` where 'F' is a typedef.
+      return handleTypedefTypeLiteralAccess(node, name, element);
     } else if (element.isTypeVariable) {
-      return oldVisitSend(node);
+      return handleTypeVariableTypeLiteralAccess(node, name, element);
     } else if (element.isPrefix) {
-      return oldVisitSend(node);
+      return handleLibraryPrefix(node, name, element);
     } else if (element.isLocal) {
       return handleLocalAccess(node, name, element);
     } else if (element.isStatic || element.isTopLevel) {
@@ -2216,16 +2413,16 @@
     } else if (text == 'this') {
       // `this()`.
       return handleThisAccess(node);
-    } else if (text == 'dynamic') {
-      // `dynamic` || `dynamic()`.
-      // TODO(johnniwinther): Handle dynamic type literal access.
-      return oldVisitSend(node);
     }
     // `name` or `name()`
     Name name = new Name(text, enclosingElement.library);
     Element element = lookupInScope(compiler, node, scope, text);
     if (element == null) {
-      if (inInstanceContext) {
+      if (text == 'dynamic') {
+        // `dynamic` or `dynamic()` where 'dynamic' is not declared in the
+        // current scope.
+        return handleDynamicTypeLiteralAccess(node);
+      } else if (inInstanceContext) {
         // Implicitly `this.name`.
         return handleThisPropertyAccess(node, name);
       } else {
@@ -2262,101 +2459,6 @@
     }
   }
 
-  ResolutionResult oldVisitSend(Send node) {
-    bool oldSendIsMemberAccess = sendIsMemberAccess;
-    sendIsMemberAccess = node.isPropertyAccess || node.isCall;
-
-    ResolutionResult result = resolveSend(node);
-    sendIsMemberAccess = oldSendIsMemberAccess;
-
-    Element target = result.element;
-
-    if (target != null
-        && target == compiler.mirrorSystemGetNameFunction
-        && !compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) {
-      compiler.reportHint(
-          node.selector, MessageKind.STATIC_FUNCTION_BLOAT,
-          {'class': compiler.mirrorSystemClass.name,
-           'name': compiler.mirrorSystemGetNameFunction.name});
-    }
-
-    if (target != null) {
-      if (target.isErroneous) {
-        registry.registerThrowNoSuchMethod();
-      } else if (target.isAbstractField) {
-        AbstractFieldElement field = target;
-        target = field.getter;
-        if (target == null) {
-          if (!inInstanceContext || field.isTopLevel || field.isStatic) {
-            registry.registerThrowNoSuchMethod();
-            target = reportAndCreateErroneousElement(node.selector, field.name,
-                MessageKind.CANNOT_RESOLVE_GETTER, const {});
-          }
-        }
-      } else if (target.isTypeVariable) {
-        ClassElement cls = target.enclosingClass;
-        assert(enclosingElement.enclosingClass == cls);
-        if (!Elements.hasAccessToTypeVariables(enclosingElement)) {
-          compiler.reportError(node,
-              MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
-              {'typeVariableName': node.selector});
-        }
-        registry.registerClassUsingVariableExpression(cls);
-        registry.registerTypeVariableExpression();
-        registerTypeLiteralAccess(node, target);
-      } else if (target.impliesType && (!sendIsMemberAccess || node.isCall)) {
-        registerTypeLiteralAccess(node, target);
-      }
-      registerPotentialAccessInClosure(node, target);
-    }
-
-    resolveArguments(node.argumentsNode);
-
-    // If the selector is null, it means that we will not be generating
-    // code for this as a send.
-    Selector selector = registry.getSelector(node);
-    if (selector == null) return const NoneResult();
-
-    if (node.isCall) {
-      if (Elements.isUnresolved(target) ||
-          target.isGetter ||
-          target.isField ||
-          Elements.isClosureSend(node, target)) {
-        // If we don't know what we're calling or if we are calling a getter,
-        // we need to register that fact that we may be calling a closure
-        // with the same arguments.
-        Selector call = new Selector.callClosureFrom(selector);
-        registry.registerDynamicInvocation(
-            new UniverseSelector(selector, null));
-      } else if (target.impliesType) {
-        // We call 'call()' on a Type instance returned from the reference to a
-        // class or typedef literal. We do not need to register this call as a
-        // dynamic invocation, because we statically know what the target is.
-      } else {
-        if (target is FunctionElement) {
-          FunctionElement function = target;
-          function.computeType(compiler);
-        }
-        if (!selector.applies(target, compiler.world)) {
-          registry.registerThrowNoSuchMethod();
-          if (node.isSuperCall) {
-            internalError(node, "Unexpected super call $node");
-          }
-        }
-      }
-
-      handleForeignCall(node, target, selector);
-    }
-
-    registry.useElement(node, target);
-    registerSend(selector, target);
-    if (node.isPropertyAccess && Elements.isStaticOrTopLevelFunction(target)) {
-      registry.registerGetOfStaticFunction(target.declaration);
-    }
-    return node.isPropertyAccess
-        ? new ResolutionResult.forElement(target) : const NoneResult();
-  }
-
   // TODO(johnniwinther): Move this to the backend resolution callbacks.
   void handleForeignCall(Send node, Element target, Selector selector) {
     if (target != null && compiler.backend.isForeign(target)) {
diff --git a/pkg/compiler/lib/src/scanner/array_based_scanner.dart b/pkg/compiler/lib/src/scanner/array_based_scanner.dart
index 85e3a3c..457be84 100644
--- a/pkg/compiler/lib/src/scanner/array_based_scanner.dart
+++ b/pkg/compiler/lib/src/scanner/array_based_scanner.dart
@@ -5,9 +5,8 @@
 part of scanner;
 
 abstract class ArrayBasedScanner extends AbstractScanner {
-  ArrayBasedScanner(SourceFile file, bool includeComments,
-                    bool enableNullAwareOperators)
-      : super(file, includeComments, enableNullAwareOperators);
+  ArrayBasedScanner(SourceFile file, bool includeComments)
+      : super(file, includeComments);
 
   /**
    * The stack of open groups, e.g [: { ... ( .. :]
diff --git a/pkg/compiler/lib/src/scanner/listener.dart b/pkg/compiler/lib/src/scanner/listener.dart
index b6c356a..ef9b651 100644
--- a/pkg/compiler/lib/src/scanner/listener.dart
+++ b/pkg/compiler/lib/src/scanner/listener.dart
@@ -746,9 +746,6 @@
           break;
       }
       reportError(token, kind, arguments);
-    } else if (token is UnsupportedNullAwareToken) {
-      reportError(token, MessageKind.NULL_AWARE_OPERATORS_DISABLED,
-          {'operator' : token.operator});
     } else if (token is UnmatchedToken) {
       String begin = token.begin.value;
       String end = closeBraceFor(begin);
diff --git a/pkg/compiler/lib/src/scanner/scanner.dart b/pkg/compiler/lib/src/scanner/scanner.dart
index 65db47e..d9ab312 100644
--- a/pkg/compiler/lib/src/scanner/scanner.dart
+++ b/pkg/compiler/lib/src/scanner/scanner.dart
@@ -8,13 +8,11 @@
   Token tokenize();
 
   factory Scanner(SourceFile file,
-      {bool includeComments: false, bool enableNullAwareOperators: false}) {
+      {bool includeComments: false}) {
     if (file is Utf8BytesSourceFile) {
-      return new Utf8BytesScanner(file, includeComments: includeComments,
-          enableNullAwareOperators: enableNullAwareOperators);
+      return new Utf8BytesScanner(file, includeComments: includeComments);
     } else {
-      return new StringScanner(file, includeComments: includeComments,
-          enableNullAwareOperators: enableNullAwareOperators);
+      return new StringScanner(file, includeComments: includeComments);
     }
   }
 }
@@ -23,7 +21,6 @@
   // TODO(ahe): Move this class to implementation.
 
   final bool includeComments;
-  final bool enableNullAwareOperators;
 
   /**
    * The string offset for the next token that will be created.
@@ -58,7 +55,7 @@
   final List<int> lineStarts = <int>[0];
 
   AbstractScanner(
-      this.file, this.includeComments, this.enableNullAwareOperators) {
+      this.file, this.includeComments) {
     this.tail = this.tokens;
   }
 
@@ -458,27 +455,9 @@
     // ? ?. ?? ??=
     next = advance();
     if (identical(next, $QUESTION)) {
-      if (enableNullAwareOperators) {
-        return select($EQ, QUESTION_QUESTION_EQ_INFO, QUESTION_QUESTION_INFO);
-      } else {
-        next = advance();
-        PrecedenceInfo info;
-        if (identical(next, $EQ)) {
-          info = QUESTION_QUESTION_EQ_INFO;
-          next = advance();
-        } else {
-          info = QUESTION_QUESTION_INFO;
-        }
-        appendErrorToken(new UnsupportedNullAwareToken(info.value, tokenStart));
-        return next;
-      }
+      return select($EQ, QUESTION_QUESTION_EQ_INFO, QUESTION_QUESTION_INFO);
     } else if (identical(next, $PERIOD)) {
-      if (enableNullAwareOperators) {
-        appendPrecedenceToken(QUESTION_PERIOD_INFO);
-      } else {
-        appendErrorToken(new UnsupportedNullAwareToken(
-            QUESTION_PERIOD_INFO.value, tokenStart));
-      }
+      appendPrecedenceToken(QUESTION_PERIOD_INFO);
       return advance();
     } else {
       appendPrecedenceToken(QUESTION_INFO);
diff --git a/pkg/compiler/lib/src/scanner/scanner_task.dart b/pkg/compiler/lib/src/scanner/scanner_task.dart
index e239026..636ee34 100644
--- a/pkg/compiler/lib/src/scanner/scanner_task.dart
+++ b/pkg/compiler/lib/src/scanner/scanner_task.dart
@@ -29,8 +29,7 @@
   void scanElements(CompilationUnitElement compilationUnit) {
     Script script = compilationUnit.script;
     Token tokens = new Scanner(script.file,
-        includeComments: compiler.preserveComments,
-        enableNullAwareOperators: compiler.enableNullAwareOperators).tokenize();
+        includeComments: compiler.preserveComments).tokenize();
     if (compiler.preserveComments) {
       tokens = compiler.processAndStripComments(tokens);
     }
diff --git a/pkg/compiler/lib/src/scanner/string_scanner.dart b/pkg/compiler/lib/src/scanner/string_scanner.dart
index 8eb736f..5a30e43 100644
--- a/pkg/compiler/lib/src/scanner/string_scanner.dart
+++ b/pkg/compiler/lib/src/scanner/string_scanner.dart
@@ -15,16 +15,14 @@
   /** The current offset in [string]. */
   int scanOffset = -1;
 
-  StringScanner(SourceFile file, {bool includeComments: false,
-                                  bool enableNullAwareOperators: false})
+  StringScanner(SourceFile file, {bool includeComments: false})
       : string = file.slowText(),
-        super(file, includeComments, enableNullAwareOperators) {
+        super(file, includeComments) {
     ensureZeroTermination();
   }
 
-  StringScanner.fromString(this.string, {bool includeComments: false,
-                                         bool enableNullAwareOperators: false})
-      : super(null, includeComments, enableNullAwareOperators) {
+  StringScanner.fromString(this.string, {bool includeComments: false})
+      : super(null, includeComments) {
     ensureZeroTermination();
   }
 
diff --git a/pkg/compiler/lib/src/scanner/token.dart b/pkg/compiler/lib/src/scanner/token.dart
index c1a502b..c7c74d1 100644
--- a/pkg/compiler/lib/src/scanner/token.dart
+++ b/pkg/compiler/lib/src/scanner/token.dart
@@ -262,21 +262,6 @@
   }
 }
 
-// TODO(sigmund): delete once we enable null-aware-operators by default.
-class UnsupportedNullAwareToken extends ErrorToken {
-  final String operator;
-
-  UnsupportedNullAwareToken(this.operator, int charOffset)
-      : super(charOffset);
-
-  String toString() => "UnsupportedNullAwareToken($operator)";
-
-  String get assertionMessage => "'$operator' isn't supported without "
-      "the --enable-null-aware-operators flag.";
-
-  int get charCount => operator.length;
-}
-
 class UnterminatedToken extends ErrorToken {
   final String start;
   final int endOffset;
diff --git a/pkg/compiler/lib/src/scanner/utf8_bytes_scanner.dart b/pkg/compiler/lib/src/scanner/utf8_bytes_scanner.dart
index f242f57..d919596 100644
--- a/pkg/compiler/lib/src/scanner/utf8_bytes_scanner.dart
+++ b/pkg/compiler/lib/src/scanner/utf8_bytes_scanner.dart
@@ -69,10 +69,9 @@
    * array whose last element is '0' to signal the end of the file. If this
    * is not the case, the entire array is copied before scanning.
    */
-  Utf8BytesScanner(SourceFile file, {bool includeComments: false,
-                                     bool enableNullAwareOperators: false})
+  Utf8BytesScanner(SourceFile file, {bool includeComments: false})
       : bytes = file.slowUtf8ZeroTerminatedBytes(),
-        super(file, includeComments, enableNullAwareOperators) {
+        super(file, includeComments) {
     assert(bytes.last == 0);
     // Skip a leading BOM.
     if (_containsBomAt(0)) byteOffset += 3;
@@ -86,10 +85,9 @@
    * scanning.
    */
   Utf8BytesScanner.fromBytes(List<int> zeroTerminatedBytes,
-                             {bool includeComments: false,
-                              bool enableNullAwareOperators: false})
+                             {bool includeComments: false})
       : this.bytes = zeroTerminatedBytes,
-        super(null, includeComments, enableNullAwareOperators) {
+        super(null, includeComments) {
     assert(bytes.last == 0);
   }
 
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index f866a0f..1335674 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -2191,8 +2191,10 @@
           constructorArguments,
           instantiatedTypes);
       if (function != null) {
+        // TODO(johnniwinther): Provide source information for creation
+        // through synthetic constructors.
         newObject.sourceInformation =
-            sourceInformationBuilder.buildGeneric(function);
+            sourceInformationBuilder.buildCreate(function);
       }
       add(newObject);
     } else {
@@ -3147,7 +3149,7 @@
     TypeMask type =
         new TypeMask.nonNullExact(compiler.functionClass, compiler.world);
     push(new HForeignNew(closureClassElement, type, capturedVariables)
-        ..sourceInformation = sourceInformationBuilder.buildGeneric(node));
+        ..sourceInformation = sourceInformationBuilder.buildCreate(node));
 
     Element methodElement = nestedClosureData.closureElement;
     registry.registerInstantiatedClosure(methodElement);
@@ -4064,8 +4066,8 @@
 
     if (!compiler.hasIsolateSupport) {
       // If the isolate library is not used, we just generate code
-      // to fetch the current isolate.
-      String name = backend.namer.currentIsolate;
+      // to fetch the static state.
+      String name = backend.namer.staticStateHolder;
       push(new HForeignCode(js.js.parseForeignJS(name),
                             backend.dynamicType,
                             <HInstruction>[]));
@@ -4331,13 +4333,13 @@
     handleForeignRawFunctionRef(node, name);
   }
 
-  void handleForeignSetCurrentIsolate(ast.Send node) {
+  void handleForeignJsSetStaticState(ast.Send node) {
     if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) {
       compiler.internalError(node.argumentsNode,
           'Exactly one argument required.');
     }
     visit(node.arguments.head);
-    String isolateName = backend.namer.currentIsolate;
+    String isolateName = backend.namer.staticStateHolder;
     SideEffects sideEffects = new SideEffects.empty();
     sideEffects.setAllSideEffects();
     push(new HForeignCode(
@@ -4348,11 +4350,11 @@
         effects: sideEffects));
   }
 
-  void handleForeignJsCurrentIsolate(ast.Send node) {
+  void handleForeignJsGetStaticState(ast.Send node) {
     if (!node.arguments.isEmpty) {
       compiler.internalError(node.argumentsNode, 'Too many arguments.');
     }
-    push(new HForeignCode(js.js.parseForeignJS(backend.namer.currentIsolate),
+    push(new HForeignCode(js.js.parseForeignJS(backend.namer.staticStateHolder),
                           backend.dynamicType,
                           <HInstruction>[]));
   }
@@ -4369,10 +4371,10 @@
       handleForeignDartClosureToJs(node, 'DART_CLOSURE_TO_JS');
     } else if (name == 'RAW_DART_FUNCTION_REF') {
       handleForeignRawFunctionRef(node, 'RAW_DART_FUNCTION_REF');
-    } else if (name == 'JS_SET_CURRENT_ISOLATE') {
-      handleForeignSetCurrentIsolate(node);
-    } else if (name == 'JS_CURRENT_ISOLATE') {
-      handleForeignJsCurrentIsolate(node);
+    } else if (name == 'JS_SET_STATIC_STATE') {
+      handleForeignJsSetStaticState(node);
+    } else if (name == 'JS_GET_STATIC_STATE') {
+      handleForeignJsGetStaticState(node);
     } else if (name == 'JS_GET_NAME') {
       handleForeignJsGetName(node);
     } else if (name == 'JS_EMBEDDED_GLOBAL') {
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart b/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart
index a6acceb..1820f1d 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart
@@ -315,6 +315,24 @@
     return node;
   }
 
+  Expression visitGetLength(GetLength node) {
+    super.visitGetLength(node);
+    ++impureCounter;
+    return node;
+  }
+
+  Expression visitGetIndex(GetIndex node) {
+    super.visitGetIndex(node);
+    ++impureCounter;
+    return node;
+  }
+
+  Expression visitSetIndex(SetIndex node) {
+    super.visitSetIndex(node);
+    ++impureCounter;
+    return node;
+  }
+
   void visitInnerFunction(FunctionDefinition node) {
     new PullIntoInitializers().rewrite(node);
   }
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
index be59dc9..6fda009 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
@@ -6,6 +6,7 @@
 
 import 'optimization.dart' show Pass;
 import '../tree_ir_nodes.dart';
+import '../../io/source_information.dart';
 
 /**
  * Translates to direct-style.
@@ -350,6 +351,7 @@
     return exp is Constant ||
            exp is This ||
            exp is CreateInvocationMirror ||
+           exp is GetStatic && exp.element.isFunction ||
            exp is Interceptor ||
            exp is ApplyBuiltinOperator ||
            exp is VariableUse && constantEnvironment.containsKey(exp.variable);
@@ -583,17 +585,15 @@
   }
 
   Statement visitIf(If node) {
-    node.condition = visitExpression(node.condition);
-
-    // Do not propagate assignments into branches.  Doing so will lead to code
-    // duplication.
-    // TODO(kmillikin): Rethink this. Propagating some assignments
-    // (e.g. variables) is benign.  If they can occur here, they should
-    // be handled well.
+    // Do not propagate assignments into branches.
     inEmptyEnvironment(() {
       node.thenStatement = visitStatement(node.thenStatement);
       node.elseStatement = visitStatement(node.elseStatement);
+    });
 
+    node.condition = visitExpression(node.condition);
+
+    inEmptyEnvironment(() {
       tryCollapseIf(node);
     });
 
@@ -717,6 +717,24 @@
     return node;
   }
 
+  Expression visitGetLength(GetLength node) {
+    node.object = visitExpression(node.object);
+    return node;
+  }
+
+  Expression visitGetIndex(GetIndex node) {
+    node.index = visitExpression(node.index);
+    node.object = visitExpression(node.object);
+    return node;
+  }
+
+  Expression visitSetIndex(SetIndex node) {
+    node.value = visitExpression(node.value);
+    node.index = visitExpression(node.index);
+    node.object = visitExpression(node.object);
+    return node;
+  }
+
   /// True if [operator] is a binary operator that always has the same value
   /// if its arguments are swapped.
   bool isSymmetricOperator(BuiltinOperator operator) {
@@ -907,7 +925,11 @@
     if (s is Return && t is Return) {
       CombinedExpressions values = combineExpressions(s.value, t.value);
       if (values != null) {
-        return new Return(values.combined);
+        // TODO(johnniwinther): Handle multiple source informations.
+        SourceInformation sourceInformation = s.sourceInformation != null
+            ? s.sourceInformation : t.sourceInformation;
+        return new Return(values.combined,
+            sourceInformation: sourceInformation);
       }
     }
     if (s is ExpressionStatement && t is ExpressionStatement) {
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
index 6ca4430..47d7898 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
@@ -274,7 +274,8 @@
     return new CreateInstance(
         node.classElement,
         translateArguments(node.arguments),
-        translateArguments(node.typeInformation));
+        translateArguments(node.typeInformation),
+        node.sourceInformation);
   }
 
   Expression visitGetField(cps_ir.GetField node) {
@@ -355,10 +356,12 @@
   }
 
   Statement visitInvokeMethod(cps_ir.InvokeMethod node) {
-    InvokeMethod invoke = new InvokeMethod(getVariableUse(node.receiver),
-                                           node.selector,
-                                           node.mask,
-                                           translateArguments(node.arguments));
+    InvokeMethod invoke = new InvokeMethod(
+        getVariableUse(node.receiver),
+        node.selector,
+        node.mask,
+        translateArguments(node.arguments),
+        node.sourceInformation);
     invoke.receiverIsNotNull = node.receiverIsNotNull;
     return continueWithExpression(node.continuation, invoke);
   }
@@ -367,7 +370,7 @@
     Expression receiver = getVariableUse(node.receiver);
     List<Expression> arguments = translateArguments(node.arguments);
     Expression invoke = new InvokeMethodDirectly(receiver, node.target,
-        node.selector, arguments);
+        node.selector, arguments, node.sourceInformation);
     return continueWithExpression(node.continuation, invoke);
   }
 
@@ -439,7 +442,8 @@
         node.type,
         node.target,
         node.selector,
-        arguments);
+        arguments,
+        node.sourceInformation);
     return continueWithExpression(node.continuation, invoke);
   }
 
@@ -452,7 +456,8 @@
     cps_ir.Continuation cont = node.continuation.definition;
     if (cont == returnContinuation) {
       assert(node.arguments.length == 1);
-      return new Return(getVariableUse(node.arguments.single));
+      return new Return(getVariableUse(node.arguments.single),
+                        sourceInformation: node.sourceInformation);
     } else {
       List<Expression> arguments = translateArguments(node.arguments);
       return buildPhiAssignments(cont.parameters, arguments,
@@ -500,7 +505,7 @@
   }
 
   Expression visitConstant(cps_ir.Constant node) {
-    return new Constant(node.value);
+    return new Constant(node.value, sourceInformation: node.sourceInformation);
   }
 
   Expression visitLiteralList(cps_ir.LiteralList node) {
@@ -552,11 +557,15 @@
   }
 
   Expression visitReifyRuntimeType(cps_ir.ReifyRuntimeType node) {
-    return new ReifyRuntimeType(getVariableUse(node.value));
+    return new ReifyRuntimeType(
+        getVariableUse(node.value), node.sourceInformation);
   }
 
   Expression visitReadTypeVariable(cps_ir.ReadTypeVariable node) {
-    return new ReadTypeVariable(node.variable, getVariableUse(node.target));
+    return new ReadTypeVariable(
+        node.variable,
+        getVariableUse(node.target),
+        node.sourceInformation);
   }
 
   @override
@@ -612,5 +621,20 @@
           node.dependency);
     }
   }
+
+  Expression visitGetLength(cps_ir.GetLength node) {
+    return new GetLength(getVariableUse(node.object));
+  }
+
+  Expression visitGetIndex(cps_ir.GetIndex node) {
+    return new GetIndex(getVariableUse(node.object),
+                        getVariableUse(node.index));
+  }
+
+  Expression visitSetIndex(cps_ir.SetIndex node) {
+    return new SetIndex(getVariableUse(node.object),
+                        getVariableUse(node.index),
+                        getVariableUse(node.value));
+  }
 }
 
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
index b30c368..d922d09 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
@@ -201,11 +201,16 @@
   final Selector selector;
   final TypeMask mask;
   final List<Expression> arguments;
+  final SourceInformation sourceInformation;
 
   /// If true, it is known that the receiver cannot be `null`.
   bool receiverIsNotNull = false;
 
-  InvokeMethod(this.receiver, this.selector, this.mask, this.arguments) {
+  InvokeMethod(this.receiver,
+               this.selector,
+               this.mask,
+               this.arguments,
+               this.sourceInformation) {
     assert(receiver != null);
   }
 
@@ -224,9 +229,10 @@
   final Element target;
   final Selector selector;
   final List<Expression> arguments;
+  final SourceInformation sourceInformation;
 
   InvokeMethodDirectly(this.receiver, this.target, this.selector,
-      this.arguments);
+      this.arguments, this.sourceInformation);
 
   accept(ExpressionVisitor visitor) => visitor.visitInvokeMethodDirectly(this);
   accept1(ExpressionVisitor1 visitor, arg) {
@@ -242,12 +248,13 @@
   final FunctionElement target;
   final List<Expression> arguments;
   final Selector selector;
+  final SourceInformation sourceInformation;
   /// TODO(karlklose): get rid of this field.  Instead use the constant's
   /// expression to find the constructor to be called in dart2dart.
   final values.ConstantValue constant;
 
   InvokeConstructor(this.type, this.target, this.selector, this.arguments,
-                    [this.constant]);
+                    this.sourceInformation, [this.constant]);
 
   ClassElement get targetClass => target.enclosingElement;
 
@@ -265,14 +272,18 @@
  */
 class Constant extends Expression {
   final values.ConstantValue value;
+  final SourceInformation sourceInformation;
 
-  Constant(this.value);
+  Constant(this.value, {this.sourceInformation});
 
   Constant.bool(values.BoolConstantValue constantValue)
-      : value = constantValue;
+      : value = constantValue,
+        sourceInformation = null;
 
   accept(ExpressionVisitor visitor) => visitor.visitConstant(this);
   accept1(ExpressionVisitor1 visitor, arg) => visitor.visitConstant(this, arg);
+
+  String toString() => 'Constant(value=${value.toStructuredString()})';
 }
 
 class This extends Expression {
@@ -364,6 +375,9 @@
   accept1(ExpressionVisitor1 visitor, arg) {
     return visitor.visitConditional(this, arg);
   }
+
+  String toString() => 'Conditional(condition=$condition,thenExpression='
+                       '$thenExpression,elseExpression=$elseExpression)';
 }
 
 /// An && or || expression. The operator is internally represented as a boolean
@@ -383,6 +397,8 @@
   accept1(ExpressionVisitor1 visitor, arg) {
     return visitor.visitLogicalOperator(this, arg);
   }
+
+  String toString() => 'LogicalOperator(left=$left,right=$right,isAnd=$isAnd)';
 }
 
 /// Logical negation.
@@ -541,11 +557,12 @@
   /// Even in constructors this holds true. Take special care when translating
   /// back to dart, where `return null;` in a constructor is an error.
   Expression value;
+  SourceInformation sourceInformation;
 
   Statement get next => null;
   void set next(Statement s) => throw 'UNREACHABLE';
 
-  Return(this.value);
+  Return(this.value, {this.sourceInformation});
 
   accept(StatementVisitor visitor) => visitor.visitReturn(this);
   accept1(StatementVisitor1 visitor, arg) => visitor.visitReturn(this, arg);
@@ -664,8 +681,10 @@
   ClassElement classElement;
   List<Expression> arguments;
   List<Expression> typeInformation;
+  SourceInformation sourceInformation;
 
-  CreateInstance(this.classElement, this.arguments, this.typeInformation);
+  CreateInstance(this.classElement, this.arguments,
+                 this.typeInformation, this.sourceInformation);
 
   accept(ExpressionVisitor visitor) => visitor.visitCreateInstance(this);
   accept1(ExpressionVisitor1 visitor, arg) {
@@ -717,10 +736,41 @@
   accept1(ExpressionVisitor1 visitor, arg) => visitor.visitSetStatic(this, arg);
 }
 
-class ReifyRuntimeType extends Expression {
+class GetLength extends Expression {
+  Expression object;
+
+  GetLength(this.object);
+
+  accept(ExpressionVisitor v) => v.visitGetLength(this);
+  accept1(ExpressionVisitor1 v, arg) => v.visitGetLength(this, arg);
+}
+
+class GetIndex extends Expression {
+  Expression object;
+  Expression index;
+
+  GetIndex(this.object, this.index);
+
+  accept(ExpressionVisitor v) => v.visitGetIndex(this);
+  accept1(ExpressionVisitor1 v, arg) => v.visitGetIndex(this, arg);
+}
+
+class SetIndex extends Expression {
+  Expression object;
+  Expression index;
   Expression value;
 
-  ReifyRuntimeType(this.value);
+  SetIndex(this.object, this.index, this.value);
+
+  accept(ExpressionVisitor v) => v.visitSetIndex(this);
+  accept1(ExpressionVisitor1 v, arg) => v.visitSetIndex(this, arg);
+}
+
+class ReifyRuntimeType extends Expression {
+  Expression value;
+  SourceInformation sourceInformation;
+
+  ReifyRuntimeType(this.value, this.sourceInformation);
 
   accept(ExpressionVisitor visitor) {
     return visitor.visitReifyRuntimeType(this);
@@ -734,8 +784,9 @@
 class ReadTypeVariable extends Expression {
   final TypeVariableType variable;
   Expression target;
+  final SourceInformation sourceInformation;
 
-  ReadTypeVariable(this.variable, this.target);
+  ReadTypeVariable(this.variable, this.target, this.sourceInformation);
 
   accept(ExpressionVisitor visitor) {
     return visitor.visitReadTypeVariable(this);
@@ -873,6 +924,9 @@
   E visitInterceptor(Interceptor node);
   E visitApplyBuiltinOperator(ApplyBuiltinOperator node);
   E visitForeignExpression(ForeignExpression node);
+  E visitGetLength(GetLength node);
+  E visitGetIndex(GetIndex node);
+  E visitSetIndex(SetIndex node);
 }
 
 abstract class ExpressionVisitor1<E, A> {
@@ -905,6 +959,9 @@
   E visitInterceptor(Interceptor node, A arg);
   E visitApplyBuiltinOperator(ApplyBuiltinOperator node, A arg);
   E visitForeignExpression(ForeignExpression node, A arg);
+  E visitGetLength(GetLength node, A arg);
+  E visitGetIndex(GetIndex node, A arg);
+  E visitSetIndex(SetIndex node, A arg);
 }
 
 abstract class StatementVisitor<S> {
@@ -1117,6 +1174,21 @@
 
   visitForeignExpression(ForeignExpression node) => visitForeignCode(node);
   visitForeignStatement(ForeignStatement node) => visitForeignCode(node);
+
+  visitGetLength(GetLength node) {
+    visitExpression(node.object);
+  }
+
+  visitGetIndex(GetIndex node) {
+    visitExpression(node.object);
+    visitExpression(node.index);
+  }
+
+  visitSetIndex(SetIndex node) {
+    visitExpression(node.object);
+    visitExpression(node.index);
+    visitExpression(node.value);
+  }
 }
 
 abstract class Transformer implements ExpressionVisitor<Expression>,
@@ -1332,6 +1404,24 @@
     node.input = visitExpression(node.input);
     return node;
   }
+
+  visitGetLength(GetLength node) {
+    node.object = visitExpression(node.object);
+    return node;
+  }
+
+  visitGetIndex(GetIndex node) {
+    node.object = visitExpression(node.object);
+    node.index = visitExpression(node.index);
+    return node;
+  }
+
+  visitSetIndex(SetIndex node) {
+    node.object = visitExpression(node.object);
+    node.index = visitExpression(node.index);
+    node.value = visitExpression(node.value);
+    return node;
+  }
 }
 
 class FallthroughTarget {
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
index caffb4a..63d1a05 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
@@ -530,6 +530,27 @@
     String args = node.arguments.map(visitExpression).join(', ');
     return 'ApplyBuiltinOperator ${node.operator} ($args)';
   }
+
+  @override
+  String visitGetLength(GetLength node) {
+    String object = visitExpression(node.object);
+    return 'GetLength($object)';
+  }
+
+  @override
+  String visitGetIndex(GetIndex node) {
+    String object = visitExpression(node.object);
+    String index = visitExpression(node.index);
+    return 'GetIndex($object, $index)';
+  }
+
+  @override
+  String visitSetIndex(SetIndex node) {
+    String object = visitExpression(node.object);
+    String index = visitExpression(node.index);
+    String value = visitExpression(node.value);
+    return 'SetIndex($object, $index, $value)';
+  }
 }
 
 /**
diff --git a/pkg/compiler/lib/src/types/flat_type_mask.dart b/pkg/compiler/lib/src/types/flat_type_mask.dart
index 17d0fc5..ce19f17 100644
--- a/pkg/compiler/lib/src/types/flat_type_mask.dart
+++ b/pkg/compiler/lib/src/types/flat_type_mask.dart
@@ -50,11 +50,11 @@
       return new FlatTypeMask.internal(base, flags);
     }
     if ((flags >> 1) == SUBTYPE) {
-      if (!world.hasAnySubtype(base) || world.hasOnlySubclasses(base)) {
+      if (!world.hasAnyStrictSubtype(base) || world.hasOnlySubclasses(base)) {
         flags = (flags & 0x1) | (SUBCLASS << 1);
       }
     }
-    if (((flags >> 1) == SUBCLASS) && !world.hasAnySubclass(base)) {
+    if (((flags >> 1) == SUBCLASS) && !world.hasAnyStrictSubclass(base)) {
       flags = (flags & 0x1) | (EXACT << 1);
     }
     Map<ClassElement, TypeMask> cachedMasks =
@@ -631,10 +631,10 @@
 
     Iterable<ClassElement> subclassesToCheck;
     if (isSubtype) {
-      subclassesToCheck = classWorld.subtypesOf(base);
+      subclassesToCheck = classWorld.strictSubtypesOf(base);
     } else {
       assert(isSubclass);
-      subclassesToCheck = classWorld.subclassesOf(base);
+      subclassesToCheck = classWorld.strictSubclassesOf(base);
     }
 
     return subclassesToCheck != null &&
@@ -704,10 +704,10 @@
     if (x.isExact) {
       return null;
     } else if (x.isSubclass) {
-      return classWorld.subclassesOf(element);
+      return classWorld.strictSubclassesOf(element);
     } else {
       assert(x.isSubtype);
-      return classWorld.subtypesOf(element);
+      return classWorld.strictSubtypesOf(element);
     }
   }
 }
diff --git a/pkg/compiler/lib/src/types/type_mask.dart b/pkg/compiler/lib/src/types/type_mask.dart
index 8e4e2d2..bf095b8 100644
--- a/pkg/compiler/lib/src/types/type_mask.dart
+++ b/pkg/compiler/lib/src/types/type_mask.dart
@@ -33,7 +33,7 @@
   }
 
   factory TypeMask.subclass(ClassElement base, ClassWorld classWorld) {
-    if (classWorld.hasAnySubclass(base)) {
+    if (classWorld.hasAnyStrictSubclass(base)) {
       return new FlatTypeMask.subclass(base);
     } else {
       return new TypeMask.exactOrEmpty(base, classWorld);
@@ -44,7 +44,7 @@
     if (classWorld.hasOnlySubclasses(base)) {
       return new TypeMask.subclass(base, classWorld);
     }
-    if (classWorld.hasAnySubtype(base)) {
+    if (classWorld.hasAnyStrictSubtype(base)) {
       return new FlatTypeMask.subtype(base);
     } else {
       return new TypeMask.exactOrEmpty(base, classWorld);
@@ -69,7 +69,7 @@
   }
 
   factory TypeMask.nonNullSubclass(ClassElement base, ClassWorld classWorld) {
-    if (classWorld.hasAnySubclass(base)) {
+    if (classWorld.hasAnyStrictSubclass(base)) {
       return new FlatTypeMask.nonNullSubclass(base);
     } else {
       return new TypeMask.nonNullExactOrEmpty(base, classWorld);
@@ -80,7 +80,7 @@
     if (classWorld.hasOnlySubclasses(base)) {
       return new TypeMask.nonNullSubclass(base, classWorld);
     }
-    if (classWorld.hasAnySubtype(base)) {
+    if (classWorld.hasAnyStrictSubtype(base)) {
       return new FlatTypeMask.nonNullSubtype(base);
     } else {
       return new TypeMask.nonNullExactOrEmpty(base, classWorld);
@@ -126,13 +126,13 @@
         return null;
       }
       if (mask.isSubclass) {
-        if (!classWorld.hasAnySubclass(mask.base)) {
+        if (!classWorld.hasAnyStrictSubclass(mask.base)) {
           return 'Subclass ${mask.base} does not have any subclasses.';
         }
         return null;
       }
       assert(mask.isSubtype);
-      if (!classWorld.hasAnySubtype(mask.base)) {
+      if (!classWorld.hasAnyStrictSubtype(mask.base)) {
         return 'Subtype ${mask.base} does not have any subclasses.';
       }
       if (classWorld.hasOnlySubclasses(mask.base)) {
diff --git a/pkg/compiler/lib/src/types/union_type_mask.dart b/pkg/compiler/lib/src/types/union_type_mask.dart
index f4c45e7..63a421d 100644
--- a/pkg/compiler/lib/src/types/union_type_mask.dart
+++ b/pkg/compiler/lib/src/types/union_type_mask.dart
@@ -103,7 +103,7 @@
     int bestSize;
     for (ClassElement candidate in candidates) {
       Iterable<ClassElement> subclasses = useSubclass
-          ? classWorld.subclassesOf(candidate)
+          ? classWorld.strictSubclassesOf(candidate)
           : const <ClassElement>[];
       int size;
       int kind;
@@ -114,10 +114,10 @@
         // subtype type mask.
         kind = FlatTypeMask.SUBCLASS;
         size = subclasses.length;
-        assert(size <= classWorld.subtypesOf(candidate).length);
+        assert(size <= classWorld.strictSubtypesOf(candidate).length);
       } else {
         kind = FlatTypeMask.SUBTYPE;
-        size = classWorld.subtypesOf(candidate).length;
+        size = classWorld.strictSubtypesOf(candidate).length;
       }
       // Update the best candidate if the new one is better.
       if (bestElement == null || size < bestSize) {
@@ -212,10 +212,10 @@
     // Check for other members.
     Iterable<ClassElement> members;
     if (flat.isSubclass) {
-      members = classWorld.subclassesOf(flat.base);
+      members = classWorld.strictSubclassesOf(flat.base);
     } else {
       assert(flat.isSubtype);
-      members = classWorld.subtypesOf(flat.base);
+      members = classWorld.strictSubtypesOf(flat.base);
     }
     return members.every((ClassElement cls) => this.contains(cls, classWorld));
   }
diff --git a/pkg/compiler/lib/src/universe/function_set.dart b/pkg/compiler/lib/src/universe/function_set.dart
index db99578..7260c6d 100644
--- a/pkg/compiler/lib/src/universe/function_set.dart
+++ b/pkg/compiler/lib/src/universe/function_set.dart
@@ -243,7 +243,7 @@
    * Compute the type of all potential receivers of this function set.
    */
   TypeMask computeMask(ClassWorld classWorld) {
-    assert(classWorld.hasAnySubclass(classWorld.objectClass));
+    assert(classWorld.hasAnyStrictSubclass(classWorld.objectClass));
     if (_mask != null) return _mask;
     return _mask = new TypeMask.unionOf(functions
         .expand((element) {
diff --git a/pkg/compiler/lib/src/use_unused_api.dart b/pkg/compiler/lib/src/use_unused_api.dart
index 3e90be4..ffbcb5e 100644
--- a/pkg/compiler/lib/src/use_unused_api.dart
+++ b/pkg/compiler/lib/src/use_unused_api.dart
@@ -31,6 +31,7 @@
 import 'js/js.dart' as js;
 import 'js_backend/js_backend.dart' as js_backend;
 import 'js_emitter/js_emitter.dart' as js_emitter;
+import 'js_emitter/full_emitter/emitter.dart' as full;
 import 'js_emitter/program_builder/program_builder.dart' as program_builder;
 import 'resolution/semantic_visitor.dart' as semantic_visitor;
 import 'resolution/operators.dart' as operators;
@@ -301,9 +302,9 @@
 }
 
 useCodeEmitterTask(js_emitter.CodeEmitterTask codeEmitterTask) {
-  codeEmitterTask.oldEmitter.clearCspPrecompiledNodes();
-  codeEmitterTask.oldEmitter.
-      buildLazilyInitializedStaticField(null, isolateProperties: null);
+  full.Emitter fullEmitter = codeEmitterTask.emitter;
+  fullEmitter.clearCspPrecompiledNodes();
+  fullEmitter.buildLazilyInitializedStaticField(null, isolateProperties: null);
 }
 
 useScript(dart2jslib.Script script) {
diff --git a/pkg/compiler/lib/src/warnings.dart b/pkg/compiler/lib/src/warnings.dart
index f144262..350af41 100644
--- a/pkg/compiler/lib/src/warnings.dart
+++ b/pkg/compiler/lib/src/warnings.dart
@@ -401,6 +401,9 @@
   static const MessageKind NOT_A_PREFIX = const MessageKind(
       "'#{node}' is not a prefix.");
 
+  static const MessageKind PREFIX_AS_EXPRESSION = const MessageKind(
+      "Library prefix '#{prefix}' is not a valid expression.");
+
   static const MessageKind CANNOT_FIND_CONSTRUCTOR = const MessageKind(
       "Cannot find constructor '#{constructorName}'.");
 
@@ -1202,7 +1205,6 @@
       "Cannot assign a value to a type. Note that types are never null, "
       "so this ??= assignment has no effect.",
       howToFix: "Try removing the '??=' assignment.",
-      options: const ['--enable-null-aware-operators'],
       examples: const [
           "class A {} main() { print(A ??= 3);}",
       ]);
@@ -2022,10 +2024,6 @@
       // This is a fall-back message that shouldn't happen.
       "Incomplete token.");
 
-  static const MessageKind NULL_AWARE_OPERATORS_DISABLED = const MessageKind(
-      "Null-aware operators like '#{operator}' are currently experimental. "
-      "You can enable them using the --enable-null-aware-operators flag.");
-
   static const MessageKind EXPONENT_MISSING = const MessageKind(
       "Numbers in exponential notation should always contain an exponent"
       " (an integer number with an optional sign).",
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index 21dc96e..b4d78dd 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -46,31 +46,17 @@
   /// instance of [y].
   bool isSubtypeOf(ClassElement x, ClassElement y);
 
-  /// Returns an iterable over the live classes that extend [cls] including
-  /// [cls] itself.
-  Iterable<ClassElement> subclassesOf(ClassElement cls);
-
   /// Returns an iterable over the live classes that extend [cls] _not_
   /// including [cls] itself.
   Iterable<ClassElement> strictSubclassesOf(ClassElement cls);
 
-  /// Returns an iterable over the live classes that implement [cls] including
-  /// [cls] if it is live.
-  Iterable<ClassElement> subtypesOf(ClassElement cls);
-
   /// Returns an iterable over the live classes that implement [cls] _not_
   /// including [cls] if it is live.
   Iterable<ClassElement> strictSubtypesOf(ClassElement cls);
 
-  /// Returns `true` if any live class extends [cls].
-  bool hasAnySubclass(ClassElement cls);
-
   /// Returns `true` if any live class other than [cls] extends [cls].
   bool hasAnyStrictSubclass(ClassElement cls);
 
-  /// Returns `true` if any live class implements [cls].
-  bool hasAnySubtype(ClassElement cls);
-
   /// Returns `true` if any live class other than [cls] implements [cls].
   bool hasAnyStrictSubtype(ClassElement cls);
 
@@ -159,9 +145,9 @@
     return compiler.resolverWorld.isInstantiated(cls);
   }
 
-  /// Returns an iterable over the live classes that extend [cls] including
-  /// [cls] itself.
-  Iterable<ClassElement> subclassesOf(ClassElement cls) {
+  /// Returns an iterable over the live classes that extend [cls] _not_
+  /// including [cls] itself.
+  Iterable<ClassElement> strictSubclassesOf(ClassElement cls) {
     Set<ClassElement> subclasses = _subclasses[cls.declaration];
     if (subclasses == null) return const <ClassElement>[];
     assert(invariant(cls, isInstantiated(cls.declaration),
@@ -169,28 +155,11 @@
     return subclasses;
   }
 
-  /// Returns an iterable over the live classes that extend [cls] _not_
-  /// including [cls] itself.
-  Iterable<ClassElement> strictSubclassesOf(ClassElement cls) {
-    return subclassesOf(cls).where((c) => c != cls);
-  }
-
-  /// Returns an iterable over the live classes that implement [cls] including
-  /// [cls] if it is live.
-  Iterable<ClassElement> subtypesOf(ClassElement cls) {
-    Set<ClassElement> subtypes = _subtypes[cls.declaration];
-    return subtypes != null ? subtypes : const <ClassElement>[];
-  }
-
   /// Returns an iterable over the live classes that implement [cls] _not_
   /// including [cls] if it is live.
   Iterable<ClassElement> strictSubtypesOf(ClassElement cls) {
-    return subtypesOf(cls).where((c) => c != cls);
-  }
-
-  /// Returns `true` if any live class extends [cls].
-  bool hasAnySubclass(ClassElement cls) {
-    return !subclassesOf(cls).isEmpty;
+    Set<ClassElement> subtypes = _subtypes[cls.declaration];
+    return subtypes != null ? subtypes : const <ClassElement>[];
   }
 
   /// Returns `true` if any live class other than [cls] extends [cls].
@@ -198,11 +167,6 @@
     return !strictSubclassesOf(cls).isEmpty;
   }
 
-  /// Returns `true` if any live class implements [cls].
-  bool hasAnySubtype(ClassElement cls) {
-    return !subtypesOf(cls).isEmpty;
-  }
-
   /// Returns `true` if any live class other than [cls] implements [cls].
   bool hasAnyStrictSubtype(ClassElement cls) {
     return !strictSubtypesOf(cls).isEmpty;
@@ -210,9 +174,9 @@
 
   /// Returns `true` if all live classes that implement [cls] extend it.
   bool hasOnlySubclasses(ClassElement cls) {
-    Iterable<ClassElement> subtypes = subtypesOf(cls);
+    Iterable<ClassElement> subtypes = strictSubtypesOf(cls);
     if (subtypes == null) return true;
-    Iterable<ClassElement> subclasses = subclassesOf(cls);
+    Iterable<ClassElement> subclasses = strictSubclassesOf(cls);
     return subclasses != null && (subclasses.length == subtypes.length);
   }
 
diff --git a/pkg/dart2js_incremental/lib/caching_compiler.dart b/pkg/dart2js_incremental/lib/caching_compiler.dart
index 0050ab0..aeab05a 100644
--- a/pkg/dart2js_incremental/lib/caching_compiler.dart
+++ b/pkg/dart2js_incremental/lib/caching_compiler.dart
@@ -65,9 +65,11 @@
         null);
     JavaScriptBackend 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.
-    backend.emitter.oldEmitter
+    emitter
         ..needsClassSupport = true
         ..needsMixinSupport = true
         ..needsLazyInitializer = true
@@ -100,19 +102,20 @@
         ..enqueuer.codegen.hasEnqueuedReflectiveStaticFields = false
         ..compilationFailed = false;
     JavaScriptBackend backend = compiler.backend;
+    full.Emitter emitter = backend.emitter.emitter;
 
     // TODO(ahe): Seems this cache only serves to tell
-    // [OldEmitter.invalidateCaches] if it was invoked on a full compile (in
+    // [emitter.invalidateCaches] if it was invoked on a full compile (in
     // which case nothing should be invalidated), or if it is an incremental
     // compilation (in which case, holders/owners of newly compiled methods
     // must be invalidated).
-    backend.emitter.oldEmitter.cachedElements.add(null);
+    emitter.cachedElements.add(null);
 
     compiler.enqueuer.codegen
         ..newlyEnqueuedElements.clear()
         ..newlySeenSelectors.clear();
 
-    backend.emitter.oldEmitter.nsmEmitter
+    emitter.nsmEmitter
         ..trivialNsmHandlers.clear();
 
     backend.emitter.typeTestRegistry
@@ -121,7 +124,7 @@
         ..rtiNeededClasses.clear()
         ..cachedClassesUsingTypeVariableTests = null;
 
-    backend.emitter.oldEmitter.interceptorEmitter
+    emitter.interceptorEmitter
         ..interceptorInvocationNames.clear();
 
     backend.emitter.nativeEmitter
@@ -130,7 +133,7 @@
 
     backend.emitter.readTypeVariables.clear();
 
-    backend.emitter.oldEmitter
+    emitter
         ..outputBuffers.clear()
         ..classesCollector = null
         ..mangledFieldNames.clear()
@@ -139,16 +142,6 @@
         ..clearCspPrecompiledNodes()
         ..elementDescriptors.clear();
 
-    backend.emitter
-        ..nativeClassesAndSubclasses.clear()
-        ..outputContainsConstantList = false
-        ..neededClasses.clear()
-        ..outputClassLists.clear()
-        ..outputConstantLists.clear()
-        ..outputStaticLists.clear()
-        ..outputStaticNonFinalFieldLists.clear()
-        ..outputLibraryLists.clear();
-
     backend
         ..preMirrorsMethodCount = 0;
 
diff --git a/pkg/dart2js_incremental/lib/dart2js_incremental.dart b/pkg/dart2js_incremental/lib/dart2js_incremental.dart
index 2adb61f..ee04336 100644
--- a/pkg/dart2js_incremental/lib/dart2js_incremental.dart
+++ b/pkg/dart2js_incremental/lib/dart2js_incremental.dart
@@ -26,6 +26,9 @@
 import 'package:compiler/src/js_backend/js_backend.dart' show
     JavaScriptBackend;
 
+import 'package:compiler/src/js_emitter/full_emitter/emitter.dart'
+    as full show Emitter;
+
 import 'package:compiler/src/elements/elements.dart' show
     LibraryElement;
 
diff --git a/pkg/dart2js_incremental/lib/library_updater.dart b/pkg/dart2js_incremental/lib/library_updater.dart
index f111d4a..bd2188b 100644
--- a/pkg/dart2js_incremental/lib/library_updater.dart
+++ b/pkg/dart2js_incremental/lib/library_updater.dart
@@ -66,6 +66,9 @@
     MemberInfo,
     computeMixinClass;
 
+import 'package:compiler/src/js_emitter/full_emitter/emitter.dart'
+    as full show Emitter;
+
 import 'package:compiler/src/js_emitter/model.dart' show
     Class,
     Method;
@@ -155,14 +158,18 @@
 
   void _captureState(Compiler compiler) {
     JavaScriptBackend backend = compiler.backend;
-    _emittedClasses = new Set.from(backend.emitter.neededClasses);
+    Set neededClasses = backend.emitter.neededClasses;
+    if (neededClasses == null) {
+      neededClasses = new Set();
+    }
+    _emittedClasses = new Set.from(neededClasses);
 
     _directlyInstantiatedClasses =
         new Set.from(compiler.codegenWorld.directlyInstantiatedClasses);
 
-    List<ConstantValue> constants =
-        backend.emitter.outputConstantLists[
-            compiler.deferredLoadTask.mainOutputUnit];
+    // This breaks constant tracking of the incremental compiler. It would need
+    // to capture the emitted constants.
+    List<ConstantValue> constants = null;
     if (constants == null) constants = <ConstantValue>[];
     _compiledConstants = new Set<ConstantValue>.identity()..addAll(constants);
   }
@@ -897,9 +904,9 @@
       if (constants != null) {
         for (ConstantValue constant in constants) {
           if (!_compiledConstants.contains(constant)) {
+            full.Emitter fullEmitter = emitter.emitter;
             jsAst.Statement constantInitializer =
-                emitter.oldEmitter.buildConstantInitializer(constant)
-                .toStatement();
+                fullEmitter.buildConstantInitializer(constant).toStatement();
             updates.add(constantInitializer);
           }
         }
@@ -976,9 +983,10 @@
     }
     // A static (or top-level) field.
     if (backend.constants.lazyStatics.contains(element)) {
+      full.Emitter fullEmitter = emitter.emitter;
       jsAst.Expression init =
-          emitter.oldEmitter.buildLazilyInitializedStaticField(
-              element, isolateProperties: namer.currentIsolate);
+          fullEmitter.buildLazilyInitializedStaticField(
+              element, isolateProperties: namer.staticStateHolder);
       if (init == null) {
         throw new StateError("Initializer optimized away for $element");
       }
@@ -1470,7 +1478,10 @@
 
   CodeEmitterTask get emitter => backend.emitter;
 
-  ContainerBuilder get containerBuilder => emitter.oldEmitter.containerBuilder;
+  ContainerBuilder get containerBuilder {
+    full.Emitter fullEmitter = emitter.emitter;
+    return fullEmitter.containerBuilder;
+  }
 
   EnqueueTask get enqueuer => compiler.enqueuer;
 }
@@ -1480,7 +1491,10 @@
 
   EmitterHelper(this.compiler);
 
-  ClassEmitter get classEmitter => backend.emitter.oldEmitter.classEmitter;
+  ClassEmitter get classEmitter {
+    full.Emitter fullEmitter = emitter.emitter;
+    return fullEmitter.classEmitter;
+  }
 
   List<String> computeFields(ClassElement classElement) {
     Class cls = new ProgramBuilder(compiler, namer, emitter)
diff --git a/pkg/pkg.status b/pkg/pkg.status
index f105670..bc0d302 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -89,6 +89,7 @@
 analyzer/test/generated/utilities_test: Pass, Slow # Issue 21628
 analyzer/test/generated/parser_test: Pass, Slow # Issue 21628
 analyzer/test/src/task/dart_test: Pass, Slow # Issue 21628
+analyzer/test/src/task/driver_test: Pass, Slow # Issue 21628
 
 [ $runtime == jsshell ]
 async/test/stream_zip_test: RuntimeError, OK # Timers are not supported.
@@ -161,7 +162,7 @@
 analyzer/test/generated/element_test: Crash # The null object does not have a getter '_element'.
 analyzer/test/generated/incremental_resolver_test: Crash # The null object does not have a getter '_element'.
 analyzer/test/generated/incremental_scanner_test: Crash # The null object does not have a getter '_element'.
-analyzer/test/generated/java_core_test: RuntimeError # receiver.get$_nums is not a function
+analyzer/test/generated/java_core_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
 analyzer/test/generated/non_error_resolver_test: Crash # The null object does not have a getter '_element'.
 analyzer/test/generated/parser_test: Crash # The null object does not have a getter '_element'.
 analyzer/test/generated/resolver_test: Crash # The null object does not have a getter '_element'.
@@ -189,7 +190,7 @@
 analyzer/test/src/task/model_test: Crash # The null object does not have a getter '_element'.
 analyzer/test/src/util/asserts_test: Crash # The null object does not have a getter '_element'.
 analyzer/test/src/util/lru_map_test: Crash # The null object does not have a getter '_element'.
-fixnum/test/int_32_test: RuntimeError # receiver.get$_nums is not a function
-fixnum/test/int_64_test: RuntimeError # receiver.get$_nums is not a function
-typed_data/test/typed_buffers_test/none: RuntimeError # receiver.get$_nums is not a function
-typed_mock/test/typed_mock_test: RuntimeError # receiver.get$_nums is not a function
+fixnum/test/int_32_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+fixnum/test/int_64_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+typed_data/test/typed_buffers_test/none: RuntimeError # receiver._addHashTableEntry$2 is not a function
+typed_mock/test/typed_mock_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index 8ba4a30..54cd64d 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -196,6 +196,7 @@
     default:
       UNREACHABLE();
   }
+  _setmode(fd, _O_BINARY);
   return new File(new FileHandle(fd));
 }
 
diff --git a/runtime/bin/thread.h b/runtime/bin/thread.h
index eb99e10..60dc75f2 100644
--- a/runtime/bin/thread.h
+++ b/runtime/bin/thread.h
@@ -7,6 +7,14 @@
 
 #include "platform/globals.h"
 
+namespace dart {
+namespace bin {
+class Thread;
+class Mutex;
+class Monitor;
+}
+}
+
 // Declare the OS-specific types ahead of defining the generic classes.
 #if defined(TARGET_OS_ANDROID)
 #include "bin/thread_android.h"
diff --git a/runtime/bin/vmservice/loader.dart b/runtime/bin/vmservice/loader.dart
index ce3c9cc..a95df08 100644
--- a/runtime/bin/vmservice/loader.dart
+++ b/runtime/bin/vmservice/loader.dart
@@ -101,6 +101,6 @@
   } else if ((uri.scheme == 'data')) {
     _loadDataUri(sp, id, uri);
   } else {
-    sp.send('Unknown scheme (${uri.scheme}) for $uri');
+    sp.send([id, 'Unknown scheme (${uri.scheme}) for $uri']);
   }
 }
diff --git a/runtime/lib/errors_patch.dart b/runtime/lib/errors_patch.dart
index 01920ed..59a61ec 100644
--- a/runtime/lib/errors_patch.dart
+++ b/runtime/lib/errors_patch.dart
@@ -57,6 +57,18 @@
                    String error_msg)
       native "TypeError_throwNew";
 
+  static _throwNewIfNotLoaded(_LibraryPrefix prefix,
+                              int location,
+                              Object src_value,
+                              String dst_type_name,
+                              String dst_name,
+                              String error_msg) {
+    if (!prefix.isLoaded()) {
+      _throwNew(location, src_value, dst_type_name, dst_name, error_msg);
+    }
+  }
+
+
   String toString() {
     String str = (_errorMsg != null) ? _errorMsg : "";
     if ((_dstName != null) && (_dstName.length > 0)) {
@@ -181,6 +193,19 @@
                                           existingArgumentNames);
   }
 
+  static void _throwNewIfNotLoaded(_LibraryPrefix prefix,
+                                   Object receiver,
+                                   String memberName,
+                                   int invocation_type,
+                                   List arguments,
+                                   List argumentNames,
+                                   List existingArgumentNames) {
+    if (!prefix.isLoaded()) {
+      _throwNew(receiver, memberName, invocation_type, arguments,
+                argumentNames, existingArgumentNames);
+    }
+  }
+
   // Remember the type from the invocation mirror or static compilation
   // analysis when thrown directly with _throwNew. A negative value means
   // that no information is available.
diff --git a/runtime/lib/lib_prefix.dart b/runtime/lib/lib_prefix.dart
index f74dcb1..fb9fe81 100644
--- a/runtime/lib/lib_prefix.dart
+++ b/runtime/lib/lib_prefix.dart
@@ -10,6 +10,7 @@
 
   bool _load() native "LibraryPrefix_load";
   Error _loadError() native "LibraryPrefix_loadError";
+  bool isLoaded() native "LibraryPrefix_isLoaded";
 
   bool _invalidateDependentCode()
       native "LibraryPrefix_invalidateDependentCode";
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 2c43d96..d8693a1 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -378,6 +378,13 @@
 }
 
 
+DEFINE_NATIVE_ENTRY(LibraryPrefix_isLoaded, 1) {
+  const LibraryPrefix& prefix =
+      LibraryPrefix::CheckedHandle(arguments->NativeArgAt(0));
+  return Bool::Get(prefix.is_loaded()).raw();
+}
+
+
 DEFINE_NATIVE_ENTRY(Internal_inquireIs64Bit, 0) {
 #if defined(ARCH_IS_64_BIT)
   return Bool::True().raw();
diff --git a/runtime/observatory/lib/service_common.dart b/runtime/observatory/lib/service_common.dart
index 790efe1..0580f5c 100644
--- a/runtime/observatory/lib/service_common.dart
+++ b/runtime/observatory/lib/service_common.dart
@@ -208,7 +208,8 @@
         return;
       }
       var event = map['event'];
-      postServiceEvent(event, data);
+      var streamId = map['streamId'];
+      postServiceEvent(streamId, event, data);
     });
   }
 
@@ -219,7 +220,8 @@
     }
     var event = map['event'];
     if (event != null) {
-      postServiceEvent(event, null);
+      var streamId = map['streamId'];
+      postServiceEvent(streamId, event, null);
       return;
     }
 
diff --git a/runtime/observatory/lib/src/app/application.dart b/runtime/observatory/lib/src/app/application.dart
index ef565f5..3dc046d 100644
--- a/runtime/observatory/lib/src/app/application.dart
+++ b/runtime/observatory/lib/src/app/application.dart
@@ -23,6 +23,7 @@
   @observable Page currentPage;
   VM _vm;
   VM get vm => _vm;
+
   set vm(VM vm) {
     if (_vm == vm) {
       // Do nothing.
@@ -53,7 +54,8 @@
                 new ServiceEvent.connectionClosed(reason)));
       });
 
-      vm.events.stream.listen(_onEvent);
+      vm.listenEventStream(VM.kIsolateStream, _onEvent);
+      vm.listenEventStream(VM.kDebugStream, _onEvent);
     }
     _vm = vm;
   }
@@ -88,11 +90,9 @@
     switch(event.kind) {
       case ServiceEvent.kIsolateStart:
       case ServiceEvent.kIsolateUpdate:
-      case ServiceEvent.kGraph:
       case ServiceEvent.kBreakpointAdded:
       case ServiceEvent.kBreakpointResolved:
       case ServiceEvent.kBreakpointRemoved:
-      case ServiceEvent.kGC:
       case ServiceEvent.kDebuggerSettingsUpdate:
         // Ignore for now.
         break;
diff --git a/runtime/observatory/lib/src/app/page.dart b/runtime/observatory/lib/src/app/page.dart
index d678926..3a96752 100644
--- a/runtime/observatory/lib/src/app/page.dart
+++ b/runtime/observatory/lib/src/app/page.dart
@@ -191,7 +191,6 @@
       if (element != null) {
         /// Update the page.
         DebuggerPageElement page = element;
-        page.app = app;
         page.isolate = isolate;
       }
     });
diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart
index 2fc89da..31f064a 100644
--- a/runtime/observatory/lib/src/elements/debugger.dart
+++ b/runtime/observatory/lib/src/elements/debugger.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import 'dart:html';
 import 'observatory_element.dart';
-import 'package:observatory/app.dart';
 import 'package:observatory/cli.dart';
 import 'package:observatory/debugger.dart';
 import 'package:observatory/service.dart';
@@ -921,9 +920,6 @@
           }
         }
         Future.wait(pending).then((_) {
-          if (_subscription == null) {
-            _subscription = vm.events.stream.listen(_onEvent);
-          }
           _refreshStack(isolate.pauseEvent).then((_) {
             reportStatus();
           });
@@ -948,7 +944,6 @@
   }
   Isolate get isolate => _isolate;
   Isolate _isolate;
-  var _subscription;
 
   void init() {
     console.newline();
@@ -1080,7 +1075,7 @@
     });
   }
 
-  void _onEvent(ServiceEvent event) {
+  void onEvent(ServiceEvent event) {
     switch(event.kind) {
       case ServiceEvent.kIsolateStart:
         {
@@ -1226,7 +1221,6 @@
 
 @CustomTag('debugger-page')
 class DebuggerPageElement extends ObservatoryElement {
-  @published ObservatoryApplication app;
   @published Isolate isolate;
 
   isolateChanged(oldValue) {
@@ -1240,6 +1234,9 @@
     debugger.page = this;
   }
 
+  Future<StreamSubscription> _isolateSubscriptionFuture;
+  Future<StreamSubscription> _debugSubscriptionFuture;
+
   @override
   void attached() {
     super.attached();
@@ -1267,6 +1264,20 @@
     debugger.input = $['commandline'];
     debugger.input.debugger = debugger;
     debugger.init();
+
+    _isolateSubscriptionFuture =
+        app.vm.listenEventStream(VM.kIsolateStream, debugger.onEvent);
+    _debugSubscriptionFuture =
+        app.vm.listenEventStream(VM.kDebugStream, debugger.onEvent);
+  }
+
+  @override
+  void detached() {
+    cancelFutureSubscription(_isolateSubscriptionFuture);
+    _isolateSubscriptionFuture = null;
+    cancelFutureSubscription(_debugSubscriptionFuture);
+    _debugSubscriptionFuture = null;
+    super.detached();
   }
 }
 
diff --git a/runtime/observatory/lib/src/elements/heap_profile.dart b/runtime/observatory/lib/src/elements/heap_profile.dart
index 243be472..c5dbc76 100644
--- a/runtime/observatory/lib/src/elements/heap_profile.dart
+++ b/runtime/observatory/lib/src/elements/heap_profile.dart
@@ -43,7 +43,7 @@
   var _classTableBody;
 
   @published bool autoRefresh = false;
-  var _subscription;
+  var _subscriptionFuture;
 
   @published Isolate isolate;
   @observable ServiceMap profile;
@@ -93,13 +93,14 @@
     _oldPieChart = new Chart('PieChart',
         shadowRoot.querySelector('#oldPieChart'));
     _classTableBody = shadowRoot.querySelector('#classTableBody');
-    _subscription = app.vm.events.stream.where(
-        (event) => event.isolate == isolate).listen(_onEvent);
+    _subscriptionFuture =
+        app.vm.listenEventStream(VM.kGCStream, _onEvent);
   }
 
   @override
   void detached() {
-    _subscription.cancel();
+    cancelFutureSubscription(_subscriptionFuture);
+    _subscriptionFuture = null;
     super.detached();
   }
 
@@ -108,7 +109,8 @@
   bool refreshAutoQueued = false;
 
   void _onEvent(ServiceEvent event) {
-    if (autoRefresh && event.kind == 'GC') {
+    assert(event.kind == 'GC');
+    if (autoRefresh) {
       if (!refreshAutoPending) {
         refreshAuto();
       } else {
diff --git a/runtime/observatory/lib/src/elements/ports.dart b/runtime/observatory/lib/src/elements/ports.dart
index dbe230e..8f9cb39 100644
--- a/runtime/observatory/lib/src/elements/ports.dart
+++ b/runtime/observatory/lib/src/elements/ports.dart
@@ -5,9 +5,7 @@
 library ports;
 
 import 'dart:async';
-import 'dart:html';
 import 'observatory_element.dart';
-import 'package:observatory/app.dart';
 import 'package:observatory/service.dart';
 import 'package:polymer/polymer.dart';
 
@@ -16,7 +14,7 @@
   PortsPageElement.created() : super.created();
 
   @observable Isolate isolate;
-  @observable /*ObservableList | ServiceObject*/ ports;
+  @observable var /*ObservableList | ServiceObject*/ ports;
 
   void isolateChanged(oldValue) {
     if (isolate != null) {
diff --git a/runtime/observatory/lib/src/elements/service_view.dart b/runtime/observatory/lib/src/elements/service_view.dart
index f0c2062..19554d6 100644
--- a/runtime/observatory/lib/src/elements/service_view.dart
+++ b/runtime/observatory/lib/src/elements/service_view.dart
@@ -97,6 +97,7 @@
             element.object = object;
             return element;
         }
+        break;
       case 'SocketList':
         IOSocketListViewElement element =
             new Element.tag('io-socket-list-view');
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index f3ebd19..0eee58f 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -4,6 +4,17 @@
 
 part of service;
 
+/// Helper function for canceling a Future<StreamSubscription>.
+Future cancelFutureSubscription(
+    Future<StreamSubscription> subscriptionFuture) async {
+  if (subscriptionFuture != null) {
+    var subscription = await subscriptionFuture;
+    return subscription.cancel();
+  } else {
+    return null;
+  }
+}
+
 /// An RpcException represents an exceptional event that happened
 /// while invoking an rpc.
 abstract class RpcException implements Exception {
@@ -426,6 +437,62 @@
   }
 }
 
+class _EventStreamState {
+  VM _vm;
+  String streamId;
+
+  Function _onDone;
+
+  // A list of all subscribed controllers for this stream.
+  List _controllers = [];
+
+  // Completes when the listen rpc is finished.
+  Future _listenFuture;
+
+  // Completes when then cancel rpc is finished.
+  Future _cancelFuture;
+
+  _EventStreamState(this._vm, this.streamId, this._onDone);
+
+  Future _cancelController(StreamController controller) {
+    _controllers.remove(controller);
+    if (_controllers.isEmpty) {
+      assert(_listenFuture != null);
+      _listenFuture = null;
+      _cancelFuture = _vm._streamCancel(streamId);
+      _cancelFuture.then((_) {
+        if (_controllers.isEmpty) {
+          // No new listeners showed up during cancelation.
+          _onDone();
+        }
+      });
+    }
+    // No need to wait for _cancelFuture here.
+    return new Future.value(null);
+  }
+
+  Future<Stream> addStream() async {
+    var controller;
+    controller = new StreamController(
+        onCancel:() => _cancelController(controller));
+    _controllers.add(controller);
+    if (_cancelFuture != null) {
+      await _cancelFuture;
+    }
+    if (_listenFuture == null) {
+      _listenFuture = _vm._streamListen(streamId);
+    }
+    await _listenFuture;
+    return controller.stream;
+  }
+
+  void addEvent(ServiceEvent event) {
+    for (var controller in _controllers) {
+      controller.add(event);
+    }
+  }
+}
+
 /// State for a VM being inspected.
 abstract class VM extends ServiceObjectOwner {
   @reflectable VM get vm => this;
@@ -459,10 +526,7 @@
     update(toObservable({'id':'vm', 'type':'@VM'}));
   }
 
-  final StreamController<ServiceEvent> events =
-      new StreamController.broadcast();
-
-  void postServiceEvent(Map response, ByteData data) {
+  void postServiceEvent(String streamId, Map response, ByteData data) {
     var map = toObservable(response);
     assert(!map.containsKey('_data'));
     if (data != null) {
@@ -475,18 +539,22 @@
     }
 
     var eventIsolate = map['isolate'];
+    var event;
     if (eventIsolate == null) {
-      var event = new ServiceObject._fromMap(vm, map);
-      events.add(event);
+      event = new ServiceObject._fromMap(vm, map);
     } else {
       // getFromMap creates the Isolate if it hasn't been seen already.
       var isolate = getFromMap(map['isolate']);
-      var event = new ServiceObject._fromMap(isolate, map);
+      event = new ServiceObject._fromMap(isolate, map);
       if (event.kind == ServiceEvent.kIsolateExit) {
         _removeIsolate(isolate.id);
       }
-      isolate._onEvent(event);
-      events.add(event);
+    }
+    var eventStream = _eventStreams[streamId];
+    if (eventStream != null) {
+      eventStream.addEvent(event);
+    } else {
+      Logger.root.warning("Ignoring unexpected event on stream '${streamId}'");
     }
   }
 
@@ -586,16 +654,20 @@
     });
   }
 
+  void _dispatchEventToIsolate(ServiceEvent event) {
+    var isolate = event.isolate;
+    if (isolate != null) {
+      isolate._onEvent(event);
+    }
+  }
+
   Future<ObservableMap> _fetchDirect() async {
     if (!loaded) {
-      // TODO(turnidge): Instead of always listening to all streams,
-      // implement a stream abstraction in the service library so
-      // that we only subscribe to the streams we want.
-      await _streamListen('Isolate');
-      await _streamListen('Debug');
-      await _streamListen('GC');
-      await _streamListen('_Echo');
-      await _streamListen('_Graph');
+      // The vm service relies on these events to keep the VM and
+      // Isolate types up to date.
+      await listenEventStream(kIsolateStream, _dispatchEventToIsolate);
+      await listenEventStream(kDebugStream, _dispatchEventToIsolate);
+      await listenEventStream(_kGraphStream, _dispatchEventToIsolate);
     }
     return await invokeRpcNoUpgrade('getVM', {});
   }
@@ -611,6 +683,37 @@
     return invokeRpc('streamListen', params);
   }
 
+  Future<ServiceObject> _streamCancel(String streamId) {
+    Map params = {
+      'streamId': streamId,
+    };
+    return invokeRpc('streamCancel', params);
+  }
+
+  // A map from stream id to event stream state.
+  Map<String,_EventStreamState> _eventStreams = {};
+
+  // Well-known stream ids.
+  static const kIsolateStream = 'Isolate';
+  static const kDebugStream = 'Debug';
+  static const kGCStream = 'GC';
+  static const _kGraphStream = '_Graph';
+
+  /// Returns a single-subscription Stream object for a VM event stream.
+  Future<Stream> getEventStream(String streamId) async {
+    var eventStream = _eventStreams.putIfAbsent(
+        streamId, () => new _EventStreamState(
+            this, streamId, () => _eventStreams.remove(streamId)));
+    return eventStream.addStream();
+  }
+
+  /// Helper function for listening to an event stream.
+  Future<StreamSubscription> listenEventStream(String streamId,
+                                               Function function) async {
+    var stream = await getEventStream(streamId);
+    return stream.listen(function);
+  }
+
   /// Force the VM to disconnect.
   void disconnect();
   /// Completes when the VM first connects.
diff --git a/runtime/observatory/tests/service/allocations_test.dart b/runtime/observatory/tests/service/allocations_test.dart
index 0882edc..4708811 100644
--- a/runtime/observatory/tests/service/allocations_test.dart
+++ b/runtime/observatory/tests/service/allocations_test.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 2014, 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=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 library allocations_test;
 
diff --git a/runtime/observatory/tests/service/async_generator_breakpoint_test.dart b/runtime/observatory/tests/service/async_generator_breakpoint_test.dart
index c8a33e3..474b54b 100644
--- a/runtime/observatory/tests/service/async_generator_breakpoint_test.dart
+++ b/runtime/observatory/tests/service/async_generator_breakpoint_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --verbose-debug
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override --verbose-debug
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
@@ -69,7 +69,8 @@
         expect(result.valueAsString, equals('true'));
       });
 
-  await for (ServiceEvent event in isolate.vm.events.stream) {
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+  await for (ServiceEvent event in stream) {
     if (event.kind == ServiceEvent.kPauseBreakpoint) {
       var bp = event.breakpoint;
       print('Hit $bp');
diff --git a/runtime/observatory/tests/service/bad_web_socket_address_test.dart b/runtime/observatory/tests/service/bad_web_socket_address_test.dart
index d328312..946a596 100644
--- a/runtime/observatory/tests/service/bad_web_socket_address_test.dart
+++ b/runtime/observatory/tests/service/bad_web_socket_address_test.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 2014, 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=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:logging/logging.dart';
 import "package:observatory/service_io.dart";
diff --git a/runtime/observatory/tests/service/break_on_activation_test.dart b/runtime/observatory/tests/service/break_on_activation_test.dart
index b266954..7de3d76 100644
--- a/runtime/observatory/tests/service/break_on_activation_test.dart
+++ b/runtime/observatory/tests/service/break_on_activation_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
@@ -54,14 +54,14 @@
 
   var breaksHit = 0;
 
-  var subscription;
-  subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
-    if (event.kind == ServiceEvent.kPauseBreakpoint) {
-      print("Hit breakpoint ${event.breakpoint}");
-      breaksHit++;
-      isolate.resume();
-    }
-  });
+  var subscriptionFuture = isolate.vm.listenEventStream(
+      VM.kDebugStream, (ServiceEvent event) {
+        if (event.kind == ServiceEvent.kPauseBreakpoint) {
+          print("Hit breakpoint ${event.breakpoint}");
+          breaksHit++;
+          isolate.resume();
+        }
+      });
 
   valueOfField(String name) async {
     var field = rootLib.variables.singleWhere((v) => v.name == name);
@@ -91,7 +91,7 @@
   expect(res is Instance, isTrue); // Not error.
   expect(breaksHit, equals(1));
 
-  await subscription.cancel();
+  await cancelFutureSubscription(subscriptionFuture);
 },
 
 (Isolate isolate) async {
@@ -99,14 +99,14 @@
 
   var breaksHit = 0;
 
-  var subscription;
-  subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
-    if (event.kind == ServiceEvent.kPauseBreakpoint) {
-      print("Hit breakpoint ${event.breakpoint}");
-      breaksHit++;
-      isolate.resume();
-    }
-  });
+  var subscriptionFuture = isolate.vm.listenEventStream(
+      VM.kDebugStream, (ServiceEvent event) {
+        if (event.kind == ServiceEvent.kPauseBreakpoint) {
+          print("Hit breakpoint ${event.breakpoint}");
+          breaksHit++;
+          isolate.resume();
+        }
+      });
 
   valueOfField(String name) async {
     var field = rootLib.variables.singleWhere((v) => v.name == name);
@@ -135,7 +135,7 @@
   expect(res is Instance, isTrue); // Not error.
   expect(breaksHit, equals(1));
 
-  await subscription.cancel();
+  await cancelFutureSubscription(subscriptionFuture);
 },
 
 (Isolate isolate) async {
@@ -143,14 +143,14 @@
 
   var breaksHit = 0;
 
-  var subscription;
-  subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
-    if (event.kind == ServiceEvent.kPauseBreakpoint) {
-      print("Hit breakpoint ${event.breakpoint}");
-      breaksHit++;
-      isolate.resume();
-    }
-  });
+  var subscriptionFuture = isolate.vm.listenEventStream(
+      VM.kDebugStream, (ServiceEvent event) {
+        if (event.kind == ServiceEvent.kPauseBreakpoint) {
+          print("Hit breakpoint ${event.breakpoint}");
+          breaksHit++;
+          isolate.resume();
+        }
+      });
 
   valueOfField(String name) async {
     var field = rootLib.variables.singleWhere((v) => v.name == name);
@@ -200,7 +200,7 @@
   expect(res is Instance, isTrue); // Not error.
   expect(breaksHit, equals(4));
 
-  await subscription.cancel();
+  await cancelFutureSubscription(subscriptionFuture);
 },
 
 ];
diff --git a/runtime/observatory/tests/service/caching_test.dart b/runtime/observatory/tests/service/caching_test.dart
index aafc7ef..196bab4 100644
--- a/runtime/observatory/tests/service/caching_test.dart
+++ b/runtime/observatory/tests/service/caching_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 // If caching is working properly, the coverage data will go into the same
 // Script object from which we requested coverage data, instead of a new
diff --git a/runtime/observatory/tests/service/code_test.dart b/runtime/observatory/tests/service/code_test.dart
index 28e2f86..bffbb79 100644
--- a/runtime/observatory/tests/service/code_test.dart
+++ b/runtime/observatory/tests/service/code_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
@@ -34,11 +34,15 @@
   return isolate.rootLibrary.load().then((_) {
       // Set up a listener to wait for breakpoint events.
       Completer completer = new Completer();
-      isolate.vm.events.stream.listen((ServiceEvent event) {
-        if (event.kind == ServiceEvent.kPauseBreakpoint) {
-          print('Breakpoint reached');
-          completer.complete();
-        }
+      isolate.vm.getEventStream(VM.kDebugStream).then((stream) {
+        var subscription;
+        subscription = stream.listen((ServiceEvent event) {
+          if (event.kind == ServiceEvent.kPauseBreakpoint) {
+            print('Breakpoint reached');
+            subscription.cancel();
+            completer.complete();
+          }
+        });
       });
 
       // Add the breakpoint.
diff --git a/runtime/observatory/tests/service/command_test.dart b/runtime/observatory/tests/service/command_test.dart
index 8e57723..9403662 100644
--- a/runtime/observatory/tests/service/command_test.dart
+++ b/runtime/observatory/tests/service/command_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'dart:async';
 
diff --git a/runtime/observatory/tests/service/contexts_test.dart b/runtime/observatory/tests/service/contexts_test.dart
index bf593f4..2a34ba0 100644
--- a/runtime/observatory/tests/service/contexts_test.dart
+++ b/runtime/observatory/tests/service/contexts_test.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 2014, 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=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 library inbound_references_test;
 
diff --git a/runtime/observatory/tests/service/coverage_test.dart b/runtime/observatory/tests/service/coverage_test.dart
index 45a60a8..9ae233f 100644
--- a/runtime/observatory/tests/service/coverage_test.dart
+++ b/runtime/observatory/tests/service/coverage_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
@@ -57,11 +57,15 @@
   return isolate.rootLibrary.load().then((_) {
       // Set up a listener to wait for breakpoint events.
       Completer completer = new Completer();
-      isolate.vm.events.stream.listen((ServiceEvent event) {
-        if (event.kind == ServiceEvent.kPauseBreakpoint) {
-          print('Breakpoint reached');
-          completer.complete();
-        }
+      isolate.vm.getEventStream(VM.kDebugStream).then((stream) {
+        var subscription;
+        subscription = stream.listen((ServiceEvent event) {
+          if (event.kind == ServiceEvent.kPauseBreakpoint) {
+            print('Breakpoint reached');
+            completer.complete();
+            subscription.cancel();
+          }
+        });
       });
 
       // Create a timer to set a breakpoint with a short delay.
diff --git a/runtime/observatory/tests/service/debugger_inspect_test.dart b/runtime/observatory/tests/service/debugger_inspect_test.dart
index e6b8e9e..3037abe 100644
--- a/runtime/observatory/tests/service/debugger_inspect_test.dart
+++ b/runtime/observatory/tests/service/debugger_inspect_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
@@ -22,12 +22,11 @@
 
 (Isolate isolate) async {
   Completer completer = new Completer();
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
   var subscription;
-  subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
-    print(event);
+  subscription = stream.listen((ServiceEvent event) {
     if (event.kind == ServiceEvent.kInspect) {
       expect((event.inspectee as Instance).clazz.name, equals('Point'));
-
       subscription.cancel();
       completer.complete();
     }
diff --git a/runtime/observatory/tests/service/debugger_location_test.dart b/runtime/observatory/tests/service/debugger_location_test.dart
index 7c4de5b..0672907 100644
--- a/runtime/observatory/tests/service/debugger_location_test.dart
+++ b/runtime/observatory/tests/service/debugger_location_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:observatory/debugger.dart';
@@ -56,10 +56,14 @@
   return isolate.rootLibrary.load().then((_) {
       // Listen for breakpoint event.
       Completer completer = new Completer();
-      isolate.vm.events.stream.listen((ServiceEvent event) {
-        if (event.kind == ServiceEvent.kPauseBreakpoint) {
-          completer.complete();
-        }
+      isolate.vm.getEventStream(VM.kDebugStream).then((stream) {
+        var subscription;
+        subscription = stream.listen((ServiceEvent event) {
+          if (event.kind == ServiceEvent.kPauseBreakpoint) {
+            subscription.cancel();
+            completer.complete();
+          }
+        });
       });
 
       // Add the breakpoint.
diff --git a/runtime/observatory/tests/service/debugging_inlined_finally_test.dart b/runtime/observatory/tests/service/debugging_inlined_finally_test.dart
index 85d910b..886b368 100644
--- a/runtime/observatory/tests/service/debugging_inlined_finally_test.dart
+++ b/runtime/observatory/tests/service/debugging_inlined_finally_test.dart
@@ -1,12 +1,11 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
 import 'test_helper.dart';
-import 'dart:async';
 import 'dart:developer';
 
 testFunction() {
@@ -17,13 +16,13 @@
     try {
       for (int i = 0; i < 10; i++) {
         var x = () => i + a + b;
-        return x;  // line 20
+        return x;  // line 19
       }
     } finally {
-      b = 10;  // line 23
+      b = 10;  // line 22
     }
   } finally {
-    a = 1;  // line 26
+    a = 1;  // line 25
   }
 }
 
@@ -45,32 +44,32 @@
 
   // Add 3 breakpoints.
   {
-    var result = await isolate.addBreakpoint(script, 20);
+    var result = await isolate.addBreakpoint(script, 19);
     expect(result is Breakpoint, isTrue);
     Breakpoint bpt = result;
     expect(bpt.type, equals('Breakpoint'));
     expect(bpt.location.script.id, equals(script.id));
-    expect(bpt.location.script.tokenToLine(bpt.location.tokenPos), equals(20));
+    expect(bpt.location.script.tokenToLine(bpt.location.tokenPos), equals(19));
     expect(isolate.breakpoints.length, equals(1));
   }
 
   {
-    var result = await isolate.addBreakpoint(script, 23);
+    var result = await isolate.addBreakpoint(script, 22);
     expect(result is Breakpoint, isTrue);
     Breakpoint bpt = result;
     expect(bpt.type, equals('Breakpoint'));
     expect(bpt.location.script.id, equals(script.id));
-    expect(bpt.location.script.tokenToLine(bpt.location.tokenPos), equals(23));
+    expect(bpt.location.script.tokenToLine(bpt.location.tokenPos), equals(22));
     expect(isolate.breakpoints.length, equals(2));
   }
 
   {
-    var result = await isolate.addBreakpoint(script, 26);
+    var result = await isolate.addBreakpoint(script, 25);
     expect(result is Breakpoint, isTrue);
     Breakpoint bpt = result;
     expect(bpt.type, equals('Breakpoint'));
     expect(bpt.location.script.id, equals(script.id));
-    expect(bpt.location.script.tokenToLine(bpt.location.tokenPos), equals(26));
+    expect(bpt.location.script.tokenToLine(bpt.location.tokenPos), equals(25));
     expect(isolate.breakpoints.length, equals(3));
   }
 
@@ -81,42 +80,42 @@
 
 hasStoppedAtBreakpoint,
 
-// We are at the breakpoint on line 20.
+// We are at the breakpoint on line 19.
 (Isolate isolate) async {
   ServiceMap stack = await isolate.getStack();
   expect(stack.type, equals('Stack'));
   expect(stack['frames'].length, greaterThanOrEqualTo(1));
 
   Script script = stack['frames'][0].location.script;
-  expect(script.tokenToLine(stack['frames'][0].location.tokenPos), equals(20));
+  expect(script.tokenToLine(stack['frames'][0].location.tokenPos), equals(19));
 },
 
 resumeIsolate,
 
 hasStoppedAtBreakpoint,
 
-// We are at the breakpoint on line 23.
+// We are at the breakpoint on line 22.
 (Isolate isolate) async {
   ServiceMap stack = await isolate.getStack();
   expect(stack.type, equals('Stack'));
   expect(stack['frames'].length, greaterThanOrEqualTo(1));
 
   Script script = stack['frames'][0].location.script;
-  expect(script.tokenToLine(stack['frames'][0].location.tokenPos), equals(23));
+  expect(script.tokenToLine(stack['frames'][0].location.tokenPos), equals(22));
 },
 
 resumeIsolate,
 
 hasStoppedAtBreakpoint,
 
-// We are at the breakpoint on line 26.
+// We are at the breakpoint on line 25.
 (Isolate isolate) async {
   ServiceMap stack = await isolate.getStack();
   expect(stack.type, equals('Stack'));
   expect(stack['frames'].length, greaterThanOrEqualTo(1));
 
   Script script = stack['frames'][0].location.script;
-  expect(script.tokenToLine(stack['frames'][0].location.tokenPos), equals(26));
+  expect(script.tokenToLine(stack['frames'][0].location.tokenPos), equals(25));
 },
 
 resumeIsolate,
diff --git a/runtime/observatory/tests/service/debugging_test.dart b/runtime/observatory/tests/service/debugging_test.dart
index e9e2c11..e20e203 100644
--- a/runtime/observatory/tests/service/debugging_test.dart
+++ b/runtime/observatory/tests/service/debugging_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
@@ -28,8 +28,9 @@
 // Pause
 (Isolate isolate) async {
   Completer completer = new Completer();
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
   var subscription;
-  subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
+  subscription = stream.listen((ServiceEvent event) {
     if (event.kind == ServiceEvent.kPauseInterrupted) {
       subscription.cancel();
       completer.complete();
@@ -42,8 +43,9 @@
 // Resume
 (Isolate isolate) async {
   Completer completer = new Completer();
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
   var subscription;
-  subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
+  subscription = stream.listen((ServiceEvent event) {
     if (event.kind == ServiceEvent.kResume) {
       subscription.cancel();
       completer.complete();
@@ -59,8 +61,9 @@
 
   // Set up a listener to wait for breakpoint events.
   Completer completer = new Completer();
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
   var subscription;
-  subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
+  subscription = stream.listen((ServiceEvent event) {
     if (event.kind == ServiceEvent.kPauseBreakpoint) {
       print('Breakpoint reached');
       subscription.cancel();
@@ -98,8 +101,9 @@
 (Isolate isolate) async {
   // Set up a listener to wait for breakpoint events.
   Completer completer = new Completer();
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
   var subscription;
-  subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
+  subscription = stream.listen((ServiceEvent event) {
     if (event.kind == ServiceEvent.kPauseBreakpoint) {
       print('Breakpoint reached');
       subscription.cancel();
@@ -126,8 +130,9 @@
 (Isolate isolate) async {
   // Set up a listener to wait for breakpoint events.
   Completer completer = new Completer();
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
   var subscription;
-  subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
+  subscription = stream.listen((ServiceEvent event) {
     if (event.kind == ServiceEvent.kBreakpointRemoved) {
       print('Breakpoint removed');
       expect(isolate.breakpoints.length, equals(0));
@@ -145,8 +150,9 @@
 // Resume
 (Isolate isolate) async {
   Completer completer = new Completer();
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
   var subscription;
-  subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
+  subscription = stream.listen((ServiceEvent event) {
     if (event.kind == ServiceEvent.kResume) {
       subscription.cancel();
       completer.complete();
@@ -160,8 +166,9 @@
 (Isolate isolate) async {
   // Set up a listener to wait for breakpoint events.
   Completer completer = new Completer();
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
   var subscription;
-  subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
+  subscription = stream.listen((ServiceEvent event) {
     if (event.kind == ServiceEvent.kPauseBreakpoint) {
       print('Breakpoint reached');
       subscription.cancel();
diff --git a/runtime/observatory/tests/service/dominator_tree_test.dart b/runtime/observatory/tests/service/dominator_tree_test.dart
index c5f62e8..ef4fcd8 100644
--- a/runtime/observatory/tests/service/dominator_tree_test.dart
+++ b/runtime/observatory/tests/service/dominator_tree_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/echo_test.dart b/runtime/observatory/tests/service/echo_test.dart
index eab5888..b64b177 100644
--- a/runtime/observatory/tests/service/echo_test.dart
+++ b/runtime/observatory/tests/service/echo_test.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 2014, 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=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'dart:async';
 import 'package:observatory/service_io.dart';
@@ -22,19 +22,22 @@
     expect(result['text'], equals('hello'));
   }),
 
-(Isolate isolate) {
+(Isolate isolate) async {
   Completer completer = new Completer();
-  isolate.vm.events.stream.listen((ServiceEvent event) {
-    if (event.kind == '_Echo') {
-      expect(event.data.lengthInBytes, equals(3));
-      expect(event.data.getUint8(0), equals(0));
-      expect(event.data.getUint8(1), equals(128));
-      expect(event.data.getUint8(2), equals(255));
-      completer.complete();
-    }
+  var stream = await isolate.vm.getEventStream('_Echo');
+  var subscription;
+  subscription = stream.listen((ServiceEvent event) {
+    assert(event.kind == '_Echo');
+    expect(event.data.lengthInBytes, equals(3));
+    expect(event.data.getUint8(0), equals(0));
+    expect(event.data.getUint8(1), equals(128));
+    expect(event.data.getUint8(2), equals(255));
+    subscription.cancel();
+    completer.complete();
   });
-  isolate.invokeRpc('_triggerEchoEvent', { 'text': 'hello' });
-  return completer.future;
+
+  await isolate.invokeRpc('_triggerEchoEvent', { 'text': 'hello' });
+  await completer.future;
 },
 
 ];
diff --git a/runtime/observatory/tests/service/eval_test.dart b/runtime/observatory/tests/service/eval_test.dart
index aac5d3f..8414aa7 100644
--- a/runtime/observatory/tests/service/eval_test.dart
+++ b/runtime/observatory/tests/service/eval_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
@@ -34,11 +34,15 @@
   return isolate.rootLibrary.load().then((_) {
       // Set up a listener to wait for breakpoint events.
       Completer completer = new Completer();
-      isolate.vm.events.stream.listen((ServiceEvent event) {
-        if (event.kind == ServiceEvent.kPauseBreakpoint) {
-          print('Breakpoint reached');
-          completer.complete();
-        }
+      isolate.vm.getEventStream(VM.kDebugStream).then((stream) {
+        var subscription;
+        subscription = stream.listen((ServiceEvent event) {
+          if (event.kind == ServiceEvent.kPauseBreakpoint) {
+            print('Breakpoint reached');
+            subscription.cancel();
+            completer.complete();
+          }
+        });
       });
 
       // Add the breakpoint.
diff --git a/runtime/observatory/tests/service/evaluate_activation_test.dart b/runtime/observatory/tests/service/evaluate_activation_test.dart
index 7862026..cffc6fa 100644
--- a/runtime/observatory/tests/service/evaluate_activation_test.dart
+++ b/runtime/observatory/tests/service/evaluate_activation_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
@@ -78,8 +78,9 @@
   expect(bpt is Breakpoint, isTrue);  // I.e, not null.
 
   bool hitBreakpoint = false;
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
   var sub;
-  sub = isolate.vm.events.stream.listen((ServiceEvent event) async {
+  sub = stream.listen((ServiceEvent event) async {
     print("Event $event");
     if (event.kind == ServiceEvent.kPauseBreakpoint) {
       var frameNumber = 1, r;
@@ -126,8 +127,9 @@
   expect(bpt is Breakpoint, isTrue);  // I.e, not null.
 
   bool hitBreakpoint = false;
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
   var sub;
-  sub = isolate.vm.events.stream.listen((ServiceEvent event) async {
+  sub = stream.listen((ServiceEvent event) async {
     print("Event $event");
     if (event.kind == ServiceEvent.kPauseBreakpoint) {
       var frameNumber = 1, r;
@@ -174,8 +176,9 @@
   expect(bpt is Breakpoint, isTrue);  // I.e, not null.
 
   bool hitBreakpoint = false;
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
   var sub;
-  sub = isolate.vm.events.stream.listen((ServiceEvent event) async {
+  sub = stream.listen((ServiceEvent event) async {
     print("Event $event");
     if (event.kind == ServiceEvent.kPauseBreakpoint) {
       var frameNumber = 1, r;
@@ -215,8 +218,9 @@
   expect(bpt is Breakpoint, isTrue);  // I.e, not null.
 
   bool hitBreakpoint = false;
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
   var sub;
-  sub = isolate.vm.events.stream.listen((ServiceEvent event) async {
+  sub = stream.listen((ServiceEvent event) async {
     print("Event $event");
     if (event.kind == ServiceEvent.kPauseBreakpoint) {
       var frameNumber = 1, r;
diff --git a/runtime/observatory/tests/service/gc_test.dart b/runtime/observatory/tests/service/gc_test.dart
index 9d93b0a..fba9ebd 100644
--- a/runtime/observatory/tests/service/gc_test.dart
+++ b/runtime/observatory/tests/service/gc_test.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 2014, 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=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'test_helper.dart';
@@ -26,13 +26,16 @@
   Completer completer = new Completer();
   // Expect at least this many GC events.
   int gcCountdown = 3;
-  isolate.vm.events.stream.listen((ServiceEvent event) {
-    if (event.kind == ServiceEvent.kGC) {
+  isolate.vm.getEventStream(VM.kGCStream).then((stream) {
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      assert(event.kind == ServiceEvent.kGC);
       print('Received GC event');
       if (--gcCountdown == 0) {
+        subscription.cancel();
         completer.complete();
       }
-    }
+    });
   });
   return completer.future;
 },
diff --git a/runtime/observatory/tests/service/get_allocation_profile_rpc_test.dart b/runtime/observatory/tests/service/get_allocation_profile_rpc_test.dart
index 0217fa5..10ffc2c 100644
--- a/runtime/observatory/tests/service/get_allocation_profile_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_allocation_profile_rpc_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/get_flag_list_rpc_test.dart b/runtime/observatory/tests/service/get_flag_list_rpc_test.dart
index f05def6..db3040c 100644
--- a/runtime/observatory/tests/service/get_flag_list_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_flag_list_rpc_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/get_heap_map_rpc_test.dart b/runtime/observatory/tests/service/get_heap_map_rpc_test.dart
index 5247ca9..9999ce6 100644
--- a/runtime/observatory/tests/service/get_heap_map_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_heap_map_rpc_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/get_instances_rpc_test.dart b/runtime/observatory/tests/service/get_instances_rpc_test.dart
index ee2df7f..da26013 100644
--- a/runtime/observatory/tests/service/get_instances_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_instances_rpc_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/get_isolate_rpc_test.dart b/runtime/observatory/tests/service/get_isolate_rpc_test.dart
index bbdeabe..153cbb6 100644
--- a/runtime/observatory/tests/service/get_isolate_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_isolate_rpc_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/get_object_rpc_test.dart b/runtime/observatory/tests/service/get_object_rpc_test.dart
index b1df709..18d984d 100644
--- a/runtime/observatory/tests/service/get_object_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_object_rpc_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 library get_object_rpc_test;
 
diff --git a/runtime/observatory/tests/service/get_ports_rpc_test.dart b/runtime/observatory/tests/service/get_ports_rpc_test.dart
index 58081a0..1c08a16 100644
--- a/runtime/observatory/tests/service/get_ports_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_ports_rpc_test.dart
@@ -1,11 +1,10 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 library get_ports_rpc_test;
 
-import 'dart:async';
 import 'dart:isolate' hide Isolate;
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/get_retained_size_rpc_test.dart b/runtime/observatory/tests/service/get_retained_size_rpc_test.dart
index 93740f3..1ead7cf 100644
--- a/runtime/observatory/tests/service/get_retained_size_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_retained_size_rpc_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/get_retaining_path_rpc_test.dart b/runtime/observatory/tests/service/get_retaining_path_rpc_test.dart
index 1e92dfd..dbb43c7 100644
--- a/runtime/observatory/tests/service/get_retaining_path_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_retaining_path_rpc_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/get_stack_rpc_test.dart b/runtime/observatory/tests/service/get_stack_rpc_test.dart
index 45b3112..f3736e6 100644
--- a/runtime/observatory/tests/service/get_stack_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_stack_rpc_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/get_version_rpc_test.dart b/runtime/observatory/tests/service/get_version_rpc_test.dart
index 92b8c06..cb03444 100644
--- a/runtime/observatory/tests/service/get_version_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_version_rpc_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/get_vm_rpc_test.dart b/runtime/observatory/tests/service/get_vm_rpc_test.dart
index 5b03dde..95481c5 100644
--- a/runtime/observatory/tests/service/get_vm_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_vm_rpc_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/graph_test.dart b/runtime/observatory/tests/service/graph_test.dart
index c3de708..feac00c 100644
--- a/runtime/observatory/tests/service/graph_test.dart
+++ b/runtime/observatory/tests/service/graph_test.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 2014, 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=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/object_graph.dart';
 import 'package:observatory/service_io.dart';
diff --git a/runtime/observatory/tests/service/inbound_references_test.dart b/runtime/observatory/tests/service/inbound_references_test.dart
index 5807c4c..ba97490 100644
--- a/runtime/observatory/tests/service/inbound_references_test.dart
+++ b/runtime/observatory/tests/service/inbound_references_test.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 2014, 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=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 library inbound_references_test;
 
diff --git a/runtime/observatory/tests/service/isolate_lifecycle_test.dart b/runtime/observatory/tests/service/isolate_lifecycle_test.dart
index 3180137..dbacef8 100644
--- a/runtime/observatory/tests/service/isolate_lifecycle_test.dart
+++ b/runtime/observatory/tests/service/isolate_lifecycle_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'dart:async';
 import 'dart:isolate' as I;
@@ -54,7 +54,8 @@
   (VM vm) async {
     // Wait for the testee to start all of the isolates.
     if (vm.isolates.length != spawnCount + 1) {
-      await processServiceEvents(vm, (event, sub, completer) {
+      await processServiceEvents(vm, VM.kIsolateStream,
+                                 (event, sub, completer) {
         if (event.kind == ServiceEvent.kIsolateStart) {
           if (vm.isolates.length == spawnCount + 1) {
             sub.cancel();
@@ -76,7 +77,8 @@
   (VM vm) async {
     // Wait for all spawned isolates to hit pause-at-exit.
     if (numPaused(vm) != spawnCount) {
-      await processServiceEvents(vm, (event, sub, completer) {
+      await processServiceEvents(vm, VM.kDebugStream,
+                                 (event, sub, completer) {
         if (event.kind == ServiceEvent.kPauseExit) {
           if (numPaused(vm) == spawnCount) {
             sub.cancel();
@@ -92,7 +94,8 @@
 
   (VM vm) async {
     var resumedReceived = 0;
-    var eventsDone = processServiceEvents(vm, (event, sub, completer) {
+    var eventsDone = processServiceEvents(vm, VM.kIsolateStream,
+                                          (event, sub, completer) {
       if (event.kind == ServiceEvent.kIsolateExit) {
         resumedReceived++;
         if (resumedReceived == resumeCount) {
diff --git a/runtime/observatory/tests/service/library_dependency_test.dart b/runtime/observatory/tests/service/library_dependency_test.dart
index 4547e96..b198f01 100644
--- a/runtime/observatory/tests/service/library_dependency_test.dart
+++ b/runtime/observatory/tests/service/library_dependency_test.dart
@@ -1,13 +1,11 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
-import 'package:observatory/debugger.dart';
 import 'package:unittest/unittest.dart';
 import 'test_helper.dart';
-import 'dart:async';
 
 export 'dart:collection';
 import 'dart:mirrors' as mirrors;
diff --git a/runtime/observatory/tests/service/malformed_test.dart b/runtime/observatory/tests/service/malformed_test.dart
index 3d224719..6cf5302 100644
--- a/runtime/observatory/tests/service/malformed_test.dart
+++ b/runtime/observatory/tests/service/malformed_test.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 2014, 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=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/metrics_test.dart b/runtime/observatory/tests/service/metrics_test.dart
index 2d3272f..0708d8e 100644
--- a/runtime/observatory/tests/service/metrics_test.dart
+++ b/runtime/observatory/tests/service/metrics_test.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 2014, 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=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/mirror_references_test.dart b/runtime/observatory/tests/service/mirror_references_test.dart
index 28a15c0f..dacb412 100644
--- a/runtime/observatory/tests/service/mirror_references_test.dart
+++ b/runtime/observatory/tests/service/mirror_references_test.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 2014, 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=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 library vm_references_test;
 
diff --git a/runtime/observatory/tests/service/native_metrics_test.dart b/runtime/observatory/tests/service/native_metrics_test.dart
index 4a7182e..39f2c37 100644
--- a/runtime/observatory/tests/service/native_metrics_test.dart
+++ b/runtime/observatory/tests/service/native_metrics_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/pause_on_exceptions_test.dart b/runtime/observatory/tests/service/pause_on_exceptions_test.dart
index d8926fe..e5528bc 100644
--- a/runtime/observatory/tests/service/pause_on_exceptions_test.dart
+++ b/runtime/observatory/tests/service/pause_on_exceptions_test.dart
@@ -34,8 +34,9 @@
   var onPaused = null;
   var onResume = null;
 
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
   var subscription;
-  subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
+  subscription = stream.listen((ServiceEvent event) {
     print("Event $event");
     if (event.kind == ServiceEvent.kPauseException) {
       if (onPaused == null) throw "Unexpected pause event $event";
diff --git a/runtime/observatory/tests/service/set_library_debuggable_rpc_test.dart b/runtime/observatory/tests/service/set_library_debuggable_rpc_test.dart
index 0f9aa40..fea9fed 100644
--- a/runtime/observatory/tests/service/set_library_debuggable_rpc_test.dart
+++ b/runtime/observatory/tests/service/set_library_debuggable_rpc_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 library set_library_debuggable_rpc_test;
 
diff --git a/runtime/observatory/tests/service/steal_breakpoint_test.dart b/runtime/observatory/tests/service/steal_breakpoint_test.dart
index bbe25d9..95a4191 100644
--- a/runtime/observatory/tests/service/steal_breakpoint_test.dart
+++ b/runtime/observatory/tests/service/steal_breakpoint_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --steal-breakpoints
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override --steal-breakpoints
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
@@ -29,8 +29,9 @@
 
   // Set up a listener to wait for breakpoint events.
   Completer completer = new Completer();
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
   var subscription;
-  subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
+  subscription = stream.listen((ServiceEvent event) {
     if (event.kind == ServiceEvent.kPauseBreakpoint) {
       print('Isolate paused at breakpoint');
       subscription.cancel();
@@ -61,8 +62,9 @@
 // Resume
 (Isolate isolate) async {
   Completer completer = new Completer();
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
   var subscription;
-  subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
+  subscription = stream.listen((ServiceEvent event) {
     if (event.kind == ServiceEvent.kResume) {
       print('Isolate resumed');
       subscription.cancel();
diff --git a/runtime/observatory/tests/service/string_escaping_test.dart b/runtime/observatory/tests/service/string_escaping_test.dart
index d3420db..0fd3c6a 100644
--- a/runtime/observatory/tests/service/string_escaping_test.dart
+++ b/runtime/observatory/tests/service/string_escaping_test.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 2014, 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=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 library string_escaping_test;
 
diff --git a/runtime/observatory/tests/service/test_helper.dart b/runtime/observatory/tests/service/test_helper.dart
index e69a257..f47f1cd 100644
--- a/runtime/observatory/tests/service/test_helper.dart
+++ b/runtime/observatory/tests/service/test_helper.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 2013, 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=--compile-all --error_on_bad_type --error_on_bad_override --checked
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override --checked
 
 library test_helper;
 
@@ -141,11 +141,15 @@
                                  StreamSubscription subscription,
                                  Completer completer);
 
-Future processServiceEvents(VM vm, ServiceEventHandler handler) {
+Future processServiceEvents(VM vm,
+                            String streamId,
+                            ServiceEventHandler handler) {
   Completer completer = new Completer();
-  var subscription;
-  subscription = vm.events.stream.listen((ServiceEvent event) {
-    handler(event, subscription, completer);
+  vm.getEventStream(streamId).then((stream) {
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      handler(event, subscription, completer);
+    });
   });
   return completer.future;
 }
@@ -161,13 +165,15 @@
 
   // Set up a listener to wait for breakpoint events.
   Completer completer = new Completer();
-  var subscription;
-  subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
-    if (event.kind == ServiceEvent.kPauseBreakpoint) {
-      print('Breakpoint reached');
-      subscription.cancel();
-      completer.complete(isolate);
-    }
+  isolate.vm.getEventStream(VM.kDebugStream).then((stream) {
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+        if (event.kind == ServiceEvent.kPauseBreakpoint) {
+          print('Breakpoint reached');
+          subscription.cancel();
+          completer.complete();
+        }
+    });
   });
 
   return completer.future;  // Will complete when breakpoint hit.
@@ -176,12 +182,14 @@
 
 Future<Isolate> resumeIsolate(Isolate isolate) {
   Completer completer = new Completer();
-  var subscription;
-  subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
-    if (event.kind == ServiceEvent.kResume) {
-      subscription.cancel();
-      completer.complete();
-    }
+  isolate.vm.getEventStream(VM.kDebugStream).then((stream) {
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kResume) {
+        subscription.cancel();
+        completer.complete();
+      }
+    });
   });
   isolate.resume();
   return completer.future;
diff --git a/runtime/observatory/tests/service/type_arguments_test.dart b/runtime/observatory/tests/service/type_arguments_test.dart
index aa06ade..6741520 100644
--- a/runtime/observatory/tests/service/type_arguments_test.dart
+++ b/runtime/observatory/tests/service/type_arguments_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/typed_data_test.dart b/runtime/observatory/tests/service/typed_data_test.dart
index f0070a0..83be522 100644
--- a/runtime/observatory/tests/service/typed_data_test.dart
+++ b/runtime/observatory/tests/service/typed_data_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 library typed_data_test;
 
diff --git a/runtime/observatory/tests/service/vm_test.dart b/runtime/observatory/tests/service/vm_test.dart
index 1e58d9b..bbce87b 100644
--- a/runtime/observatory/tests/service/vm_test.dart
+++ b/runtime/observatory/tests/service/vm_test.dart
@@ -1,7 +1,7 @@
 // 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.
-// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/weak_properties_test.dart b/runtime/observatory/tests/service/weak_properties_test.dart
index 30ae2a0..7de95c1 100644
--- a/runtime/observatory/tests/service/weak_properties_test.dart
+++ b/runtime/observatory/tests/service/weak_properties_test.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 2014, 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=--compile-all --error_on_bad_type --error_on_bad_override
+// VMOptions=--compile_all --error_on_bad_type --error_on_bad_override
 
 library vm_references_test;
 
diff --git a/runtime/third_party/double-conversion/src/strtod.cc b/runtime/third_party/double-conversion/src/strtod.cc
index 3471756..17abcbb 100644
--- a/runtime/third_party/double-conversion/src/strtod.cc
+++ b/runtime/third_party/double-conversion/src/strtod.cc
@@ -286,7 +286,7 @@
   const int kDenominator = 1 << kDenominatorLog;
   // Move the remaining decimals into the exponent.
   exponent += remaining_decimals;
-  int error = (remaining_decimals == 0 ? 0 : kDenominator / 2);
+  uint64_t error = (remaining_decimals == 0 ? 0 : kDenominator / 2);
 
   int old_e = input.e();
   input.Normalize();
diff --git a/runtime/vm/allocation.cc b/runtime/vm/allocation.cc
index b8f9cb1..b6ca73e 100644
--- a/runtime/vm/allocation.cc
+++ b/runtime/vm/allocation.cc
@@ -20,12 +20,12 @@
 
 
 void* ZoneAllocated::operator new(uword size) {
-  return Allocate(size, Isolate::Current()->current_zone());
+  return Allocate(size, Thread::Current()->zone());
 }
 
 
 void* ZoneAllocated::operator new(uword size, Zone* zone) {
-  ASSERT(zone == Isolate::Current()->current_zone());
+  ASSERT(zone == Thread::Current()->zone());
   return Allocate(size, zone);
 }
 
diff --git a/runtime/vm/allocation.h b/runtime/vm/allocation.h
index 579ed77..f6b74b8 100644
--- a/runtime/vm/allocation.h
+++ b/runtime/vm/allocation.h
@@ -8,6 +8,7 @@
 #include "platform/assert.h"
 #include "vm/base_isolate.h"
 #include "vm/globals.h"
+#include "vm/thread.h"
 
 namespace dart {
 
@@ -36,42 +37,62 @@
 // to a stack frame above the frame where these objects were allocated.
 class StackResource {
  public:
-  explicit StackResource(Isolate* isolate)
-      : isolate_(reinterpret_cast<BaseIsolate*>(isolate)), previous_(NULL) {
-    // We can only have longjumps and exceptions when there is a current
-    // isolate.  If there is no current isolate, we don't need to
-    // protect this case.
-    if (isolate_ != NULL) {
-      previous_ = isolate_->top_resource();
-      isolate_->set_top_resource(this);
-    }
+  // DEPRECATED: Use Thread-based interface. During migration, this defaults
+  // to using the mutator thread (which must also be the current thread).
+  explicit StackResource(Isolate* isolate) : thread_(NULL), previous_(NULL) {
+    Init((isolate == NULL) ?
+        NULL : reinterpret_cast<BaseIsolate*>(isolate)->mutator_thread_);
+  }
+
+  explicit StackResource(Thread* thread) : thread_(NULL), previous_(NULL) {
+    Init(thread);
   }
 
   virtual ~StackResource() {
-    if (isolate_ != NULL) {
-      StackResource* top = isolate_->top_resource();
+    if (thread_ != NULL) {
+      StackResource* top = thread_->top_resource();
       ASSERT(top == this);
-      isolate_->set_top_resource(previous_);
+      thread_->set_top_resource(previous_);
     }
 #if defined(DEBUG)
-    if (isolate_ != NULL) {
-      BaseIsolate::AssertCurrent(isolate_);
+    if (thread_ != NULL) {
+      ASSERT(Thread::Current() == thread_);
+      BaseIsolate::AssertCurrent(reinterpret_cast<BaseIsolate*>(isolate()));
     }
 #endif
   }
 
-  // We can only create StackResources with Isolates, so provide the original
-  // isolate to the subclasses. The only reason we have a BaseIsolate in the
-  // StackResource is to break the header include cycles.
-  Isolate* isolate() const { return reinterpret_cast<Isolate*>(isolate_); }
+  // Convenient access to the isolate of the thread of this resource.
+  Isolate* isolate() const {
+    return thread_ == NULL ? NULL : thread_->isolate();
+  }
+
+  // The thread that owns this resource.
+  Thread* thread() const { return thread_; }
 
   // Destroy stack resources of isolate until top exit frame.
+  // TODO(koda): Migrate to Thread.
   static void Unwind(Isolate* isolate) { UnwindAbove(isolate, NULL); }
+  // TODO(koda): Migrate to Thread.
   // Destroy stack resources of isolate above new_top, exclusive.
   static void UnwindAbove(Isolate* isolate, StackResource* new_top);
 
  private:
-  BaseIsolate* const isolate_;  // Current isolate for this stack resource.
+  void Init(Thread* thread) {
+    // We can only have longjumps and exceptions when there is a current
+    // thread and isolate.  If there is no current thread, we don't need to
+    // protect this case.
+    // TODO(23807): Eliminate this special case.
+    if (thread != NULL) {
+      ASSERT(Thread::Current() == thread);
+      thread_ = thread;
+      previous_ = thread_->top_resource();
+      ASSERT((previous_ == NULL) || (previous_->thread_ == thread));
+      thread_->set_top_resource(this);
+    }
+  }
+
+  Thread* thread_;
   StackResource* previous_;
 
   DISALLOW_ALLOCATION();
diff --git a/runtime/vm/assembler.cc b/runtime/vm/assembler.cc
index cefafb8..3f3e61a 100644
--- a/runtime/vm/assembler.cc
+++ b/runtime/vm/assembler.cc
@@ -24,7 +24,7 @@
 DECLARE_FLAG(bool, disassemble_optimized);
 
 static uword NewContents(intptr_t capacity) {
-  Zone* zone = Isolate::Current()->current_zone();
+  Zone* zone = Thread::Current()->zone();
   uword result = zone->AllocUnsafe(capacity);
 #if defined(DEBUG)
   // Initialize the buffer with kBreakPointInstruction to force a break
@@ -254,8 +254,6 @@
 
 intptr_t ObjectPoolWrapper::AddObject(ObjectPool::Entry entry,
                                       Patchability patchable) {
-  // The object pool cannot be used in the vm isolate.
-  ASSERT(Isolate::Current() != Dart::vm_isolate());
   object_pool_.Add(entry);
   if (patchable == kNotPatchable) {
     // The object isn't patchable. Record the index for fast lookup.
@@ -268,7 +266,6 @@
 
 intptr_t ObjectPoolWrapper::AddExternalLabel(const ExternalLabel* label,
                                              Patchability patchable) {
-  ASSERT(Isolate::Current() != Dart::vm_isolate());
   return AddObject(ObjectPool::Entry(label->address(),
                                      ObjectPool::kImmediate),
                    patchable);
@@ -277,9 +274,6 @@
 
 intptr_t ObjectPoolWrapper::FindObject(ObjectPool::Entry entry,
                                        Patchability patchable) {
-  // The object pool cannot be used in the vm isolate.
-  ASSERT(Isolate::Current() != Dart::vm_isolate());
-
   // If the object is not patchable, check if we've already got it in the
   // object pool.
   if (patchable == kNotPatchable) {
@@ -306,8 +300,6 @@
 
 intptr_t ObjectPoolWrapper::FindExternalLabel(const ExternalLabel* label,
                                               Patchability patchable) {
-  // The object pool cannot be used in the vm isolate.
-  ASSERT(Isolate::Current() != Dart::vm_isolate());
   return FindObject(ObjectPool::Entry(label->address(),
                                       ObjectPool::kImmediate),
                     patchable);
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index 28d2c56..a354940 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -1567,6 +1567,12 @@
                                  const Object& object,
                                  Condition cond,
                                  bool is_unique) {
+  // Load common VM constants from the thread. This works also in places where
+  // no constant pool is set up (e.g. intrinsic code).
+  if (Thread::CanLoadFromThread(object)) {
+    ldr(rd, Address(THR, Thread::OffsetFromThread(object)), cond);
+    return;
+  }
   // Smis and VM heap objects are never relocated; do not use object pool.
   if (object.IsSmi()) {
     LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw()), cond);
@@ -1808,8 +1814,8 @@
   if (object != R0) {
     mov(R0, Operand(object));
   }
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  BranchLink(&stub_code->UpdateStoreBufferLabel());
+  ldr(LR, Address(THR, Thread::update_store_buffer_entry_point_offset()));
+  blx(LR);
   PopList(regs);
   Bind(&done);
 }
@@ -1961,8 +1967,10 @@
 
 void Assembler::LoadClassById(Register result, Register class_id) {
   ASSERT(result != class_id);
-  LoadImmediate(result, Isolate::Current()->class_table()->TableAddress());
-  LoadFromOffset(kWord, result, result, 0);
+  LoadIsolate(result);
+  const intptr_t offset =
+      Isolate::class_table_offset() + ClassTable::table_offset();
+  LoadFromOffset(kWord, result, result, offset);
   ldr(result, Address(result, class_id, LSL, 2));
 }
 
@@ -3337,8 +3345,7 @@
 
 
 void Assembler::LoadAllocationStatsAddress(Register dest,
-                                           intptr_t cid,
-                                           Heap::Space space) {
+                                           intptr_t cid) {
   ASSERT(dest != kNoRegister);
   ASSERT(dest != TMP);
   ASSERT(cid > 0);
@@ -3358,6 +3365,18 @@
 }
 
 
+void Assembler::MaybeTraceAllocation(intptr_t cid,
+                                     Register temp_reg,
+                                     Label* trace) {
+  LoadAllocationStatsAddress(temp_reg, cid);
+  const uword state_offset = ClassHeapStats::state_offset();
+  const Address& state_address = Address(temp_reg, state_offset);
+  ldr(temp_reg, state_address);
+  tst(temp_reg, Operand(ClassHeapStats::TraceAllocationMask()));
+  b(trace, NE);
+}
+
+
 void Assembler::IncrementAllocationStats(Register stats_addr_reg,
                                          intptr_t cid,
                                          Heap::Space space) {
@@ -3408,6 +3427,10 @@
     ASSERT(temp_reg != IP);
     const intptr_t instance_size = cls.instance_size();
     ASSERT(instance_size != 0);
+    // If this allocation is traced, program will jump to failure path
+    // (i.e. the allocation stub) which will allocate the object and trace the
+    // allocation call site.
+    MaybeTraceAllocation(cls.id(), temp_reg, failure);
     Heap* heap = Isolate::Current()->heap();
     Heap::Space space = heap->SpaceForAllocation(cls.id());
     const uword top_address = heap->TopAddress(space);
@@ -3429,7 +3452,7 @@
     // next object start and store the class in the class field of object.
     str(instance_reg, Address(temp_reg));
 
-    LoadAllocationStatsAddress(temp_reg, cls.id(), space);
+    LoadAllocationStatsAddress(temp_reg, cls.id());
 
     ASSERT(instance_size >= kHeapObjectTag);
     AddImmediate(instance_reg, -instance_size + kHeapObjectTag);
@@ -3456,6 +3479,10 @@
                                  Register temp1,
                                  Register temp2) {
   if (FLAG_inline_alloc) {
+    // If this allocation is traced, program will jump to failure path
+    // (i.e. the allocation stub) which will allocate the object and trace the
+    // allocation call site.
+    MaybeTraceAllocation(cid, temp1, failure);
     Isolate* isolate = Isolate::Current();
     Heap* heap = isolate->heap();
     Heap::Space space = heap->SpaceForAllocation(cid);
@@ -3472,7 +3499,7 @@
     cmp(end_address, Operand(temp2));
     b(failure, CS);
 
-    LoadAllocationStatsAddress(temp2, cid, space);
+    LoadAllocationStatsAddress(temp2, cid);
 
     // Successfully allocated the object(s), now update top to point to
     // next object start and initialize the object.
diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h
index f3d9583..4301677 100644
--- a/runtime/vm/assembler_arm.h
+++ b/runtime/vm/assembler_arm.h
@@ -910,8 +910,7 @@
   // allocation stats. These are separate assembler macros so we can
   // avoid a dependent load too nearby the load of the table address.
   void LoadAllocationStatsAddress(Register dest,
-                                  intptr_t cid,
-                                  Heap::Space space);
+                                  intptr_t cid);
   void IncrementAllocationStats(Register stats_addr,
                                 intptr_t cid,
                                 Heap::Space space);
@@ -935,6 +934,12 @@
                                     Register array,
                                     Register index);
 
+  // If allocation tracing for |cid| is enabled, will jump to |trace| label,
+  // which will allocate in the runtime where tracing occurs.
+  void MaybeTraceAllocation(intptr_t cid,
+                            Register temp_reg,
+                            Label* trace);
+
   // Inlined allocation of an instance of class 'cls', code has no runtime
   // calls. Jump to 'failure' if the instance cannot be allocated here.
   // Allocated instance is returned in 'instance_reg'.
diff --git a/runtime/vm/assembler_arm64.cc b/runtime/vm/assembler_arm64.cc
index 4e39862..6d315e6 100644
--- a/runtime/vm/assembler_arm64.cc
+++ b/runtime/vm/assembler_arm64.cc
@@ -31,28 +31,6 @@
       use_far_branches_(use_far_branches),
       comments_(),
       allow_constant_pool_(true) {
-  if (Isolate::Current() != Dart::vm_isolate()) {
-    // These objects and labels need to be accessible through every pool-pointer
-    // at the same index.
-    intptr_t index =
-        object_pool_wrapper_.AddObject(Object::null_object());
-    ASSERT(index == 0);
-
-    index = object_pool_wrapper_.AddObject(Bool::True());
-    ASSERT(index == 1);
-
-    index = object_pool_wrapper_.AddObject(Bool::False());
-    ASSERT(index == 2);
-
-    const Smi& vacant = Smi::Handle(Smi::New(0xfa >> kSmiTagShift));
-    StubCode* stub_code = Isolate::Current()->stub_code();
-    if (stub_code->UpdateStoreBuffer_entry() != NULL) {
-      object_pool_wrapper_.AddExternalLabel(
-          &stub_code->UpdateStoreBufferLabel(), kNotPatchable);
-    } else {
-      object_pool_wrapper_.AddObject(vacant);
-    }
-  }
 }
 
 
@@ -382,23 +360,14 @@
 
 
 intptr_t Assembler::FindImmediate(int64_t imm) {
-  ASSERT(Isolate::Current() != Dart::vm_isolate());
   return object_pool_wrapper_.FindImmediate(imm);
 }
 
 
-// A set of VM objects that are present in every constant pool.
-static bool IsAlwaysInConstantPool(const Object& object) {
-  // TODO(zra): Evaluate putting all VM heap objects into the pool.
-  return (object.raw() == Object::null())
-      || (object.raw() == Bool::True().raw())
-      || (object.raw() == Bool::False().raw());
-}
-
-
-bool Assembler::CanLoadObjectFromPool(const Object& object) {
+bool Assembler::CanLoadFromObjectPool(const Object& object) const {
+  ASSERT(!Thread::CanLoadFromThread(object));
   if (!allow_constant_pool()) {
-    return IsAlwaysInConstantPool(object);
+    return false;
   }
 
   // TODO(zra, kmillikin): Also load other large immediates from the object
@@ -410,7 +379,7 @@
   }
   ASSERT(object.IsNotTemporaryScopedHandle());
   ASSERT(object.IsOld());
-  return (Isolate::Current() != Dart::vm_isolate());
+  return true;
 }
 
 
@@ -418,12 +387,7 @@
   if (!allow_constant_pool()) {
     return false;
   }
-  return !Utils::IsInt(32, imm) &&
-         (pp != kNoPP) &&
-         // We *could* put constants in the pool in a VM isolate, but it is
-         // simpler to maintain the invariant that the object pool is not used
-         // in the VM isolate.
-         (Isolate::Current() != Dart::vm_isolate());
+  return !Utils::IsInt(32, imm) && (pp != kNoPP);
 }
 
 
@@ -452,7 +416,7 @@
 }
 
 
-void Assembler::LoadIsolate(Register dst, Register pp) {
+void Assembler::LoadIsolate(Register dst) {
   ldr(dst, Address(THR, Thread::isolate_offset()));
 }
 
@@ -461,15 +425,15 @@
                                  const Object& object,
                                  Register pp,
                                  bool is_unique) {
-  if (CanLoadObjectFromPool(object)) {
+  if (Thread::CanLoadFromThread(object)) {
+    ldr(dst, Address(THR, Thread::OffsetFromThread(object)));
+  } else if (CanLoadFromObjectPool(object)) {
     const int32_t offset = ObjectPool::element_offset(
         is_unique ? object_pool_wrapper_.AddObject(object)
                   : object_pool_wrapper_.FindObject(object));
     LoadWordFromPoolOffset(dst, pp, offset);
   } else {
-    ASSERT((Isolate::Current() == Dart::vm_isolate()) ||
-           object.IsSmi() ||
-           object.InVMHeap());
+    ASSERT(object.IsSmi() || object.InVMHeap());
     LoadDecodableImmediate(dst, reinterpret_cast<int64_t>(object.raw()), pp);
   }
 }
@@ -488,7 +452,10 @@
 
 
 void Assembler::CompareObject(Register reg, const Object& object, Register pp) {
-  if (CanLoadObjectFromPool(object)) {
+  if (Thread::CanLoadFromThread(object)) {
+    ldr(TMP, Address(THR, Thread::OffsetFromThread(object)));
+    CompareRegisters(reg, TMP);
+  } else if (CanLoadFromObjectPool(object)) {
     LoadObject(TMP, object, pp);
     CompareRegisters(reg, TMP);
   } else {
@@ -498,17 +465,9 @@
 
 
 void Assembler::LoadDecodableImmediate(Register reg, int64_t imm, Register pp) {
-  if ((pp != kNoPP) &&
-      (Isolate::Current() != Dart::vm_isolate()) &&
-      allow_constant_pool()) {
-    int64_t val_smi_tag = imm & kSmiTagMask;
-    imm &= ~kSmiTagMask;  // Mask off the tag bits.
+  if ((pp != kNoPP) && allow_constant_pool()) {
     const int32_t offset = ObjectPool::element_offset(FindImmediate(imm));
     LoadWordFromPoolOffset(reg, pp, offset);
-    if (val_smi_tag != 0) {
-      // Add back the tag bits.
-      orri(reg, reg, Immediate(val_smi_tag));
-    }
   } else {
     // TODO(zra): Since this sequence only needs to be decodable, it can be
     // of variable length.
@@ -931,8 +890,8 @@
   if (object != R0) {
     mov(R0, object);
   }
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  BranchLink(&stub_code->UpdateStoreBufferLabel(), PP);
+  ldr(TMP, Address(THR, Thread::update_store_buffer_entry_point_offset()));
+  blr(TMP);
   Pop(LR);
   if (value != R0) {
     // Restore R0.
@@ -1005,8 +964,10 @@
 
 void Assembler::LoadClassById(Register result, Register class_id, Register pp) {
   ASSERT(result != class_id);
-  LoadImmediate(result, Isolate::Current()->class_table()->TableAddress(), pp);
-  LoadFromOffset(result, result, 0, pp);
+  LoadIsolate(result);
+  const intptr_t offset =
+      Isolate::class_table_offset() + ClassTable::table_offset();
+  LoadFromOffset(result, result, offset, pp);
   ldr(result, Address(result, class_id, UXTX, Address::Scaled));
 }
 
@@ -1347,6 +1308,31 @@
 }
 
 
+void Assembler::MaybeTraceAllocation(intptr_t cid,
+                                     Register temp_reg,
+                                     Register pp,
+                                     Label* trace) {
+  ASSERT(cid > 0);
+  Isolate* isolate = Isolate::Current();
+  ClassTable* class_table = isolate->class_table();
+  const uword class_offset = cid * sizeof(ClassHeapStats);  // NOLINT
+  if (cid < kNumPredefinedCids) {
+    const uword class_heap_stats_table_address =
+        class_table->PredefinedClassHeapStatsTableAddress();
+    LoadImmediate(temp_reg, class_heap_stats_table_address + class_offset, pp);
+  } else {
+    LoadImmediate(temp_reg, class_table->ClassStatsTableAddress(), pp);
+    ldr(temp_reg, Address(temp_reg, 0));
+    AddImmediate(temp_reg, temp_reg, class_offset, pp);
+  }
+  const uword state_offset = ClassHeapStats::state_offset();
+  const Address& state_address = Address(temp_reg, state_offset);
+  ldr(temp_reg, state_address);
+  tsti(temp_reg, Immediate(ClassHeapStats::TraceAllocationMask()));
+  b(trace, NE);
+}
+
+
 void Assembler::TryAllocate(const Class& cls,
                             Label* failure,
                             Register instance_reg,
@@ -1354,6 +1340,10 @@
                             Register pp) {
   ASSERT(failure != NULL);
   if (FLAG_inline_alloc) {
+    // If this allocation is traced, program will jump to failure path
+    // (i.e. the allocation stub) which will allocate the object and trace the
+    // allocation call site.
+    MaybeTraceAllocation(cls.id(), temp_reg, pp, failure);
     const intptr_t instance_size = cls.instance_size();
     Heap* heap = Isolate::Current()->heap();
     Heap::Space space = heap->SpaceForAllocation(cls.id());
@@ -1401,6 +1391,10 @@
                                  Register temp1,
                                  Register temp2) {
   if (FLAG_inline_alloc) {
+    // If this allocation is traced, program will jump to failure path
+    // (i.e. the allocation stub) which will allocate the object and trace the
+    // allocation call site.
+    MaybeTraceAllocation(cid, temp1, PP, failure);
     Isolate* isolate = Isolate::Current();
     Heap* heap = isolate->heap();
     Heap::Space space = heap->SpaceForAllocation(cid);
diff --git a/runtime/vm/assembler_arm64.h b/runtime/vm/assembler_arm64.h
index 1da9605..1468547 100644
--- a/runtime/vm/assembler_arm64.h
+++ b/runtime/vm/assembler_arm64.h
@@ -1311,7 +1311,7 @@
   void LoadWordFromPoolOffset(Register dst, Register pp, uint32_t offset);
   void LoadWordFromPoolOffsetFixed(Register dst, Register pp, uint32_t offset);
   intptr_t FindImmediate(int64_t imm);
-  bool CanLoadObjectFromPool(const Object& object);
+  bool CanLoadFromObjectPool(const Object& object) const;
   bool CanLoadImmediateFromPool(int64_t imm, Register pp);
   void LoadExternalLabel(Register dst, const ExternalLabel* label,
                          Patchability patchable, Register pp);
@@ -1319,7 +1319,7 @@
                               const ExternalLabel* label,
                               Patchability patchable,
                               Register pp);
-  void LoadIsolate(Register dst, Register pp);
+  void LoadIsolate(Register dst);
   void LoadObject(Register dst, const Object& obj, Register pp);
   void LoadUniqueObject(Register dst, const Object& obj, Register pp);
   void LoadDecodableImmediate(Register reg, int64_t imm, Register pp);
@@ -1387,6 +1387,13 @@
                                      Register pp,
                                      Heap::Space space);
 
+  // If allocation tracing for |cid| is enabled, will jump to |trace| label,
+  // which will allocate in the runtime where tracing occurs.
+  void MaybeTraceAllocation(intptr_t cid,
+                            Register temp_reg,
+                            Register pp,
+                            Label* trace);
+
   // Inlined allocation of an instance of class 'cls', code has no runtime
   // calls. Jump to 'failure' if the instance cannot be allocated here.
   // Allocated instance is returned in 'instance_reg'.
diff --git a/runtime/vm/assembler_arm64_test.cc b/runtime/vm/assembler_arm64_test.cc
index 621c03c..28749b3 100644
--- a/runtime/vm/assembler_arm64_test.cc
+++ b/runtime/vm/assembler_arm64_test.cc
@@ -1693,58 +1693,78 @@
 }
 
 
+#if defined(USING_SIMULATOR)
+#define ASSEMBLER_TEST_RUN_WITH_THREAD(var_name) \
+  Thread* thread = Thread::Current(); \
+  int64_t var_name = Simulator::Current()->Call( \
+      bit_cast<intptr_t, uword>(test->entry()), \
+      reinterpret_cast<intptr_t>(thread), 0, 0, 0)
+#else
+#define ASSEMBER_TEST_RUN_WITH_THREAD(var_name) \
+  typedef int64_t (*Int64Return)(Thread* thread); \
+  Int64Return test_code = reinterpret_cast<Int64Return>(test->entry()); \
+  int64_t var_name = test_code(thread)
+#endif
+
+
 // LoadObject null.
 ASSEMBLER_TEST_GENERATE(LoadObjectNull, assembler) {
   __ SetupDartSP(kTestStackSpace);
+  __ Push(THR);
+  __ mov(THR, R0);
   __ TagAndPushPP();  // Save caller's pool pointer and load a new one here.
   __ LoadPoolPointer(PP);
   __ LoadObject(R0, Object::null_object(), PP);
   __ PopAndUntagPP();
+  __ Pop(THR);
   __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(LoadObjectNull, test) {
-  typedef int64_t (*Int64Return)() DART_UNUSED;
-  EXPECT_EQ(reinterpret_cast<int64_t>(Object::null()),
-            EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
+  ASSEMBLER_TEST_RUN_WITH_THREAD(result);
+  EXPECT_EQ(reinterpret_cast<int64_t>(Object::null()), result);
 }
 
 
 ASSEMBLER_TEST_GENERATE(LoadObjectTrue, assembler) {
   __ SetupDartSP(kTestStackSpace);
+  __ Push(THR);
+  __ mov(THR, R0);
   __ TagAndPushPP();  // Save caller's pool pointer and load a new one here.
   __ LoadPoolPointer(PP);
   __ LoadObject(R0, Bool::True(), PP);
   __ PopAndUntagPP();
+  __ Pop(THR);
   __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(LoadObjectTrue, test) {
-  typedef int64_t (*Int64Return)() DART_UNUSED;
-  EXPECT_EQ(reinterpret_cast<int64_t>(Bool::True().raw()),
-            EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
+  ASSEMBLER_TEST_RUN_WITH_THREAD(result);
+  EXPECT_EQ(reinterpret_cast<int64_t>(Bool::True().raw()), result);
 }
 
 
 ASSEMBLER_TEST_GENERATE(LoadObjectFalse, assembler) {
   __ SetupDartSP(kTestStackSpace);
+  __ Push(THR);
+  __ mov(THR, R0);
   __ TagAndPushPP();  // Save caller's pool pointer and load a new one here.
   __ LoadPoolPointer(PP);
   __ LoadObject(R0, Bool::False(), PP);
   __ PopAndUntagPP();
+  __ Pop(THR);
   __ mov(CSP, SP);
   __ ret();
 }
 
 
 ASSEMBLER_TEST_RUN(LoadObjectFalse, test) {
-  typedef int64_t (*Int64Return)() DART_UNUSED;
-  EXPECT_EQ(reinterpret_cast<int64_t>(Bool::False().raw()),
-            EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
+  ASSEMBLER_TEST_RUN_WITH_THREAD(result);
+  EXPECT_EQ(reinterpret_cast<int64_t>(Bool::False().raw()), result);
 }
 
 
diff --git a/runtime/vm/assembler_ia32.cc b/runtime/vm/assembler_ia32.cc
index 249fba0..1059706 100644
--- a/runtime/vm/assembler_ia32.cc
+++ b/runtime/vm/assembler_ia32.cc
@@ -2683,6 +2683,45 @@
 }
 
 
+static void ComputeHeapStatsStateAddressForCid(intptr_t cid,
+                                               Address* state_address) {
+  ASSERT(cid < kNumPredefinedCids);
+  Isolate* isolate = Isolate::Current();
+  ClassTable* class_table = isolate->class_table();
+  const uword class_heap_stats_table_address =
+      class_table->PredefinedClassHeapStatsTableAddress();
+  const uword class_offset = cid * sizeof(ClassHeapStats);  // NOLINT
+  const uword state_offset = ClassHeapStats::state_offset();
+  *state_address = Address::Absolute(class_heap_stats_table_address +
+                                     class_offset +
+                                     state_offset);
+}
+
+
+void Assembler::MaybeTraceAllocation(intptr_t cid,
+                                     Register temp_reg,
+                                     Label* trace,
+                                     bool near_jump) {
+  ASSERT(cid > 0);
+  Address state_address(kNoRegister, 0);
+  if (cid < kNumPredefinedCids) {
+    ComputeHeapStatsStateAddressForCid(cid, &state_address);
+  } else {
+    ASSERT(temp_reg != kNoRegister);
+    const uword class_offset = cid * sizeof(ClassHeapStats);  // NOLINT
+    const uword state_offset = ClassHeapStats::state_offset();
+    // temp_reg gets address of class table pointer.
+    ClassTable* class_table = Isolate::Current()->class_table();
+    movl(temp_reg, Address::Absolute(class_table->ClassStatsTableAddress()));
+    state_address = Address(temp_reg, class_offset + state_offset);
+  }
+  testb(state_address, Immediate(ClassHeapStats::TraceAllocationMask()));
+  // We are tracing for this class, jump to the trace label which will use
+  // the allocation stub.
+  j(NOT_ZERO, trace, near_jump);
+}
+
+
 void Assembler::UpdateAllocationStats(intptr_t cid,
                                       Register temp_reg,
                                       Heap::Space space) {
@@ -2739,6 +2778,10 @@
                             Register temp_reg) {
   ASSERT(failure != NULL);
   if (FLAG_inline_alloc) {
+    // If this allocation is traced, program will jump to failure path
+    // (i.e. the allocation stub) which will allocate the object and trace the
+    // allocation call site.
+    MaybeTraceAllocation(cls.id(), temp_reg, failure, near_jump);
     Heap* heap = Isolate::Current()->heap();
     const intptr_t instance_size = cls.instance_size();
     Heap::Space space = heap->SpaceForAllocation(cls.id());
@@ -2772,6 +2815,10 @@
                                  Register end_address) {
   ASSERT(failure != NULL);
   if (FLAG_inline_alloc) {
+    // If this allocation is traced, program will jump to failure path
+    // (i.e. the allocation stub) which will allocate the object and trace the
+    // allocation call site.
+    MaybeTraceAllocation(cid, kNoRegister, failure, near_jump);
     Isolate* isolate = Isolate::Current();
     Heap* heap = isolate->heap();
     Heap::Space space = heap->SpaceForAllocation(cid);
@@ -2976,8 +3023,10 @@
 
 void Assembler::LoadClassById(Register result, Register class_id) {
   ASSERT(result != class_id);
-  movl(result,
-       Address::Absolute(Isolate::Current()->class_table()->TableAddress()));
+  LoadIsolate(result);
+  const intptr_t offset =
+      Isolate::class_table_offset() + ClassTable::table_offset();
+  movl(result, Address(result, offset));
   movl(result, Address(result, class_id, TIMES_4, 0));
 }
 
diff --git a/runtime/vm/assembler_ia32.h b/runtime/vm/assembler_ia32.h
index 7ebea1d..f08b9d0 100644
--- a/runtime/vm/assembler_ia32.h
+++ b/runtime/vm/assembler_ia32.h
@@ -871,6 +871,13 @@
     return kEntryPointToPcMarkerOffset;
   }
 
+  // If allocation tracing for |cid| is enabled, will jump to |trace| label,
+  // which will allocate in the runtime where tracing occurs.
+  void MaybeTraceAllocation(intptr_t cid,
+                            Register temp_reg,
+                            Label* trace,
+                            bool near_jump);
+
   void UpdateAllocationStats(intptr_t cid,
                              Register temp_reg,
                              Heap::Space space);
diff --git a/runtime/vm/assembler_mips.cc b/runtime/vm/assembler_mips.cc
index b418fc8..da5a6df 100644
--- a/runtime/vm/assembler_mips.cc
+++ b/runtime/vm/assembler_mips.cc
@@ -459,6 +459,12 @@
 void Assembler::LoadObjectHelper(Register rd,
                                  const Object& object,
                                  bool is_unique) {
+  // Load common VM constants from the thread. This works also in places where
+  // no constant pool is set up (e.g. intrinsic code).
+  if (Thread::CanLoadFromThread(object)) {
+    lw(rd, Address(THR, Thread::OffsetFromThread(object)));
+    return;
+  }
   ASSERT(!in_delay_slot_);
   // Smis and VM heap objects are never relocated; do not use object pool.
   if (object.IsSmi()) {
@@ -568,8 +574,8 @@
   if (object != T0) {
     mov(T0, object);
   }
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  BranchLink(&stub_code->UpdateStoreBufferLabel());
+  lw(T9, Address(THR, Thread::update_store_buffer_entry_point_offset()));
+  jalr(T9);
   lw(RA, Address(SP, 0 * kWordSize));
   if (value != T0) {
     // Restore T0.
@@ -664,8 +670,10 @@
 void Assembler::LoadClassById(Register result, Register class_id) {
   ASSERT(!in_delay_slot_);
   ASSERT(result != class_id);
-  LoadImmediate(result, Isolate::Current()->class_table()->TableAddress());
-  lw(result, Address(result, 0));
+  LoadIsolate(result);
+  const intptr_t offset =
+      Isolate::class_table_offset() + ClassTable::table_offset();
+  lw(result, Address(result, offset));
   sll(TMP, class_id, 2);
   addu(result, result, TMP);
   lw(result, Address(result));
@@ -884,6 +892,33 @@
 }
 
 
+void Assembler::MaybeTraceAllocation(intptr_t cid,
+                                     Register temp_reg,
+                                     Label* trace) {
+  ASSERT(cid > 0);
+  ASSERT(!in_delay_slot_);
+  ASSERT(temp_reg != kNoRegister);
+  ASSERT(temp_reg != TMP);
+  Isolate* isolate = Isolate::Current();
+  ClassTable* class_table = isolate->class_table();
+  const uword class_offset = cid * sizeof(ClassHeapStats);  // NOLINT
+  if (cid < kNumPredefinedCids) {
+    const uword class_heap_stats_table_address =
+        class_table->PredefinedClassHeapStatsTableAddress();
+    LoadImmediate(temp_reg, class_heap_stats_table_address + class_offset);
+  } else {
+    LoadImmediate(temp_reg, class_table->ClassStatsTableAddress());
+    lw(temp_reg, Address(temp_reg, 0));
+    AddImmediate(temp_reg, class_offset);
+  }
+  const uword state_offset = ClassHeapStats::state_offset();
+  const Address& state_address = Address(temp_reg, state_offset);
+  lw(temp_reg, state_address);
+  andi(CMPRES1, temp_reg, Immediate(ClassHeapStats::TraceAllocationMask()));
+  bne(CMPRES1, ZR, trace);
+}
+
+
 void Assembler::TryAllocate(const Class& cls,
                             Label* failure,
                             Register instance_reg,
@@ -891,6 +926,10 @@
   ASSERT(!in_delay_slot_);
   ASSERT(failure != NULL);
   if (FLAG_inline_alloc) {
+    // If this allocation is traced, program will jump to failure path
+    // (i.e. the allocation stub) which will allocate the object and trace the
+    // allocation call site.
+    MaybeTraceAllocation(cls.id(), temp_reg, failure);
     const intptr_t instance_size = cls.instance_size();
     Heap* heap = Isolate::Current()->heap();
     Heap::Space space = heap->SpaceForAllocation(cls.id());
@@ -934,6 +973,10 @@
                                  Register temp1,
                                  Register temp2) {
   if (FLAG_inline_alloc) {
+    // If this allocation is traced, program will jump to failure path
+    // (i.e. the allocation stub) which will allocate the object and trace the
+    // allocation call site.
+    MaybeTraceAllocation(cid, temp1, failure);
     Isolate* isolate = Isolate::Current();
     Heap* heap = isolate->heap();
     Heap::Space space = heap->SpaceForAllocation(cid);
diff --git a/runtime/vm/assembler_mips.h b/runtime/vm/assembler_mips.h
index a4c379b..00c0f62 100644
--- a/runtime/vm/assembler_mips.h
+++ b/runtime/vm/assembler_mips.h
@@ -312,6 +312,10 @@
                                      Heap::Space space);
 
 
+  void MaybeTraceAllocation(intptr_t cid,
+                            Register temp_reg,
+                            Label* trace);
+
   // Inlined allocation of an instance of class 'cls', code has no runtime
   // calls. Jump to 'failure' if the instance cannot be allocated here.
   // Allocated instance is returned in 'instance_reg'.
diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc
index 66b36d0..7477651 100644
--- a/runtime/vm/assembler_x64.cc
+++ b/runtime/vm/assembler_x64.cc
@@ -28,28 +28,6 @@
       allow_constant_pool_(true) {
   // Far branching mode is only needed and implemented for MIPS and ARM.
   ASSERT(!use_far_branches);
-  Isolate* isolate = Isolate::Current();
-  if (isolate != Dart::vm_isolate()) {
-    // These objects and labels need to be accessible through every pool-pointer
-    // at the same index.
-    intptr_t index = object_pool_wrapper_.AddObject(Object::null_object());
-    ASSERT(index == 0);
-
-    index = object_pool_wrapper_.AddObject(Bool::True());
-    ASSERT(index == 1);
-
-    index = object_pool_wrapper_.AddObject(Bool::False());
-    ASSERT(index == 2);
-
-    const Smi& vacant = Smi::Handle(Smi::New(0xfa >> kSmiTagShift));
-    StubCode* stub_code = isolate->stub_code();
-    if (stub_code->UpdateStoreBuffer_entry() != NULL) {
-      object_pool_wrapper_.AddExternalLabel(
-          &stub_code->UpdateStoreBufferLabel(), kNotPatchable);
-    } else {
-      object_pool_wrapper_.AddObject(vacant);
-    }
-  }
 }
 
 
@@ -115,13 +93,9 @@
 
 
 void Assembler::Call(const ExternalLabel* label, Register pp) {
-  if (Isolate::Current() == Dart::vm_isolate()) {
-    call(label);
-  } else {
-    const int32_t offset = ObjectPool::element_offset(
-        object_pool_wrapper_.FindExternalLabel(label, kNotPatchable));
-    call(Address::AddressBaseImm32(pp, offset - kHeapObjectTag));
-  }
+  const int32_t offset = ObjectPool::element_offset(
+      object_pool_wrapper_.FindExternalLabel(label, kNotPatchable));
+  call(Address::AddressBaseImm32(pp, offset - kHeapObjectTag));
 }
 
 
@@ -2794,18 +2768,10 @@
 }
 
 
-// A set of VM objects that are present in every constant pool.
-static bool IsAlwaysInConstantPool(const Object& object) {
-  // TODO(zra): Evaluate putting all VM heap objects into the pool.
-  return (object.raw() == Object::null())
-      || (object.raw() == Bool::True().raw())
-      || (object.raw() == Bool::False().raw());
-}
-
-
-bool Assembler::CanLoadFromObjectPool(const Object& object) {
+bool Assembler::CanLoadFromObjectPool(const Object& object) const {
+  ASSERT(!Thread::CanLoadFromThread(object));
   if (!allow_constant_pool()) {
-    return IsAlwaysInConstantPool(object);
+    return false;
   }
 
   // TODO(zra, kmillikin): Also load other large immediates from the object
@@ -2817,7 +2783,7 @@
   }
   ASSERT(object.IsNotTemporaryScopedHandle());
   ASSERT(object.IsOld());
-  return (Isolate::Current() != Dart::vm_isolate());
+  return true;
 }
 
 
@@ -2838,15 +2804,15 @@
                                  const Object& object,
                                  Register pp,
                                  bool is_unique) {
-  if (CanLoadFromObjectPool(object)) {
+  if (Thread::CanLoadFromThread(object)) {
+    movq(dst, Address(THR, Thread::OffsetFromThread(object)));
+  } else if (CanLoadFromObjectPool(object)) {
     const int32_t offset = ObjectPool::element_offset(
         is_unique ? object_pool_wrapper_.AddObject(object)
                   : object_pool_wrapper_.FindObject(object));
     LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag);
   } else {
-    ASSERT((Isolate::Current() == Dart::vm_isolate()) ||
-           object.IsSmi() ||
-           object.InVMHeap());
+    ASSERT(object.IsSmi() || object.InVMHeap());
     LoadImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())), pp);
   }
 }
@@ -2866,7 +2832,10 @@
 
 void Assembler::StoreObject(const Address& dst, const Object& object,
                             Register pp) {
-  if (CanLoadFromObjectPool(object)) {
+  if (Thread::CanLoadFromThread(object)) {
+    movq(TMP, Address(THR, Thread::OffsetFromThread(object)));
+    movq(dst, TMP);
+  } else if (CanLoadFromObjectPool(object)) {
     LoadObject(TMP, object, pp);
     movq(dst, TMP);
   } else {
@@ -2876,7 +2845,9 @@
 
 
 void Assembler::PushObject(const Object& object, Register pp) {
-  if (CanLoadFromObjectPool(object)) {
+  if (Thread::CanLoadFromThread(object)) {
+    pushq(Address(THR, Thread::OffsetFromThread(object)));
+  } else if (CanLoadFromObjectPool(object)) {
     LoadObject(TMP, object, pp);
     pushq(TMP);
   } else {
@@ -2886,7 +2857,9 @@
 
 
 void Assembler::CompareObject(Register reg, const Object& object, Register pp) {
-  if (CanLoadFromObjectPool(object)) {
+  if (Thread::CanLoadFromThread(object)) {
+    cmpq(reg, Address(THR, Thread::OffsetFromThread(object)));
+  } else if (CanLoadFromObjectPool(object)) {
     const int32_t offset =
         ObjectPool::element_offset(object_pool_wrapper_.FindObject(object));
     cmpq(reg, Address(pp, offset-kHeapObjectTag));
@@ -2898,7 +2871,6 @@
 
 
 intptr_t Assembler::FindImmediate(int64_t imm) {
-  ASSERT(Isolate::Current() != Dart::vm_isolate());
   return object_pool_wrapper_.FindImmediate(imm);
 }
 
@@ -2907,9 +2879,7 @@
   if (!allow_constant_pool()) {
     return false;
   }
-  return !imm.is_int32() &&
-         (pp != kNoRegister) &&
-         (Isolate::Current() != Dart::vm_isolate());
+  return !imm.is_int32() && (pp != kNoRegister);
 }
 
 
@@ -3090,8 +3060,8 @@
   if (object != RDX) {
     movq(RDX, object);
   }
-  StubCode* stub_code = Isolate::Current()->stub_code();
-  Call(&stub_code->UpdateStoreBufferLabel(), PP);
+  movq(TMP, Address(THR, Thread::update_store_buffer_entry_point_offset()));
+  call(TMP);
   if (value != RDX) popq(RDX);
   Bind(&done);
 }
@@ -3491,6 +3461,46 @@
 }
 
 
+void Assembler::ComputeHeapStatsStateAddressForCid(intptr_t cid,
+                                                   Address* state_address) {
+  ASSERT(cid < kNumPredefinedCids);
+  Register temp_reg = TMP;
+  Isolate* isolate = Isolate::Current();
+  ClassTable* class_table = isolate->class_table();
+  const uword class_heap_stats_table_address =
+      class_table->PredefinedClassHeapStatsTableAddress();
+  const uword class_offset = cid * sizeof(ClassHeapStats);  // NOLINT
+  const uword state_offset = ClassHeapStats::state_offset();
+  movq(temp_reg, Immediate(class_heap_stats_table_address +
+                           class_offset +
+                           state_offset));
+  *state_address = Address(temp_reg, 0);
+}
+
+
+void Assembler::MaybeTraceAllocation(intptr_t cid,
+                                     Label* trace,
+                                     bool near_jump) {
+  ASSERT(cid > 0);
+  Address state_address(kNoRegister, 0);
+  if (cid < kNumPredefinedCids) {
+    ComputeHeapStatsStateAddressForCid(cid, &state_address);
+  } else {
+    Register temp_reg = TMP;
+    const uword class_offset = cid * sizeof(ClassHeapStats);  // NOLINT
+    const uword state_offset = ClassHeapStats::state_offset();
+    // temp_reg gets address of class table pointer.
+    ClassTable* class_table = Isolate::Current()->class_table();
+    movq(temp_reg, Immediate(class_table->ClassStatsTableAddress()));
+    state_address = Address(temp_reg, class_offset + state_offset);
+  }
+  testb(state_address, Immediate(ClassHeapStats::TraceAllocationMask()));
+  // We are tracing for this class, jump to the trace label which will use
+  // the allocation stub.
+  j(NOT_ZERO, trace, near_jump);
+}
+
+
 void Assembler::UpdateAllocationStats(intptr_t cid,
                                       Heap::Space space) {
   ASSERT(cid > 0);
@@ -3543,6 +3553,10 @@
                             Register pp) {
   ASSERT(failure != NULL);
   if (FLAG_inline_alloc) {
+    // If this allocation is traced, program will jump to failure path
+    // (i.e. the allocation stub) which will allocate the object and trace the
+    // allocation call site.
+    MaybeTraceAllocation(cls.id(), failure, near_jump);
     Heap* heap = Isolate::Current()->heap();
     const intptr_t instance_size = cls.instance_size();
     Heap::Space space = heap->SpaceForAllocation(cls.id());
@@ -3580,6 +3594,10 @@
                                  Register end_address) {
   ASSERT(failure != NULL);
   if (FLAG_inline_alloc) {
+    // If this allocation is traced, program will jump to failure path
+    // (i.e. the allocation stub) which will allocate the object and trace the
+    // allocation call site.
+    MaybeTraceAllocation(cid, failure, near_jump);
     Isolate* isolate = Isolate::Current();
     Heap* heap = isolate->heap();
     Heap::Space space = heap->SpaceForAllocation(cid);
@@ -3763,9 +3781,10 @@
 
 void Assembler::LoadClassById(Register result, Register class_id, Register pp) {
   ASSERT(result != class_id);
-  Isolate* isolate = Isolate::Current();
-  LoadImmediate(result, Immediate(isolate->class_table()->TableAddress()), pp);
-  movq(result, Address(result, 0));
+  LoadIsolate(result);
+  const intptr_t offset =
+      Isolate::class_table_offset() + ClassTable::table_offset();
+  movq(result, Address(result, offset));
   movq(result, Address(result, class_id, TIMES_8, 0));
 }
 
diff --git a/runtime/vm/assembler_x64.h b/runtime/vm/assembler_x64.h
index d964931..56cff9c 100644
--- a/runtime/vm/assembler_x64.h
+++ b/runtime/vm/assembler_x64.h
@@ -994,6 +994,12 @@
                                      intptr_t instance_size,
                                      Heap::Space space);
 
+  // If allocation tracing for |cid| is enabled, will jump to |trace| label,
+  // which will allocate in the runtime where tracing occurs.
+  void MaybeTraceAllocation(intptr_t cid,
+                            Label* trace,
+                            bool near_jump);
+
   // Inlined allocation of an instance of class 'cls', code has no runtime
   // calls. Jump to 'failure' if the instance cannot be allocated here.
   // Allocated instance is returned in 'instance_reg'.
@@ -1067,7 +1073,7 @@
   bool allow_constant_pool_;
 
   intptr_t FindImmediate(int64_t imm);
-  bool CanLoadFromObjectPool(const Object& object);
+  bool CanLoadFromObjectPool(const Object& object) const;
   void LoadObjectHelper(Register dst,
                         const Object& obj,
                         Register pp,
@@ -1129,6 +1135,8 @@
                                      Heap::Space space,
                                      Address* count_address,
                                      Address* size_address);
+  void ComputeHeapStatsStateAddressForCid(intptr_t cid,
+                                          Address* state_address);
   DISALLOW_ALLOCATION();
   DISALLOW_COPY_AND_ASSIGN(Assembler);
 };
diff --git a/runtime/vm/base_isolate.h b/runtime/vm/base_isolate.h
index dccb44b..1e92a22 100644
--- a/runtime/vm/base_isolate.h
+++ b/runtime/vm/base_isolate.h
@@ -12,6 +12,7 @@
 
 class HandleScope;
 class StackResource;
+class Thread;
 class Zone;
 
 // A BaseIsolate contains just enough functionality to allocate
@@ -19,18 +20,6 @@
 // constructor/destructor for performance.
 class BaseIsolate {
  public:
-  StackResource* top_resource() const { return top_resource_; }
-  void set_top_resource(StackResource* value) { top_resource_ = value; }
-  static intptr_t top_resource_offset() {
-    return OFFSET_OF(BaseIsolate, top_resource_);
-  }
-
-  // DEPRECATED: Use Thread::current_zone.
-  Zone* current_zone() const {
-    AssertCurrentThreadIsMutator();
-    return current_zone_;
-  }
-  void set_current_zone(Zone* zone) { current_zone_ = zone; }
 #if defined(DEBUG)
   void AssertCurrentThreadIsMutator() const;
 #else
@@ -115,8 +104,7 @@
 
  protected:
   BaseIsolate()
-      : top_resource_(NULL),
-        current_zone_(NULL),
+      : mutator_thread_(NULL),
 #if defined(DEBUG)
         top_handle_scope_(NULL),
         no_handle_scope_depth_(0),
@@ -129,8 +117,7 @@
     // Do not delete stack resources: top_resource_ and current_zone_.
   }
 
-  StackResource* top_resource_;
-  Zone* current_zone_;
+  Thread* mutator_thread_;
 #if defined(DEBUG)
   HandleScope* top_handle_scope_;
   int32_t no_handle_scope_depth_;
@@ -139,6 +126,9 @@
   int32_t no_callback_scope_depth_;
 
  private:
+  // During migration, some deprecated interfaces will default to using the
+  // mutator_thread_ (can't use accessor in Isolate due to circular deps).
+  friend class StackResource;
   DISALLOW_COPY_AND_ASSIGN(BaseIsolate);
 };
 
diff --git a/runtime/vm/bigint_test.cc b/runtime/vm/bigint_test.cc
index b4e9cdd..967e036 100644
--- a/runtime/vm/bigint_test.cc
+++ b/runtime/vm/bigint_test.cc
@@ -10,7 +10,7 @@
 namespace dart {
 
 static uword ZoneAllocator(intptr_t size) {
-  Zone* zone = Isolate::Current()->current_zone();
+  Zone* zone = Thread::Current()->zone();
   return zone->AllocUnsafe(size);
 }
 
diff --git a/runtime/vm/bitmap.cc b/runtime/vm/bitmap.cc
index 8a2ebde..ae091ae 100644
--- a/runtime/vm/bitmap.cc
+++ b/runtime/vm/bitmap.cc
@@ -54,7 +54,7 @@
       data_size_in_bytes_ =
           Utils::RoundUp(byte_offset + 1, kIncrementSizeInBytes);
       ASSERT(data_size_in_bytes_ > 0);
-      data_ = Isolate::Current()->current_zone()->Alloc<uint8_t>(
+      data_ = Thread::Current()->zone()->Alloc<uint8_t>(
           data_size_in_bytes_);
       ASSERT(data_ != NULL);
       memmove(data_, old_data, old_size);
diff --git a/runtime/vm/bitmap.h b/runtime/vm/bitmap.h
index 6d3376a3..507167e 100644
--- a/runtime/vm/bitmap.h
+++ b/runtime/vm/bitmap.h
@@ -24,7 +24,7 @@
   BitmapBuilder()
       : length_(0),
         data_size_in_bytes_(kInitialSizeInBytes),
-        data_(Isolate::Current()->current_zone()->Alloc<uint8_t>(
+        data_(Thread::Current()->zone()->Alloc<uint8_t>(
             kInitialSizeInBytes)) {
     memset(data_, 0, kInitialSizeInBytes);
   }
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 6784ece..cef070c 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -380,6 +380,7 @@
   V(LibraryPrefix_load, 1)                                                     \
   V(LibraryPrefix_invalidateDependentCode, 1)                                  \
   V(LibraryPrefix_loadError, 1)                                                \
+  V(LibraryPrefix_isLoaded, 1)                                                 \
   V(UserTag_new, 2)                                                            \
   V(UserTag_label, 1)                                                          \
   V(UserTag_defaultTag, 0)                                                     \
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index 8ec699b..1966b21 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -82,6 +82,12 @@
 }
 
 
+void ClassTable::TraceAllocationsFor(intptr_t cid, bool trace) {
+  ClassHeapStats* stats = PreliminaryStatsAt(cid);
+  stats->set_trace_allocation(trace);
+}
+
+
 void ClassTable::Register(const Class& cls) {
   intptr_t index = cls.id();
   if (index != kIllegalCid) {
@@ -233,6 +239,7 @@
   last_reset.Reset();
   promoted_count = 0;
   promoted_size = 0;
+  state_ = 0;
 }
 
 
diff --git a/runtime/vm/class_table.h b/runtime/vm/class_table.h
index 4781e37..9a23630 100644
--- a/runtime/vm/class_table.h
+++ b/runtime/vm/class_table.h
@@ -6,6 +6,7 @@
 #define VM_CLASS_TABLE_H_
 
 #include "platform/assert.h"
+#include "vm/bitfield.h"
 #include "vm/globals.h"
 
 namespace dart {
@@ -102,6 +103,12 @@
     return OFFSET_OF(ClassHeapStats, recent) +
            OFFSET_OF(AllocStats<intptr_t>, old_size);
   }
+  static intptr_t state_offset() {
+    return OFFSET_OF(ClassHeapStats, state_);
+  }
+  static intptr_t TraceAllocationMask() {
+    return (1 << kTraceAllocationBit);
+  }
 
   void Initialize();
   void ResetAtNewGC();
@@ -112,10 +119,25 @@
   void PrintToJSONObject(const Class& cls, JSONObject* obj) const;
   void Verify();
 
+  bool trace_allocation() const {
+    return TraceAllocationBit::decode(state_);
+  }
+
+  void set_trace_allocation(bool trace_allocation) {
+    state_ = TraceAllocationBit::update(trace_allocation, state_);
+  }
+
  private:
+  enum StateBits {
+    kTraceAllocationBit = 0,
+  };
+
+  class TraceAllocationBit : public BitField<bool, kTraceAllocationBit, 1> {};
+
   // Recent old at start of last new GC (used to compute promoted_*).
   intptr_t old_pre_new_gc_count_;
   intptr_t old_pre_new_gc_size_;
+  intptr_t state_;
 };
 
 
@@ -156,6 +178,7 @@
 
   void PrintToJSONObject(JSONObject* object);
 
+  // Used by the generated code.
   static intptr_t table_offset() {
     return OFFSET_OF(ClassTable, table_);
   }
@@ -172,11 +195,6 @@
   void UpdatePromoted();
 
   // Used by the generated code.
-  uword TableAddress() {
-    return reinterpret_cast<uword>(&table_);
-  }
-
-  // Used by the generated code.
   uword PredefinedClassHeapStatsTableAddress() {
     return reinterpret_cast<uword>(predefined_class_heap_stats_table_);
   }
@@ -194,6 +212,8 @@
   // Deallocates table copies. Do not call during concurrent access to table.
   void FreeOldTables();
 
+  void TraceAllocationsFor(intptr_t cid, bool trace);
+
  private:
   friend class MarkingVisitor;
   friend class ScavengerVisitor;
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 0afc458..9e15de3 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -64,6 +64,7 @@
 DEFINE_FLAG(bool, verify_compiler, false,
     "Enable compiler verification assertions");
 
+DECLARE_FLAG(bool, load_deferred_eagerly);
 DECLARE_FLAG(bool, trace_failed_optimization_attempts);
 DECLARE_FLAG(bool, trace_inlining_intervals);
 DECLARE_FLAG(bool, trace_irregexp);
@@ -71,6 +72,7 @@
 
 
 bool Compiler::always_optimize_ = false;
+bool Compiler::allow_recompilation_ = true;
 
 
 // TODO(zerny): Factor out unoptimizing/optimizing pipelines and remove
@@ -788,6 +790,7 @@
           ASSERT(CodePatcher::CodeIsPatchable(code));
         }
         if (parsed_function->HasDeferredPrefixes()) {
+          ASSERT(!FLAG_load_deferred_eagerly);
           ZoneGrowableArray<const LibraryPrefix*>* prefixes =
               parsed_function->deferred_prefixes();
           for (intptr_t i = 0; i < prefixes->length(); i++) {
@@ -972,6 +975,11 @@
                                        const Function& function,
                                        bool optimized,
                                        intptr_t osr_id) {
+  // Check that we optimize if 'Compiler::always_optimize()' is set to true,
+  // except if the function is marked as not optimizable.
+  ASSERT(!function.IsOptimizable() ||
+         !Compiler::always_optimize() || optimized);
+  ASSERT(Compiler::allow_recompilation() || !function.HasCode());
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
     Thread* const thread = Thread::Current();
diff --git a/runtime/vm/compiler.h b/runtime/vm/compiler.h
index d4099cc..e8052c7 100644
--- a/runtime/vm/compiler.h
+++ b/runtime/vm/compiler.h
@@ -90,8 +90,14 @@
   static bool always_optimize() { return always_optimize_; }
   static void set_always_optimize(bool value) { always_optimize_ = value; }
 
+  static bool allow_recompilation() { return allow_recompilation_; }
+  static void set_allow_recompilation(bool value) {
+    allow_recompilation_ = value;
+  }
+
  private:
   static bool always_optimize_;
+  static bool allow_recompilation_;
 };
 
 }  // namespace dart
diff --git a/runtime/vm/coverage.cc b/runtime/vm/coverage.cc
index ee74763..cef0201 100644
--- a/runtime/vm/coverage.cc
+++ b/runtime/vm/coverage.cc
@@ -252,7 +252,7 @@
   intptr_t pid = OS::ProcessId();
   intptr_t len = OS::SNPrint(NULL, 0, format,
                              FLAG_coverage_dir, pid, isolate->main_port());
-  char* filename = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
+  char* filename = Thread::Current()->zone()->Alloc<char>(len + 1);
   OS::SNPrint(filename, len + 1, format,
               FLAG_coverage_dir, pid, isolate->main_port());
   void* file = (*file_open)(filename, true);
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 4fd93cb..7bb4fe3 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -95,7 +95,7 @@
   Isolate::SetEntropySourceCallback(entropy_source);
   OS::InitOnce();
   VirtualMemory::InitOnce();
-  Thread::InitOnce();
+  Thread::InitOnceBeforeIsolate();
   Isolate::InitOnce();
   PortMap::InitOnce();
   FreeListElement::InitOnce();
@@ -120,7 +120,6 @@
     ASSERT(vm_isolate_ == NULL);
     ASSERT(Flags::Initialized());
     const bool is_vm_isolate = true;
-    Thread::EnsureInit();
 
     // Setup default flags for the VM isolate.
     Isolate::Flags vm_flags;
@@ -140,6 +139,7 @@
     Object::InitOnce(vm_isolate_);
     ArgumentsDescriptor::InitOnce();
     StubCode::InitOnce();
+    Thread::InitOnceAfterObjectAndStubCode();
     // Now that the needed stub has been generated, set the stack limit.
     vm_isolate_->InitializeStackLimit();
     if (vm_isolate_snapshot != NULL) {
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 17406ea..99e9a55 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -439,7 +439,9 @@
 
 
 Dart_Handle Api::NewError(const char* format, ...) {
-  Isolate* isolate = Isolate::Current();
+  Thread* thread = Thread::Current();
+  Isolate* isolate = thread->isolate();
+  Zone* zone = thread->zone();
   DARTSCOPE(isolate);
   CHECK_CALLBACK_STATE(isolate);
 
@@ -448,13 +450,13 @@
   intptr_t len = OS::VSNPrint(NULL, 0, format, args);
   va_end(args);
 
-  char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
+  char* buffer = zone->Alloc<char>(len + 1);
   va_list args2;
   va_start(args2, format);
   OS::VSNPrint(buffer, (len + 1), format, args2);
   va_end(args2);
 
-  const String& message = String::Handle(isolate, String::New(buffer));
+  const String& message = String::Handle(zone, String::New(buffer));
   return Api::NewHandle(isolate, ApiError::New(message));
 }
 
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 0364ac8..6f761b6 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -404,7 +404,7 @@
       func_class.IsTopLevel() ? "" : ".",
       func_name.ToCString());
   len++;  // String terminator.
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, kFormat,
               func_class.IsTopLevel() ? "" : class_name.ToCString(),
               func_class.IsTopLevel() ? "" : ".",
@@ -1020,7 +1020,7 @@
   const String& url = String::Handle(SourceUrl());
   intptr_t line = LineNumber();
   const char* func_name = Debugger::QualifiedFunctionName(function());
-  return Isolate::Current()->current_zone()->
+  return Thread::Current()->zone()->
       PrintToString("[ Frame pc(0x%" Px ") fp(0x%" Px ") sp(0x%" Px ")\n"
                     "\tfunction = %s\n"
                     "\turl = %s\n"
diff --git a/runtime/vm/debugger_test.cc b/runtime/vm/debugger_test.cc
index 9ccfce1..7393c67 100644
--- a/runtime/vm/debugger_test.cc
+++ b/runtime/vm/debugger_test.cc
@@ -13,14 +13,12 @@
 // TODO(turnidge): This function obscures the line number of failing
 // EXPECTs.  Rework this.
 static void ExpectSubstringF(const char* buff, const char* fmt, ...) {
-  Isolate* isolate = Isolate::Current();
-
   va_list args;
   va_start(args, fmt);
   intptr_t len = OS::VSNPrint(NULL, 0, fmt, args);
   va_end(args);
 
-  char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
+  char* buffer = Thread::Current()->zone()->Alloc<char>(len + 1);
   va_list args2;
   va_start(args2, fmt);
   OS::VSNPrint(buffer, (len + 1), fmt, args2);
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 3260760..d6e2568 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -1191,7 +1191,7 @@
 static uint8_t* ZoneReAlloc(uint8_t* ptr,
                             intptr_t old_size,
                             intptr_t new_size) {
-  return Isolate::Current()->current_zone()->Realloc<uint8_t>(
+  return Thread::Current()->zone()->Realloc<uint8_t>(
       ptr, old_size, new_size);
 }
 
diff --git a/runtime/vm/disassembler_ia32.cc b/runtime/vm/disassembler_ia32.cc
index c63057b..852621b 100644
--- a/runtime/vm/disassembler_ia32.cc
+++ b/runtime/vm/disassembler_ia32.cc
@@ -481,7 +481,7 @@
   const char* full_class_name = clazz.ToCString();
   const char* format = "instance of %s";
   intptr_t len = OS::SNPrint(NULL, 0, format, full_class_name) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, format, full_class_name);
   return chars;
 }
diff --git a/runtime/vm/disassembler_x64.cc b/runtime/vm/disassembler_x64.cc
index 0b87662..dba7e42 100644
--- a/runtime/vm/disassembler_x64.cc
+++ b/runtime/vm/disassembler_x64.cc
@@ -798,7 +798,7 @@
   const char* full_class_name = clazz.ToCString();
   const char* format = "instance of %s";
   intptr_t len = OS::SNPrint(NULL, 0, format, full_class_name) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, format, full_class_name);
   return chars;
 }
diff --git a/runtime/vm/double_conversion.cc b/runtime/vm/double_conversion.cc
index 44233fe..cb3c047 100644
--- a/runtime/vm/double_conversion.cc
+++ b/runtime/vm/double_conversion.cc
@@ -86,7 +86,7 @@
       kDoubleToStringCommonExponentChar,
       0, 0, 0, 0);  // Last four values are ignored in fixed mode.
 
-  char* buffer = Isolate::Current()->current_zone()->Alloc<char>(kBufferSize);
+  char* buffer = Thread::Current()->zone()->Alloc<char>(kBufferSize);
   buffer[kBufferSize - 1] = '\0';
   double_conversion::StringBuilder builder(buffer, kBufferSize);
   bool status = converter.ToFixed(d, fraction_digits, &builder);
@@ -119,7 +119,7 @@
       kDoubleToStringCommonExponentChar,
       0, 0, 0, 0);  // Last four values are ignored in exponential mode.
 
-  char* buffer = Isolate::Current()->current_zone()->Alloc<char>(kBufferSize);
+  char* buffer = Thread::Current()->zone()->Alloc<char>(kBufferSize);
   buffer[kBufferSize - 1] = '\0';
   double_conversion::StringBuilder builder(buffer, kBufferSize);
   bool status = converter.ToExponential(d, fraction_digits, &builder);
@@ -158,7 +158,7 @@
       kMaxLeadingPaddingZeroes,
       kMaxTrailingPaddingZeroes);
 
-  char* buffer = Isolate::Current()->current_zone()->Alloc<char>(kBufferSize);
+  char* buffer = Thread::Current()->zone()->Alloc<char>(kBufferSize);
   buffer[kBufferSize - 1] = '\0';
   double_conversion::StringBuilder builder(buffer, kBufferSize);
   bool status = converter.ToPrecision(d, precision, &builder);
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index d493fa3..1efd006 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -81,10 +81,14 @@
     FLAG_collect_code = false;
     FLAG_load_deferred_eagerly = true;
     FLAG_deoptimize_alot = false;  // Used in some tests.
-    FLAG_deoptimize_every = 0;  // Used in some tests.
+    FLAG_deoptimize_every = 0;     // Used in some tests.
     FLAG_collect_code = false;
     FLAG_guess_other_cid = true;
     Compiler::set_always_optimize(true);
+    // Triggers assert if we try to recompile (e.g., because of deferred
+    // loading, deoptimization, ...). Noopt mode simulates behavior
+    // of precompiled code, therefore do not allow recompilation.
+    Compiler::set_allow_recompilation(false);
     // TODO(srdjan): Enable CHA deoptimization when eager class finalization is
     // implemented, either with precompilation or as a special pass.
     FLAG_use_cha_deopt = false;
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index 17b2612..2ea19ee 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -177,7 +177,7 @@
     const char* kFormat = "Deopt stub for id %d, reason: %s";
     const intptr_t len = OS::SNPrint(NULL, 0, kFormat,
         deopt_id(), DeoptReasonToCString(reason())) + 1;
-    char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+    char* chars = Thread::Current()->zone()->Alloc<char>(len);
     OS::SNPrint(chars, len, kFormat,
         deopt_id(), DeoptReasonToCString(reason()));
     return chars;
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index add12f5..f2572a1 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -5536,7 +5536,7 @@
     if (def == NULL) {
       return "*";
     } else {
-      return Isolate::Current()->current_zone()->PrintToString(
+      return Thread::Current()->zone()->PrintToString(
             "v%" Pd, def->ssa_temp_index());
     }
   }
@@ -5549,34 +5549,34 @@
       case kField: {
         const char* field_name = String::Handle(field().name()).ToCString();
         if (field().is_static()) {
-          return Isolate::Current()->current_zone()->PrintToString(
+          return Thread::Current()->zone()->PrintToString(
               "<%s>", field_name);
         } else {
-          return Isolate::Current()->current_zone()->PrintToString(
+          return Thread::Current()->zone()->PrintToString(
               "<%s.%s>", DefinitionName(instance()), field_name);
         }
       }
 
       case kVMField:
-        return Isolate::Current()->current_zone()->PrintToString(
+        return Thread::Current()->zone()->PrintToString(
             "<%s.@%" Pd ">",
             DefinitionName(instance()),
             offset_in_bytes());
 
       case kIndexed:
-        return Isolate::Current()->current_zone()->PrintToString(
+        return Thread::Current()->zone()->PrintToString(
             "<%s[%s]>",
             DefinitionName(instance()),
             DefinitionName(index()));
 
       case kConstantIndexed:
         if (element_size() == kNoSize) {
-          return Isolate::Current()->current_zone()->PrintToString(
+          return Thread::Current()->zone()->PrintToString(
               "<%s[%" Pd "]>",
               DefinitionName(instance()),
               index_constant());
         } else {
-          return Isolate::Current()->current_zone()->PrintToString(
+          return Thread::Current()->zone()->PrintToString(
               "<%s[%" Pd "|%" Pd "]>",
               DefinitionName(instance()),
               index_constant(),
diff --git a/runtime/vm/flow_graph_range_analysis.cc b/runtime/vm/flow_graph_range_analysis.cc
index 5fec37b..cd45479 100644
--- a/runtime/vm/flow_graph_range_analysis.cc
+++ b/runtime/vm/flow_graph_range_analysis.cc
@@ -1516,7 +1516,7 @@
     char buffer[1024];
     BufferFormatter f(buffer, sizeof(buffer));
     PrettyPrintIndexBoundRecursively(&f, index_bound);
-    return Isolate::Current()->current_zone()->MakeCopyOfString(buffer);
+    return Thread::Current()->zone()->MakeCopyOfString(buffer);
   }
 
   RangeAnalysis* range_analysis_;
diff --git a/runtime/vm/growable_array.h b/runtime/vm/growable_array.h
index ba6f807..045c3e5 100644
--- a/runtime/vm/growable_array.h
+++ b/runtime/vm/growable_array.h
@@ -161,10 +161,10 @@
   explicit GrowableArray(intptr_t initial_capacity)
       : BaseGrowableArray<T, ValueObject>(
           initial_capacity,
-          ASSERT_NOTNULL(Isolate::Current()->current_zone())) {}
+          ASSERT_NOTNULL(Thread::Current()->zone())) {}
   GrowableArray()
       : BaseGrowableArray<T, ValueObject>(
-          ASSERT_NOTNULL(Isolate::Current()->current_zone())) {}
+          ASSERT_NOTNULL(Thread::Current()->zone())) {}
 };
 
 
@@ -177,10 +177,10 @@
   explicit ZoneGrowableArray(intptr_t initial_capacity)
       : BaseGrowableArray<T, ZoneAllocated>(
           initial_capacity,
-          ASSERT_NOTNULL(Isolate::Current()->current_zone())) {}
+          ASSERT_NOTNULL(Thread::Current()->zone())) {}
   ZoneGrowableArray()
       : BaseGrowableArray<T, ZoneAllocated>(
-          ASSERT_NOTNULL(Isolate::Current()->current_zone())) {}
+          ASSERT_NOTNULL(Thread::Current()->zone())) {}
 };
 
 
diff --git a/runtime/vm/hash_map.h b/runtime/vm/hash_map.h
index 37fdc9b..5c20d04 100644
--- a/runtime/vm/hash_map.h
+++ b/runtime/vm/hash_map.h
@@ -106,9 +106,9 @@
     array_size_(other.array_size_),
     lists_size_(other.lists_size_),
     count_(other.count_),
-    array_(Isolate::Current()->current_zone()->
+    array_(Thread::Current()->zone()->
            Alloc<HashMapListElement>(other.array_size_)),
-    lists_(Isolate::Current()->current_zone()->
+    lists_(Thread::Current()->zone()->
            Alloc<HashMapListElement>(other.lists_size_)),
     free_list_head_(other.free_list_head_) {
   memmove(array_, other.array_, array_size_ * sizeof(HashMapListElement));
@@ -131,7 +131,7 @@
   }
 
   HashMapListElement* new_array =
-      Isolate::Current()->current_zone()->Alloc<HashMapListElement>(new_size);
+      Thread::Current()->zone()->Alloc<HashMapListElement>(new_size);
   InitArray(new_array, new_size);
 
   HashMapListElement* old_array = array_;
@@ -169,7 +169,7 @@
   ASSERT(new_size > lists_size_);
 
   HashMapListElement* new_lists =
-      Isolate::Current()->current_zone()->
+      Thread::Current()->zone()->
       Alloc<HashMapListElement>(new_size);
   InitArray(new_lists, new_size);
 
diff --git a/runtime/vm/il_printer.cc b/runtime/vm/il_printer.cc
index 0d79149..6a5ce90 100644
--- a/runtime/vm/il_printer.cc
+++ b/runtime/vm/il_printer.cc
@@ -180,7 +180,7 @@
   char buffer[1024];
   BufferFormatter f(buffer, sizeof(buffer));
   PrintTo(&f);
-  return Isolate::Current()->current_zone()->MakeCopyOfString(buffer);
+  return Thread::Current()->zone()->MakeCopyOfString(buffer);
 }
 
 
@@ -247,7 +247,7 @@
   char buffer[1024];
   BufferFormatter f(buffer, sizeof(buffer));
   PrintTo(&f);
-  return Isolate::Current()->current_zone()->MakeCopyOfString(buffer);
+  return Thread::Current()->zone()->MakeCopyOfString(buffer);
 }
 
 
@@ -321,7 +321,7 @@
     f->Print("#%s", cstr);
   } else {
     const intptr_t pos = new_line - cstr;
-    char* buffer = Isolate::Current()->current_zone()->Alloc<char>(pos + 1);
+    char* buffer = Thread::Current()->zone()->Alloc<char>(pos + 1);
     strncpy(buffer, cstr, pos);
     buffer[pos] = '\0';
     f->Print("#%s\\n...", buffer);
@@ -351,7 +351,7 @@
   char buffer[256];
   BufferFormatter f(buffer, sizeof(buffer));
   range->PrintTo(&f);
-  return Isolate::Current()->current_zone()->MakeCopyOfString(buffer);
+  return Thread::Current()->zone()->MakeCopyOfString(buffer);
 }
 
 
@@ -382,7 +382,7 @@
   char buffer[256];
   BufferFormatter f(buffer, sizeof(buffer));
   PrintTo(&f);
-  return Isolate::Current()->current_zone()->MakeCopyOfString(buffer);
+  return Thread::Current()->zone()->MakeCopyOfString(buffer);
 }
 
 
@@ -1210,7 +1210,7 @@
   char buffer[1024];
   BufferFormatter bf(buffer, 1024);
   PrintTo(&bf);
-  return Isolate::Current()->current_zone()->MakeCopyOfString(buffer);
+  return Thread::Current()->zone()->MakeCopyOfString(buffer);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index 6238014..893352e 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -189,6 +189,7 @@
 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift)           \
   Label fall_through;                                                          \
   const intptr_t kArrayLengthStackOffset = 0 * kWordSize;                      \
+  __ MaybeTraceAllocation(cid, R2, &fall_through);                             \
   __ ldr(R2, Address(SP, kArrayLengthStackOffset));  /* Array length. */       \
   /* Check that length is a positive Smi. */                                   \
   /* R2: requested array length argument. */                                   \
@@ -225,7 +226,7 @@
                                                                                \
   /* Successfully allocated the object(s), now update top to point to */       \
   /* next object start and initialize the object. */                           \
-  __ LoadAllocationStatsAddress(R4, cid, space);                               \
+  __ LoadAllocationStatsAddress(R4, cid);                                      \
   __ LoadImmediate(R3, heap->TopAddress(space));                               \
   __ str(R1, Address(R3, 0));                                                  \
   __ AddImmediate(R0, kHeapObjectTag);                                         \
@@ -1762,7 +1763,7 @@
                                      Label* failure) {
   const Register length_reg = R2;
   Label fail;
-
+  __ MaybeTraceAllocation(kOneByteStringCid, R0, failure);
   __ mov(R6, Operand(length_reg));  // Save the length register.
   // TODO(koda): Protect against negative length and overflow here.
   __ SmiUntag(length_reg);
@@ -1793,7 +1794,7 @@
 
   // Successfully allocated the object(s), now update top to point to
   // next object start and initialize the object.
-  __ LoadAllocationStatsAddress(R4, cid, space);
+  __ LoadAllocationStatsAddress(R4, cid);
   __ str(R1, Address(R3, 0));
   __ AddImmediate(R0, kHeapObjectTag);
 
diff --git a/runtime/vm/intrinsifier_arm64.cc b/runtime/vm/intrinsifier_arm64.cc
index dd46bcc..8cbb1ba 100644
--- a/runtime/vm/intrinsifier_arm64.cc
+++ b/runtime/vm/intrinsifier_arm64.cc
@@ -198,6 +198,7 @@
 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift)           \
   Label fall_through;                                                          \
   const intptr_t kArrayLengthStackOffset = 0 * kWordSize;                      \
+  __ MaybeTraceAllocation(cid, R2, kNoPP, &fall_through);                      \
   __ ldr(R2, Address(SP, kArrayLengthStackOffset));  /* Array length. */       \
   /* Check that length is a positive Smi. */                                   \
   /* R2: requested array length argument. */                                   \
@@ -1842,7 +1843,7 @@
                                      Label* failure) {
   const Register length_reg = R2;
   Label fail;
-
+  __ MaybeTraceAllocation(kOneByteStringCid, R0, kNoPP, failure);
   __ mov(R6, length_reg);  // Save the length register.
   // TODO(koda): Protect against negative length and overflow here.
   __ SmiUntag(length_reg);
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc
index 2b15a71..f2bb256 100644
--- a/runtime/vm/intrinsifier_ia32.cc
+++ b/runtime/vm/intrinsifier_ia32.cc
@@ -186,6 +186,7 @@
 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_factor)          \
   Label fall_through;                                                          \
   const intptr_t kArrayLengthStackOffset = 1 * kWordSize;                      \
+  __ MaybeTraceAllocation(cid, EDI, &fall_through, false);                     \
   __ movl(EDI, Address(ESP, kArrayLengthStackOffset));  /* Array length. */    \
   /* Check that length is a positive Smi. */                                   \
   /* EDI: requested array length argument. */                                  \
@@ -1868,6 +1869,7 @@
                                      Label* ok,
                                      Label* failure,
                                      Register length_reg) {
+  __ MaybeTraceAllocation(kOneByteStringCid, EAX, failure, false);
   if (length_reg != EDI) {
     __ movl(EDI, length_reg);
   }
diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc
index e20cbd0..1cbb12f 100644
--- a/runtime/vm/intrinsifier_mips.cc
+++ b/runtime/vm/intrinsifier_mips.cc
@@ -179,6 +179,7 @@
 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift)           \
   Label fall_through;                                                          \
   const intptr_t kArrayLengthStackOffset = 0 * kWordSize;                      \
+  __ MaybeTraceAllocation(cid, T2, &fall_through);                             \
   __ lw(T2, Address(SP, kArrayLengthStackOffset));  /* Array length. */        \
   /* Check that length is a positive Smi. */                                   \
   /* T2: requested array length argument. */                                   \
@@ -1882,7 +1883,7 @@
                                      Label* ok,
                                      Label* failure) {
   const Register length_reg = T2;
-
+  __ MaybeTraceAllocation(kOneByteStringCid, V0, failure);
   __ mov(T6, length_reg);  // Save the length register.
   // TODO(koda): Protect against negative length and overflow here.
   __ SmiUntag(length_reg);
diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc
index 96fe7bc..6ed3726 100644
--- a/runtime/vm/intrinsifier_x64.cc
+++ b/runtime/vm/intrinsifier_x64.cc
@@ -130,6 +130,7 @@
 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_factor)          \
   Label fall_through;                                                          \
   const intptr_t kArrayLengthStackOffset = 1 * kWordSize;                      \
+  __ MaybeTraceAllocation(cid, &fall_through, false);                          \
   __ movq(RDI, Address(RSP, kArrayLengthStackOffset));  /* Array length. */    \
   /* Check that length is a positive Smi. */                                   \
   /* RDI: requested array length argument. */                                  \
@@ -1237,9 +1238,9 @@
                                      Label* not_double_smi) {
   __ movq(RAX, Address(RSP, + 1 * kWordSize));
   __ testq(RAX, Immediate(kSmiTagMask));
-  __ j(ZERO, is_smi, Assembler::kNearJump);  // Jump if Smi.
+  __ j(ZERO, is_smi);  // Jump if Smi.
   __ CompareClassId(RAX, kDoubleCid);
-  __ j(NOT_EQUAL, not_double_smi, Assembler::kNearJump);
+  __ j(NOT_EQUAL, not_double_smi);
   // Fall through if double.
 }
 
@@ -1319,7 +1320,7 @@
       Isolate::Current()->object_store()->double_class());
   __ TryAllocate(double_class,
                  &fall_through,
-                 Assembler::kNearJump,
+                 Assembler::kFarJump,
                  RAX,  // Result register.
                  kNoRegister);  // Pool pointer might not be loaded.
   __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
@@ -1353,7 +1354,7 @@
   // Only smis allowed.
   __ movq(RAX, Address(RSP, + 1 * kWordSize));
   __ testq(RAX, Immediate(kSmiTagMask));
-  __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);
+  __ j(NOT_ZERO, &fall_through);
   // Is Smi.
   __ SmiUntag(RAX);
   __ cvtsi2sdq(XMM1, RAX);
@@ -1364,7 +1365,7 @@
       Isolate::Current()->object_store()->double_class());
   __ TryAllocate(double_class,
                  &fall_through,
-                 Assembler::kNearJump,
+                 Assembler::kFarJump,
                  RAX,  // Result register.
                  kNoRegister);  // Pool pointer might not be loaded.
   __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
@@ -1378,7 +1379,7 @@
   Label fall_through;
   __ movq(RAX, Address(RSP, +1 * kWordSize));
   __ testq(RAX, Immediate(kSmiTagMask));
-  __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);
+  __ j(NOT_ZERO, &fall_through);
   // Is Smi.
   __ SmiUntag(RAX);
   __ cvtsi2sdq(XMM0, RAX);
@@ -1386,7 +1387,7 @@
       Isolate::Current()->object_store()->double_class());
   __ TryAllocate(double_class,
                  &fall_through,
-                 Assembler::kNearJump,
+                 Assembler::kFarJump,
                  RAX,  // Result register.
                  kNoRegister);  // Pool pointer might not be loaded.
   __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
@@ -1460,7 +1461,7 @@
       Isolate::Current()->object_store()->double_class());
   __ TryAllocate(double_class,
                  &fall_through,
-                 Assembler::kNearJump,
+                 Assembler::kFarJump,
                  RAX,  // Result register.
                  kNoRegister);  // Pool pointer might not be loaded.
   __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
@@ -1726,6 +1727,7 @@
                                      Label* ok,
                                      Label* failure,
                                      Register length_reg) {
+  __ MaybeTraceAllocation(kOneByteStringCid, failure, false);
   if (length_reg != RDI) {
     __ movq(RDI, length_reg);
   }
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 50df955..b247e56 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -36,6 +36,7 @@
 #include "vm/symbols.h"
 #include "vm/tags.h"
 #include "vm/thread_interrupter.h"
+#include "vm/thread_registry.h"
 #include "vm/timeline.h"
 #include "vm/timer.h"
 #include "vm/visitor.h"
@@ -622,9 +623,9 @@
   object##_handle_(NULL),
 
 Isolate::Isolate(const Dart_IsolateFlags& api_flags)
-  :   mutator_thread_(NULL),
-      vm_tag_(0),
+  :   vm_tag_(0),
       store_buffer_(new StoreBuffer()),
+      thread_registry_(new ThreadRegistry()),
       message_notify_callback_(NULL),
       name_(NULL),
       debugger_name_(NULL),
@@ -726,6 +727,7 @@
     compiler_stats_ = NULL;
   }
   RemoveTimelineEventRecorder();
+  delete thread_registry_;
 }
 
 
@@ -1532,9 +1534,6 @@
   // Visit objects in per isolate stubs.
   StubCode::VisitObjectPointers(visitor);
 
-  // Visit objects in zones.
-  current_zone()->VisitObjectPointers(visitor);
-
   // Visit objects in isolate specific handles area.
   reusable_handles_.VisitObjectPointers(visitor);
 
@@ -1571,6 +1570,9 @@
   if (deopt_context() != NULL) {
     deopt_context()->VisitObjectPointers(visitor);
   }
+
+  // Visit objects in thread registry (e.g., handles in zones).
+  thread_registry()->VisitObjectPointers(visitor);
 }
 
 
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 447afac..88c789d 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -78,6 +78,7 @@
 class StackZone;
 class StoreBuffer;
 class StubCode;
+class ThreadRegistry;
 class TypeArguments;
 class TypeParameter;
 class UserTag;
@@ -144,6 +145,8 @@
 
   StoreBuffer* store_buffer() { return store_buffer_; }
 
+  ThreadRegistry* thread_registry() { return thread_registry_; }
+
   ClassTable* class_table() { return &class_table_; }
   static intptr_t class_table_offset() {
     return OFFSET_OF(Isolate, class_table_);
@@ -208,10 +211,24 @@
     return OFFSET_OF(Isolate, object_store_);
   }
 
-  uword top_exit_frame_info() const { return top_exit_frame_info_; }
-  void set_top_exit_frame_info(uword value) { top_exit_frame_info_ = value; }
-  static intptr_t top_exit_frame_info_offset() {
-    return OFFSET_OF(Isolate, top_exit_frame_info_);
+  // DEPRECATED: Use Thread's methods instead. During migration, these default
+  // to using the mutator thread (which must also be the current thread).
+  StackResource* top_resource() const {
+    ASSERT(Thread::Current() == mutator_thread_);
+    return mutator_thread_->top_resource();
+  }
+  void set_top_resource(StackResource* value) {
+    ASSERT(Thread::Current() == mutator_thread_);
+    mutator_thread_->set_top_resource(value);
+  }
+  // DEPRECATED: Use Thread's methods instead. During migration, these default
+  // to using the mutator thread.
+  // NOTE: These are also used by the profiler.
+  uword top_exit_frame_info() const {
+    return mutator_thread_->top_exit_frame_info();
+  }
+  void set_top_exit_frame_info(uword value) {
+    mutator_thread_->set_top_exit_frame_info(value);
   }
 
   uword vm_tag() const {
@@ -719,6 +736,17 @@
   // Handle service messages until we are told to resume execution.
   void PauseEventHandler();
 
+  // DEPRECATED: Use Thread's methods instead. During migration, these default
+  // to using the mutator thread (which must also be the current thread).
+  Zone* current_zone() const {
+    ASSERT(Thread::Current() == mutator_thread_);
+    return mutator_thread_->zone();
+  }
+  void set_current_zone(Zone* zone) {
+    ASSERT(Thread::Current() == mutator_thread_);
+    mutator_thread_->set_zone(zone);
+  }
+
  private:
   explicit Isolate(const Dart_IsolateFlags& api_flags);
 
@@ -743,9 +771,9 @@
 
   template<class T> T* AllocateReusableHandle();
 
-  Thread* mutator_thread_;
   uword vm_tag_;
   StoreBuffer* store_buffer_;
+  ThreadRegistry* thread_registry_;
   ClassTable class_table_;
   MegamorphicCacheTable megamorphic_cache_table_;
   Dart_MessageNotifyCallback message_notify_callback_;
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index e716e50..5b10ab0 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -131,14 +131,12 @@
     JSONObject data(&jsobj, "data");
     PrintRequest(&data, this);
     if (details_format != NULL) {
-      Isolate* isolate = Isolate::Current();
-
       va_list args;
       va_start(args, details_format);
       intptr_t len = OS::VSNPrint(NULL, 0, details_format, args);
       va_end(args);
 
-      char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
+      char* buffer = Thread::Current()->zone()->Alloc<char>(len + 1);
       va_list args2;
       va_start(args2, details_format);
       OS::VSNPrint(buffer, (len + 1), details_format, args2);
diff --git a/runtime/vm/locations.cc b/runtime/vm/locations.cc
index 69fc7cc..525855a 100644
--- a/runtime/vm/locations.cc
+++ b/runtime/vm/locations.cc
@@ -219,7 +219,7 @@
   char buffer[1024];
   BufferFormatter bf(buffer, 1024);
   PrintTo(&bf);
-  return Isolate::Current()->current_zone()->MakeCopyOfString(buffer);
+  return Thread::Current()->zone()->MakeCopyOfString(buffer);
 }
 
 
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 907156f..18d86ff 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -66,13 +66,15 @@
 DEFINE_FLAG(bool, use_lib_cache, true, "Use library name cache");
 DEFINE_FLAG(bool, trace_field_guards, false, "Trace changes in field's cids.");
 
+DECLARE_FLAG(charp, coverage_dir);
+DECLARE_FLAG(bool, load_deferred_eagerly);
+DECLARE_FLAG(bool, show_invisible_frames);
 DECLARE_FLAG(bool, trace_compiler);
 DECLARE_FLAG(bool, trace_deoptimization);
 DECLARE_FLAG(bool, trace_deoptimization_verbose);
-DECLARE_FLAG(bool, show_invisible_frames);
-DECLARE_FLAG(charp, coverage_dir);
 DECLARE_FLAG(bool, write_protect_code);
 
+
 static const char* kGetterPrefix = "get:";
 static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix);
 static const char* kSetterPrefix = "set:";
@@ -627,6 +629,9 @@
   // isolate.
   Class::NewExternalTypedDataClass(kExternalTypedDataUint8ArrayCid);
 
+  // Needed for object pools of VM isolate stubs.
+  Class::NewTypedDataClass(kTypedDataInt8ArrayCid);
+
   // Allocate and initialize the empty_array instance.
   {
     uword address = heap->Allocate(Array::InstanceSize(0), Heap::kOld);
@@ -1440,7 +1445,6 @@
 
   // Finish the initialization by compiling the bootstrap scripts containing the
   // base interfaces and the implementation of the internal classes.
-  StubCode::InitBootstrapStubs(isolate);
   const Error& error = Error::Handle(Bootstrap::LoadandCompileScripts());
   if (!error.IsNull()) {
     return error.raw();
@@ -1593,7 +1597,6 @@
                                            Context::New(0, Heap::kOld));
   object_store->set_empty_context(context);
 
-  StubCode::InitBootstrapStubs(isolate);
 #endif  // defined(DART_NO_SNAPSHOT).
 
   return Error::null();
@@ -2736,6 +2739,9 @@
   set_state_bits(
       TraceAllocationBit::update(trace_allocation, raw_ptr()->state_bits_));
   if (changed) {
+    Isolate* isolate = Isolate::Current();
+    ClassTable* class_table = isolate->class_table();
+    class_table->TraceAllocationsFor(id(), trace_allocation);
     DisableAllocationStub();
   }
 }
@@ -4168,7 +4174,7 @@
   const char* library_name = lib.IsNull() ? "" : lib.ToCString();
   const char* class_name = String::Handle(Name()).ToCString();
   intptr_t len = OS::SNPrint(NULL, 0, format, library_name, class_name) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, format, library_name, class_name);
   return chars;
 }
@@ -4339,7 +4345,7 @@
   const char* format = "unresolved class '%s'";
   const char* cname =  String::Handle(Name()).ToCString();
   intptr_t len = OS::SNPrint(NULL, 0, format, cname) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, format, cname);
   return chars;
 }
@@ -5093,7 +5099,7 @@
     const AbstractType& type_at = AbstractType::Handle(TypeAt(i));
     const char* type_cstr = type_at.IsNull() ? "null" : type_at.ToCString();
     intptr_t len = OS::SNPrint(NULL, 0, format, prev_cstr, type_cstr) + 1;
-    char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+    char* chars = Thread::Current()->zone()->Alloc<char>(len);
     OS::SNPrint(chars, len, format, prev_cstr, type_cstr);
     prev_cstr = chars;
   }
@@ -5106,7 +5112,7 @@
   const Class& cls = Class::Handle(patched_class());
   const char* cls_name = cls.ToCString();
   intptr_t len = OS::SNPrint(NULL, 0, kFormat, cls_name) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, kFormat, cls_name);
   return chars;
 }
@@ -5921,7 +5927,7 @@
     reserve_len +=
         OS::SNPrint(NULL, 0, lib_class_format, library_name, class_name);
     ASSERT(chars != NULL);
-    *chars = Isolate::Current()->current_zone()->Alloc<char>(reserve_len + 1);
+    *chars = Thread::Current()->zone()->Alloc<char>(reserve_len + 1);
     written = OS::SNPrint(
         *chars, reserve_len + 1, lib_class_format, library_name, class_name);
   } else {
@@ -6926,7 +6932,7 @@
   const char* function_name = String::Handle(name()).ToCString();
   intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name,
                              static_str, abstract_str, kind_str, const_str) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, kFormat, function_name,
               static_str, abstract_str, kind_str, const_str);
   return chars;
@@ -7318,7 +7324,7 @@
   const char* cls_name = String::Handle(cls.Name()).ToCString();
   intptr_t len =
       OS::SNPrint(NULL, 0, kFormat, cls_name, field_name, kF0, kF1, kF2) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, kFormat, cls_name, field_name, kF0, kF1, kF2);
   return chars;
 }
@@ -7528,10 +7534,10 @@
       is_final()) {
     ASSERT(guarded_list_length() != kUnknownFixedLength);
     if (guarded_list_length() == kNoFixedLength) {
-      return Isolate::Current()->current_zone()->PrintToString(
+      return Thread::Current()->zone()->PrintToString(
           "<%s [*]>", class_name);
     } else {
-      return Isolate::Current()->current_zone()->PrintToString(
+      return Thread::Current()->zone()->PrintToString(
           "<%s [%" Pd " @%" Pd "]>",
           class_name,
           guarded_list_length(),
@@ -7539,7 +7545,7 @@
     }
   }
 
-  return Isolate::Current()->current_zone()->PrintToString("<%s %s>",
+  return Thread::Current()->zone()->PrintToString("<%s %s>",
     is_nullable() ? "nullable" : "not-nullable",
     class_name);
 }
@@ -10011,7 +10017,7 @@
   const char* kFormat = "Library:'%s'";
   const String& name = String::Handle(url());
   intptr_t len = OS::SNPrint(NULL, 0, kFormat, name.ToCString()) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, kFormat, name.ToCString());
   return chars;
 }
@@ -10219,7 +10225,7 @@
 
 
 RawObject* LibraryPrefix::LookupObject(const String& name) const {
-  if (!is_loaded()) {
+  if (!is_loaded() && !FLAG_load_deferred_eagerly) {
     return Object::null();
   }
   Array& imports = Array::Handle(this->imports());
@@ -10425,7 +10431,7 @@
   const char* kFormat = "LibraryPrefix:'%s'";
   const String& prefix = String::Handle(name());
   intptr_t len = OS::SNPrint(NULL, 0, kFormat, prefix.ToCString()) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, kFormat, prefix.ToCString());
   return chars;
 }
@@ -10481,7 +10487,7 @@
   const char* kFormat = "Namespace for library '%s'";
   const Library& lib = Library::Handle(library());
   intptr_t len = OS::SNPrint(NULL, 0, kFormat, lib.ToCString()) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, kFormat, lib.ToCString());
   return chars;
 }
@@ -10989,7 +10995,7 @@
     }
   }
   // Allocate the buffer.
-  char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* buffer = Thread::Current()->zone()->Alloc<char>(len);
   // Layout the fields in the buffer.
   intptr_t index = 0;
   Iterator iter(*this, RawPcDescriptors::kAnyKind);
@@ -11177,7 +11183,7 @@
   } else {
     const char* kFormat = "%#" Px ": ";
     intptr_t fixed_length = OS::SNPrint(NULL, 0, kFormat, PcOffset()) + 1;
-    Isolate* isolate = Isolate::Current();
+    Thread* thread = Thread::Current();
     // Guard against integer overflow in the computation of alloc_size.
     //
     // TODO(kmillikin): We could just truncate the string if someone
@@ -11186,7 +11192,7 @@
       FATAL1("Length() is unexpectedly large (%" Pd ")", Length());
     }
     intptr_t alloc_size = fixed_length + Length();
-    char* chars = isolate->current_zone()->Alloc<char>(alloc_size);
+    char* chars = thread->zone()->Alloc<char>(alloc_size);
     intptr_t index = OS::SNPrint(chars, alloc_size, kFormat, PcOffset());
     for (intptr_t i = 0; i < Length(); i++) {
       chars[index++] = IsObject(i) ? '1' : '0';
@@ -11301,7 +11307,7 @@
     GetInfo(i, &info);
     len += PrintVarInfo(NULL, 0, i, var_name, info);
   }
-  char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
+  char* buffer = Thread::Current()->zone()->Alloc<char>(len + 1);
   buffer[0] = '\0';
   intptr_t num_chars = 0;
   for (intptr_t i = 0; i < Length(); i++) {
@@ -11544,7 +11550,7 @@
     }
   }
   // Allocate the buffer.
-  char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* buffer = Thread::Current()->zone()->Alloc<char>(len);
   // Layout the fields in the buffer.
   intptr_t num_chars = 0;
   for (intptr_t i = 0; i < num_entries(); i++) {
@@ -11653,7 +11659,7 @@
   }
 
   // Allocate the buffer.
-  char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* buffer = Thread::Current()->zone()->Alloc<char>(len);
 
   // Layout the fields in the buffer.
   intptr_t index = 0;
@@ -11690,7 +11696,7 @@
   const intptr_t num_checks = NumberOfChecks();
   intptr_t len = OS::SNPrint(NULL, 0, kFormat, name.ToCString(),
       num_args, num_checks) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, kFormat, name.ToCString(), num_args, num_checks);
   return chars;
 }
@@ -12953,7 +12959,7 @@
 const char* Code::ToCString() const {
   const char* kFormat = "Code entry:%p";
   intptr_t len = OS::SNPrint(NULL, 0, kFormat, EntryPoint()) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, kFormat, EntryPoint());
   return chars;
 }
@@ -13272,7 +13278,7 @@
   if (IsNull()) {
     return "Context (Null)";
   }
-  Zone* zone = Isolate::Current()->current_zone();
+  Zone* zone = Thread::Current()->zone();
   const Context& parent_ctx = Context::Handle(parent());
   if (parent_ctx.IsNull()) {
     return zone->PrintToString("Context@%p num_variables:% " Pd "",
@@ -13473,7 +13479,7 @@
     intptr_t lvl = ContextLevelAt(i);
     intptr_t len =
         OS::SNPrint(NULL, 0, format, prev_cstr, cname, pos, lvl, idx) + 1;
-    char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+    char* chars = Thread::Current()->zone()->Alloc<char>(len);
     OS::SNPrint(chars, len, format, prev_cstr, cname, pos, lvl, idx);
     prev_cstr = chars;
   }
@@ -13930,7 +13936,8 @@
 
 
 const char* UnhandledException::ToErrorCString() const {
-  Isolate* isolate = Isolate::Current();
+  Thread* thread = Thread::Current();
+  Isolate* isolate = thread->isolate();
   HANDLESCOPE(isolate);
   Object& strtmp = Object::Handle();
   const char* exc_str;
@@ -13956,7 +13963,7 @@
   }
   const char* format = "Unhandled exception:\n%s\n%s";
   intptr_t len = OS::SNPrint(NULL, 0, format, exc_str, stack_str);
-  char* chars = isolate->current_zone()->Alloc<char>(len);
+  char* chars = thread->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, format, exc_str, stack_str);
   return chars;
 }
@@ -14122,7 +14129,7 @@
           const char* kFormat = "field: %s\n";
           const intptr_t len =
               OS::SNPrint(NULL, 0, kFormat, obj.ToCString()) + 1;
-          char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+          char* chars = Thread::Current()->zone()->Alloc<char>(len);
           OS::SNPrint(chars, len, kFormat, obj.ToCString());
           *error_str = chars;
           return false;
@@ -14456,7 +14463,7 @@
     const String& type_name = String::Handle(type.UserVisibleName());
     // Calculate the size of the string.
     intptr_t len = OS::SNPrint(NULL, 0, kFormat, type_name.ToCString()) + 1;
-    char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+    char* chars = Thread::Current()->zone()->Alloc<char>(len);
     OS::SNPrint(chars, len, kFormat, type_name.ToCString());
     return chars;
   }
@@ -15612,7 +15619,7 @@
     const char* format = "%sType: class '%s'";
     const intptr_t len =
         OS::SNPrint(NULL, 0, format, unresolved, class_name) + 1;
-    char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+    char* chars = Thread::Current()->zone()->Alloc<char>(len);
     OS::SNPrint(chars, len, format, unresolved, class_name);
     return chars;
   } else if (IsResolved() && IsFinalized() && IsRecursive()) {
@@ -15621,7 +15628,7 @@
     const char* args_cstr = TypeArguments::Handle(arguments()).ToCString();
     const intptr_t len =
         OS::SNPrint(NULL, 0, format, raw(), hash, class_name, args_cstr) + 1;
-    char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+    char* chars = Thread::Current()->zone()->Alloc<char>(len);
     OS::SNPrint(chars, len, format, raw(), hash, class_name, args_cstr);
     return chars;
   } else {
@@ -15629,7 +15636,7 @@
     const char* args_cstr = TypeArguments::Handle(arguments()).ToCString();
     const intptr_t len =
         OS::SNPrint(NULL, 0, format, unresolved, class_name, args_cstr) + 1;
-    char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+    char* chars = Thread::Current()->zone()->Alloc<char>(len);
     OS::SNPrint(chars, len, format, unresolved, class_name, args_cstr);
     return chars;
   }
@@ -15814,13 +15821,13 @@
     const intptr_t hash = ref_type.Hash();
     const intptr_t len =
         OS::SNPrint(NULL, 0, format, type_cstr, ref_type.raw(), hash) + 1;
-    char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+    char* chars = Thread::Current()->zone()->Alloc<char>(len);
     OS::SNPrint(chars, len, format, type_cstr, ref_type.raw(), hash);
     return chars;
   } else {
     const char* format = "TypeRef: %s<...>";
     const intptr_t len = OS::SNPrint(NULL, 0, format, type_cstr) + 1;
-    char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+    char* chars = Thread::Current()->zone()->Alloc<char>(len);
     OS::SNPrint(chars, len, format, type_cstr);
     return chars;
   }
@@ -16056,7 +16063,7 @@
   const char* bound_cstr = String::Handle(upper_bound.Name()).ToCString();
   intptr_t len = OS::SNPrint(
       NULL, 0, format, name_cstr, index(), cls_cstr, bound_cstr) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, format, name_cstr, index(), cls_cstr, bound_cstr);
   return chars;
 }
@@ -16271,7 +16278,7 @@
   const char* cls_cstr = String::Handle(cls.Name()).ToCString();
   intptr_t len = OS::SNPrint(
       NULL, 0, format, type_cstr, bound_cstr, type_param_cstr, cls_cstr) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(
       chars, len, format, type_cstr, bound_cstr, type_param_cstr, cls_cstr);
   return chars;
@@ -16317,7 +16324,7 @@
       MixinTypeAt(0)).Name()).ToCString();
   intptr_t len = OS::SNPrint(
       NULL, 0, format, super_type_cstr, first_mixin_type_cstr) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, format, super_type_cstr, first_mixin_type_cstr);
   return chars;
 }
@@ -16804,7 +16811,7 @@
   const char* kFormat = "%ld";
   // Calculate the size of the string.
   intptr_t len = OS::SNPrint(NULL, 0, kFormat, Value()) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, kFormat, Value());
   return chars;
 }
@@ -16935,7 +16942,7 @@
   const char* kFormat = "%lld";
   // Calculate the size of the string.
   intptr_t len = OS::SNPrint(NULL, 0, kFormat, value()) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, kFormat, value());
   return chars;
 }
@@ -17066,7 +17073,7 @@
     return value() < 0 ? "-Infinity" : "Infinity";
   }
   const int kBufferSize = 128;
-  char* buffer = Isolate::Current()->current_zone()->Alloc<char>(kBufferSize);
+  char* buffer = Thread::Current()->zone()->Alloc<char>(kBufferSize);
   buffer[kBufferSize - 1] = '\0';
   DoubleToCString(value(), buffer, kBufferSize);
   return buffer;
@@ -17815,7 +17822,7 @@
 
 
 static uword BigintAllocator(intptr_t size) {
-  Zone* zone = Isolate::Current()->current_zone();
+  Zone* zone = Thread::Current()->zone();
   return zone->AllocUnsafe(size);
 }
 
@@ -18401,7 +18408,7 @@
 
 RawString* String::EncodeIRI(const String& str) {
   const intptr_t len = Utf8::Length(str);
-  Zone* zone = Isolate::Current()->current_zone();
+  Zone* zone = Thread::Current()->zone();
   uint8_t* utf8 = zone->Alloc<uint8_t>(len);
   str.ToUTF8(utf8, len);
   intptr_t num_escapes = 0;
@@ -18465,7 +18472,7 @@
   }
   intptr_t utf8_len = len - num_escapes;
   ASSERT(utf8_len >= 0);
-  Zone* zone = Isolate::Current()->current_zone();
+  Zone* zone = Thread::Current()->zone();
   uint8_t* utf8 = zone->Alloc<uint8_t>(utf8_len);
   {
     intptr_t index = 0;
@@ -18508,7 +18515,7 @@
   intptr_t len = OS::VSNPrint(NULL, 0, format, args_copy);
   va_end(args_copy);
 
-  Zone* zone = Isolate::Current()->current_zone();
+  Zone* zone = Thread::Current()->zone();
   char* buffer = zone->Alloc<char>(len + 1);
   OS::VSNPrint(buffer, (len + 1), format, args);
 
@@ -18618,7 +18625,7 @@
     if (len == 0) {
       return "";
     }
-    Zone* zone = Isolate::Current()->current_zone();
+    Zone* zone = Thread::Current()->zone();
     uint8_t* result = zone->Alloc<uint8_t>(len + 1);
     NoSafepointScope no_safepoint;
     const uint8_t* original_str = OneByteString::CharAddr(*this, 0);
@@ -18636,7 +18643,7 @@
     }
   }
   const intptr_t len = Utf8::Length(*this);
-  Zone* zone = Isolate::Current()->current_zone();
+  Zone* zone = Thread::Current()->zone();
   uint8_t* result = zone->Alloc<uint8_t>(len + 1);
   ToUTF8(result, len);
   result[len] = 0;
@@ -18840,7 +18847,7 @@
   } else if (str.IsExternalOneByteString()) {
     startChar = ExternalOneByteString::CharAddr(str, start);
   } else {
-    uint8_t* chars = Isolate::Current()->current_zone()->Alloc<uint8_t>(length);
+    uint8_t* chars = Thread::Current()->zone()->Alloc<uint8_t>(length);
     const Scanner::CharAtFunc char_at = str.CharAtFunc();
     for (intptr_t i = 0; i < length; i++) {
       int32_t ch = char_at(str, start + i);
@@ -19665,7 +19672,7 @@
   if (IsNull()) {
     return IsImmutable() ? "_ImmutableList NULL" : "_List NULL";
   }
-  Zone* zone = Isolate::Current()->current_zone();
+  Zone* zone = Thread::Current()->zone();
   const char* format = IsImmutable() ? "_ImmutableList len:%" Pd
                                      : "_List len:%" Pd;
   return zone->PrintToString(format, Length());
@@ -19782,7 +19789,7 @@
         const char* kFormat = "element at index %" Pd ": %s\n";
         const intptr_t len =
             OS::SNPrint(NULL, 0, kFormat, i, obj.ToCString()) + 1;
-        char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+        char* chars = Thread::Current()->zone()->Alloc<char>(len);
         OS::SNPrint(chars, len, kFormat, i, obj.ToCString());
         *error_str = chars;
         return false;
@@ -19909,7 +19916,7 @@
   }
   const char* format = "Instance(length:%" Pd ") of '_GrowableList'";
   intptr_t len = OS::SNPrint(NULL, 0, format, Length()) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, format, Length());
   return chars;
 }
@@ -20017,7 +20024,7 @@
 
 
 const char* LinkedHashMap::ToCString() const {
-  Zone* zone = Isolate::Current()->current_zone();
+  Zone* zone = Thread::Current()->zone();
   return zone->PrintToString("_LinkedHashMap len:%" Pd, Length());
 }
 
@@ -20140,7 +20147,7 @@
   float _w = w();
   // Calculate the size of the string.
   intptr_t len = OS::SNPrint(NULL, 0, kFormat, _x, _y, _z, _w) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, kFormat, _x, _y, _z, _w);
   return chars;
 }
@@ -20245,7 +20252,7 @@
   int32_t _w = w();
   // Calculate the size of the string.
   intptr_t len = OS::SNPrint(NULL, 0, kFormat, _x, _y, _z, _w) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, kFormat, _x, _y, _z, _w);
   return chars;
 }
@@ -20325,7 +20332,7 @@
   double _y = y();
   // Calculate the size of the string.
   intptr_t len = OS::SNPrint(NULL, 0, kFormat, _x, _y) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, kFormat, _x, _y);
   return chars;
 }
@@ -20595,7 +20602,7 @@
   const char* fun_desc = is_implicit_closure ? fun.ToCString() : "";
   const char* format = "Closure: %s%s%s";
   intptr_t len = OS::SNPrint(NULL, 0, format, fun_sig, from, fun_desc) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len);
   OS::SNPrint(chars, len, format, fun_sig, from, fun_desc);
   return chars;
 }
@@ -20711,7 +20718,7 @@
 }
 
 
-static intptr_t PrintOneStacktrace(Isolate* isolate,
+static intptr_t PrintOneStacktrace(Zone* zone,
                                    GrowableArray<char*>* frame_strings,
                                    uword pc,
                                    const Function& function,
@@ -20721,10 +20728,10 @@
   const char* kFormatNoCol = "#%-6d %s (%s:%d)\n";
   const char* kFormatNoLine = "#%-6d %s (%s)\n";
   const intptr_t token_pos = code.GetTokenIndexOfPC(pc);
-  const Script& script = Script::Handle(isolate, function.script());
+  const Script& script = Script::Handle(zone, function.script());
   const String& function_name =
-      String::Handle(isolate, function.QualifiedUserVisibleName());
-  const String& url = String::Handle(isolate, script.url());
+      String::Handle(zone, function.QualifiedUserVisibleName());
+  const String& url = String::Handle(zone, script.url());
   intptr_t line = -1;
   intptr_t column = -1;
   if (token_pos > 0) {
@@ -20740,7 +20747,7 @@
     len = OS::SNPrint(NULL, 0, kFormatWithCol,
                       frame_index, function_name.ToCString(),
                       url.ToCString(), line, column);
-    chars = isolate->current_zone()->Alloc<char>(len + 1);
+    chars = zone->Alloc<char>(len + 1);
     OS::SNPrint(chars, (len + 1), kFormatWithCol,
                 frame_index,
                 function_name.ToCString(),
@@ -20749,7 +20756,7 @@
     len = OS::SNPrint(NULL, 0, kFormatNoCol,
                       frame_index, function_name.ToCString(),
                       url.ToCString(), line);
-    chars = isolate->current_zone()->Alloc<char>(len + 1);
+    chars = zone->Alloc<char>(len + 1);
     OS::SNPrint(chars, (len + 1), kFormatNoCol,
                 frame_index, function_name.ToCString(),
                 url.ToCString(), line);
@@ -20757,7 +20764,7 @@
     len = OS::SNPrint(NULL, 0, kFormatNoLine,
                       frame_index, function_name.ToCString(),
                       url.ToCString());
-    chars = isolate->current_zone()->Alloc<char>(len + 1);
+    chars = zone->Alloc<char>(len + 1);
     OS::SNPrint(chars, (len + 1), kFormatNoLine,
                 frame_index, function_name.ToCString(),
                 url.ToCString());
@@ -20769,7 +20776,7 @@
 
 const char* Stacktrace::ToCStringInternal(intptr_t* frame_index,
                                           intptr_t max_frames) const {
-  Isolate* isolate = Isolate::Current();
+  Zone* zone = Thread::Current()->zone();
   Function& function = Function::Handle();
   Code& code = Code::Handle();
   // Iterate through the stack frames and create C string description
@@ -20784,7 +20791,7 @@
           (FunctionAtFrame(i + 1) != Function::null())) {
         const char* kTruncated = "...\n...\n";
         intptr_t truncated_len = strlen(kTruncated) + 1;
-        char* chars = isolate->current_zone()->Alloc<char>(truncated_len);
+        char* chars = zone->Alloc<char>(truncated_len);
         OS::SNPrint(chars, truncated_len, "%s", kTruncated);
         frame_strings.Add(chars);
         total_len += truncated_len;
@@ -20806,20 +20813,20 @@
             ASSERT(code.EntryPoint() <= pc);
             ASSERT(pc < (code.EntryPoint() + code.Size()));
             total_len += PrintOneStacktrace(
-                isolate, &frame_strings, pc, function, code, *frame_index);
+                zone, &frame_strings, pc, function, code, *frame_index);
             (*frame_index)++;  // To account for inlined frames.
           }
         }
       } else {
         total_len += PrintOneStacktrace(
-            isolate, &frame_strings, pc, function, code, *frame_index);
+            zone, &frame_strings, pc, function, code, *frame_index);
         (*frame_index)++;
       }
     }
   }
 
   // Now concatenate the frame descriptions into a single C string.
-  char* chars = isolate->current_zone()->Alloc<char>(total_len + 1);
+  char* chars = zone->Alloc<char>(total_len + 1);
   intptr_t index = 0;
   for (intptr_t i = 0; i < frame_strings.length(); i++) {
     index += OS::SNPrint((chars + index),
@@ -20932,7 +20939,7 @@
   const String& str = String::Handle(pattern());
   const char* format = "JSRegExp: pattern=%s flags=%s";
   intptr_t len = OS::SNPrint(NULL, 0, format, str.ToCString(), Flags());
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
+  char* chars = Thread::Current()->zone()->Alloc<char>(len + 1);
   OS::SNPrint(chars, (len + 1), format, str.ToCString(), Flags());
   return chars;
 }
diff --git a/runtime/vm/os_android.cc b/runtime/vm/os_android.cc
index 6606381..676e278 100644
--- a/runtime/vm/os_android.cc
+++ b/runtime/vm/os_android.cc
@@ -76,7 +76,7 @@
     const char* format = "%" Px " %" Px " %s%s\n";
     const char* marker = optimized ? "*" : "";
     intptr_t len = OS::SNPrint(NULL, 0, format, base, size, marker, name);
-    char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
+    char* buffer = Thread::Current()->zone()->Alloc<char>(len + 1);
     OS::SNPrint(buffer, len + 1, format, base, size, marker, name);
     (*file_write)(buffer, len, out_file_);
   }
@@ -109,7 +109,7 @@
       // <name> for rest of the code (first instruction is prologue sequence).
       const char* kFormat = "%s_%s";
       intptr_t len = OS::SNPrint(NULL, 0, kFormat, name, "entry");
-      char* pname = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
+      char* pname = Thread::Current()->zone()->Alloc<char>(len + 1);
       OS::SNPrint(pname, (len + 1), kFormat, name, "entry");
       DebugInfo::RegisterSection(pname, base, size);
       DebugInfo::RegisterSection(name,
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index 430af48..288db46 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -82,7 +82,7 @@
     const char* format = "%" Px " %" Px " %s%s\n";
     const char* marker = optimized ? "*" : "";
     intptr_t len = OS::SNPrint(NULL, 0, format, base, size, marker, name);
-    char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
+    char* buffer = Thread::Current()->zone()->Alloc<char>(len + 1);
     OS::SNPrint(buffer, len + 1, format, base, size, marker, name);
     {
       MutexLocker ml(CodeObservers::mutex());
@@ -118,7 +118,7 @@
       // <name> for rest of the code (first instruction is prologue sequence).
       const char* kFormat = "%s_%s";
       intptr_t len = OS::SNPrint(NULL, 0, kFormat, name, "entry");
-      char* pname = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
+      char* pname = Thread::Current()->zone()->Alloc<char>(len + 1);
       OS::SNPrint(pname, (len + 1), kFormat, name, "entry");
       DebugInfo::RegisterSection(pname, base, size);
       DebugInfo::RegisterSection(name,
@@ -248,7 +248,7 @@
     const char* format = "%s%s";
     const char* marker = optimized ? "*" : "";
     intptr_t len = OS::SNPrint(NULL, 0, format, marker, name);
-    char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
+    char* buffer = Thread::Current()->zone()->Alloc<char>(len + 1);
     OS::SNPrint(buffer, len + 1, format, marker, name);
     return buffer;
   }
diff --git a/runtime/vm/os_thread.h b/runtime/vm/os_thread.h
index 2dfd3f5..c3250d8 100644
--- a/runtime/vm/os_thread.h
+++ b/runtime/vm/os_thread.h
@@ -6,7 +6,7 @@
 #define VM_OS_THREAD_H_
 
 #include "platform/globals.h"
-#include "vm/allocation.h"
+#include "vm/globals.h"
 
 // Declare the OS-specific types ahead of defining the generic classes.
 #if defined(TARGET_OS_ANDROID)
@@ -24,7 +24,8 @@
 namespace dart {
 
 // Low-level operations on OS platform threads.
-class OSThread : AllStatic {
+// TODO(koda): Move to runtime/platform.
+class OSThread {
  public:
   static ThreadLocalKey kUnsetThreadLocalKey;
   static ThreadId kInvalidThreadId;
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index a966b40..d3ccd42 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -38,15 +38,17 @@
 namespace dart {
 
 DEFINE_FLAG(bool, enable_debug_break, false, "Allow use of break \"message\".");
+DEFINE_FLAG(bool, enable_mirrors, true,
+    "Disable to make importing dart:mirrors an error.");
 DEFINE_FLAG(bool, load_deferred_eagerly, false,
     "Load deferred libraries eagerly.");
 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations.");
 DEFINE_FLAG(bool, warn_mixin_typedef, true, "Warning on legacy mixin typedef.");
+
+DECLARE_FLAG(bool, lazy_dispatchers);
+DECLARE_FLAG(bool, load_deferred_eagerly);
 DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
 DECLARE_FLAG(bool, warn_on_javascript_compatibility);
-DEFINE_FLAG(bool, enable_mirrors, true,
-    "Disable to make importing dart:mirrors an error.");
-DECLARE_FLAG(bool, lazy_dispatchers);
 
 // Quick access to the current isolate and zone.
 #define I (isolate())
@@ -172,6 +174,9 @@
 
 
 void ParsedFunction::AddDeferredPrefix(const LibraryPrefix& prefix) {
+  // 'deferred_prefixes_' are used to invalidate code, but no invalidation is
+  // needed if --load_deferred_eagerly.
+  ASSERT(!FLAG_load_deferred_eagerly);
   ASSERT(prefix.is_deferred_load());
   ASSERT(!prefix.is_loaded());
   for (intptr_t i = 0; i < deferred_prefixes_->length(); i++) {
@@ -10038,8 +10043,19 @@
 }
 
 
-AstNode* Parser::ThrowTypeError(intptr_t type_pos, const AbstractType& type) {
+// Call _throwNewIfNotLoaded if prefix is not NULL, otherwise call _throwNew.
+AstNode* Parser::ThrowTypeError(intptr_t type_pos, const AbstractType& type,
+                                LibraryPrefix* prefix) {
   ArgumentListNode* arguments = new(Z) ArgumentListNode(type_pos);
+
+  String& method_name = String::Handle(Z);
+  if (prefix == NULL) {
+    method_name = Library::PrivateCoreLibName(Symbols::ThrowNew()).raw();
+  } else {
+    arguments->Add(new(Z) LiteralNode(type_pos, *prefix));
+    method_name = Library::PrivateCoreLibName(
+        Symbols::ThrowNewIfNotLoaded()).raw();
+  }
   // Location argument.
   arguments->Add(new(Z) LiteralNode(
       type_pos, Integer::ZoneHandle(Z, Integer::New(type_pos))));
@@ -10054,20 +10070,29 @@
   ASSERT(!error.IsNull());
   arguments->Add(new(Z) LiteralNode(type_pos, String::ZoneHandle(Z,
       Symbols::New(error.ToErrorCString()))));
-  return MakeStaticCall(Symbols::TypeError(),
-                        Library::PrivateCoreLibName(Symbols::ThrowNew()),
-                        arguments);
+  return MakeStaticCall(Symbols::TypeError(), method_name, arguments);
 }
 
 
+// Call _throwNewIfNotLoaded if prefix is not NULL, otherwise call _throwNew.
 AstNode* Parser::ThrowNoSuchMethodError(intptr_t call_pos,
                                         const Class& cls,
                                         const String& function_name,
                                         ArgumentListNode* function_arguments,
                                         InvocationMirror::Call im_call,
                                         InvocationMirror::Type im_type,
-                                        const Function* func) {
+                                        const Function* func,
+                                        const LibraryPrefix* prefix) {
   ArgumentListNode* arguments = new(Z) ArgumentListNode(call_pos);
+
+  String& method_name = String::Handle(Z);
+  if (prefix == NULL) {
+    method_name = Library::PrivateCoreLibName(Symbols::ThrowNew()).raw();
+  } else {
+    arguments->Add(new(Z) LiteralNode(call_pos, *prefix));
+    method_name = Library::PrivateCoreLibName(
+        Symbols::ThrowNewIfNotLoaded()).raw();
+  }
   // Object receiver.
   // If the function is external and dynamic, pass the actual receiver,
   // otherwise, pass a class literal of the unresolved method's owner.
@@ -10140,9 +10165,7 @@
   }
   arguments->Add(new(Z) LiteralNode(call_pos, array));
 
-  return MakeStaticCall(Symbols::NoSuchMethodError(),
-                        Library::PrivateCoreLibName(Symbols::ThrowNew()),
-                        arguments);
+  return MakeStaticCall(Symbols::NoSuchMethodError(), method_name, arguments);
 }
 
 
@@ -11816,7 +11839,7 @@
     return NULL;
   }
   Object& obj = Object::Handle(Z);
-  if (prefix.is_loaded()) {
+  if (prefix.is_loaded() || FLAG_load_deferred_eagerly) {
     obj = prefix.LookupObject(ident);
   } else {
     // Remember that this function depends on an import prefix of an
@@ -11952,16 +11975,25 @@
 }
 
 
-// Parses type = [ident "."] ident ["<" type { "," type } ">"], then resolve and
-// finalize it according to the given type finalization mode.
 RawAbstractType* Parser::ParseType(
     ClassFinalizer::FinalizationKind finalization,
     bool allow_deferred_type,
     bool consume_unresolved_prefix) {
+  LibraryPrefix& prefix = LibraryPrefix::Handle(Z);
+  return ParseType(finalization, allow_deferred_type,
+                         consume_unresolved_prefix, &prefix);
+}
+
+// Parses type = [ident "."] ident ["<" type { "," type } ">"], then resolve and
+// finalize it according to the given type finalization mode. Returns prefix.
+RawAbstractType* Parser::ParseType(
+    ClassFinalizer::FinalizationKind finalization,
+    bool allow_deferred_type,
+    bool consume_unresolved_prefix,
+    LibraryPrefix* prefix) {
   TRACE_PARSER("ParseType");
   CheckToken(Token::kIDENT, "type name expected");
   intptr_t ident_pos = TokenPos();
-  LibraryPrefix& prefix = LibraryPrefix::Handle(Z);
   String& type_name = String::Handle(Z);
 
   if (finalization == ClassFinalizer::kIgnore) {
@@ -11972,7 +12004,7 @@
     }
     SkipQualIdent();
   } else {
-    prefix = ParsePrefix();
+    *prefix = ParsePrefix();
     type_name = CurrentLiteral()->raw();
     ConsumeToken();
 
@@ -11982,7 +12014,7 @@
     // a period and another identifier, consume the qualified identifier
     // and create a malformed type.
     if (consume_unresolved_prefix &&
-        prefix.IsNull() &&
+        prefix->IsNull() &&
         (CurrentToken() == Token::kPERIOD) &&
         (Token::IsIdentifier(LookaheadToken(1)))) {
       if (!is_top_level_ && (current_block_ != NULL)) {
@@ -12009,7 +12041,7 @@
     // If parsing inside a local scope, check whether the type name
     // is shadowed by a local declaration.
     if (!is_top_level_ &&
-        (prefix.IsNull()) &&
+        (prefix->IsNull()) &&
         ResolveIdentInLocalScope(ident_pos, type_name, NULL)) {
       // The type is malformed. Skip over its type arguments.
       ParseTypeArguments(ClassFinalizer::kIgnore);
@@ -12020,29 +12052,30 @@
           "using '%s' in this context is invalid",
           type_name.ToCString());
     }
-    if (!prefix.IsNull() && prefix.is_deferred_load()) {
+    if ((!FLAG_load_deferred_eagerly || !allow_deferred_type) &&
+        !prefix->IsNull() && prefix->is_deferred_load()) {
       // If deferred prefixes are allowed but it is not yet loaded,
       // remember that this function depends on the prefix.
-      if (allow_deferred_type && !prefix.is_loaded()) {
+      if (allow_deferred_type && !prefix->is_loaded()) {
         if (parsed_function() != NULL) {
-          parsed_function()->AddDeferredPrefix(prefix);
+          parsed_function()->AddDeferredPrefix(*prefix);
         }
       }
       // If the deferred prefixes are not allowed, or if the prefix is not yet
       // loaded when finalization is requested, return a malformed type.
       // Otherwise, handle resolution below, as needed.
       if (!allow_deferred_type ||
-          (!prefix.is_loaded()
+          (!prefix->is_loaded()
               && (finalization > ClassFinalizer::kResolveTypeParameters))) {
         ParseTypeArguments(ClassFinalizer::kIgnore);
         return ClassFinalizer::NewFinalizedMalformedType(
             Error::Handle(Z),  // No previous error.
             script_,
             ident_pos,
-            !prefix.is_loaded()
+            !prefix->is_loaded() && allow_deferred_type
                 ? "deferred type '%s.%s' is not yet loaded"
                 : "using deferred type '%s.%s' is invalid",
-            String::Handle(Z, prefix.name()).ToCString(),
+            String::Handle(Z, prefix->name()).ToCString(),
             type_name.ToCString());
       }
     }
@@ -12050,7 +12083,7 @@
   Object& type_class = Object::Handle(Z);
   // Leave type_class as null if type finalization mode is kIgnore.
   if (finalization != ClassFinalizer::kIgnore) {
-    type_class = UnresolvedClass::New(prefix, type_name, ident_pos);
+    type_class = UnresolvedClass::New(*prefix, type_name, ident_pos);
   }
   TypeArguments& type_arguments = TypeArguments::Handle(
       Z, ParseTypeArguments(finalization));
@@ -12599,10 +12632,28 @@
   const bool allow_deferred_type = !is_const;
   const bool consume_unresolved_prefix = (LookaheadToken(3) == Token::kLT) ||
                                          (LookaheadToken(3) == Token::kPERIOD);
+  LibraryPrefix& prefix = LibraryPrefix::ZoneHandle(Z);
   AbstractType& type = AbstractType::Handle(Z,
       ParseType(ClassFinalizer::kCanonicalizeWellFormed,
                 allow_deferred_type,
-                consume_unresolved_prefix));
+                consume_unresolved_prefix,
+                &prefix));
+  if (FLAG_load_deferred_eagerly &&
+      !prefix.IsNull() && prefix.is_deferred_load() && !prefix.is_loaded()) {
+    // Add runtime check.
+    Type& malformed_type = Type::Handle(Z);
+    malformed_type = ClassFinalizer::NewFinalizedMalformedType(
+        Error::Handle(Z),  // No previous error.
+        script_,
+        type_pos,
+        "deferred type '%s.%s' is not yet loaded",
+        String::Handle(Z, prefix.name()).ToCString(),
+        String::Handle(type.Name()).ToCString());
+    // Note: Adding a statement to current block is a hack, parsing an
+    // expression should have no side-effect.
+    current_block_->statements->Add(
+        ThrowTypeError(type_pos, malformed_type, &prefix));
+  }
   // In case the type is malformed, throw a dynamic type error after finishing
   // parsing the instance creation expression.
   if (!type.IsMalformed() && (type.IsTypeParameter() || type.IsDynamicType())) {
@@ -13083,6 +13134,26 @@
                                            call_type,
                                            NULL);  // No existing function.
         }
+      } else if (FLAG_load_deferred_eagerly && prefix.is_deferred_load()) {
+        // primary != NULL.
+        String& qualified_name = String::ZoneHandle(Z, prefix.name());
+        qualified_name = String::Concat(qualified_name, Symbols::Dot());
+        qualified_name = String::Concat(qualified_name, ident);
+        qualified_name = Symbols::New(qualified_name);
+        InvocationMirror::Type call_type =
+            CurrentToken() == Token::kLPAREN ?
+                InvocationMirror::kMethod : InvocationMirror::kGetter;
+        // Note: Adding a statement to current block is a hack, parsing an
+        // espression should have no side-effect.
+        current_block_->statements->Add(ThrowNoSuchMethodError(
+                                            qual_ident_pos,
+                                            current_class(),
+                                            qualified_name,
+                                            NULL,  // No arguments.
+                                            InvocationMirror::kTopLevel,
+                                            call_type,
+                                            NULL,  // No existing function.
+                                            &prefix));
       }
     }
     ASSERT(primary != NULL);
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index ba56ec9..9cab860 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -432,6 +432,12 @@
   RawAbstractType* ParseType(ClassFinalizer::FinalizationKind finalization,
                              bool allow_deferred_type = false,
                              bool consume_unresolved_prefix = true);
+  RawAbstractType* ParseType(
+      ClassFinalizer::FinalizationKind finalization,
+      bool allow_deferred_type,
+      bool consume_unresolved_prefix,
+      LibraryPrefix* prefix);
+
   void ParseTypeParameters(const Class& cls);
   RawTypeArguments* ParseTypeArguments(
       ClassFinalizer::FinalizationKind finalization);
@@ -763,14 +769,16 @@
                           ArgumentListNode* arguments);
   String& Interpolate(const GrowableArray<AstNode*>& values);
   AstNode* MakeAssertCall(intptr_t begin, intptr_t end);
-  AstNode* ThrowTypeError(intptr_t type_pos, const AbstractType& type);
+  AstNode* ThrowTypeError(intptr_t type_pos, const AbstractType& type,
+                           LibraryPrefix* prefix = NULL);
   AstNode* ThrowNoSuchMethodError(intptr_t call_pos,
                                   const Class& cls,
                                   const String& function_name,
                                   ArgumentListNode* function_arguments,
                                   InvocationMirror::Call call,
                                   InvocationMirror::Type type,
-                                  const Function* func);
+                                  const Function* func,
+                                  const LibraryPrefix* prefix = NULL);
 
   void SetupSavedTryContext(LocalVariable* saved_try_context);
 
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index 5e8940a..fac0bf4 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -252,7 +252,7 @@
     name_ = NULL;
   }
   intptr_t len = strlen(name);
-  name_ = Isolate::Current()->current_zone()->Alloc<const char>(len + 1);
+  name_ = Thread::Current()->zone()->Alloc<const char>(len + 1);
   strncpy(const_cast<char*>(name_), name, len);
   const_cast<char*>(name_)[len] = '\0';
 }
diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
index 4f1ea87..b4b9080 100644
--- a/runtime/vm/profiler_test.cc
+++ b/runtime/vm/profiler_test.cc
@@ -103,7 +103,7 @@
 
 static RawClass* GetClass(const Library& lib, const char* name) {
   const Class& cls = Class::Handle(
-      lib.LookupClass(String::Handle(Symbols::New(name))));
+      lib.LookupClassAllowPrivate(String::Handle(Symbols::New(name))));
   EXPECT(!cls.IsNull());  // No ambiguity error expected.
   return cls.raw();
 }
@@ -313,4 +313,422 @@
   }
 }
 
+
+TEST_CASE(Profiler_IntrinsicAllocation) {
+  const char* kScript = "double foo(double a, double b) => a + b;";
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  Library& root_library = Library::Handle();
+  root_library ^= Api::UnwrapHandle(lib);
+  Isolate* isolate = Isolate::Current();
+
+  const Class& double_class =
+      Class::Handle(isolate->object_store()->double_class());
+  EXPECT(!double_class.IsNull());
+
+  Dart_Handle args[2] = { Dart_NewDouble(1.0), Dart_NewDouble(2.0), };
+
+  Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
+  EXPECT_VALID(result);
+
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, double_class.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should have no allocation samples.
+    EXPECT_EQ(0, profile.sample_count());
+  }
+
+  double_class.SetTraceAllocation(true);
+  result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
+  EXPECT_VALID(result);
+
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, double_class.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should have one allocation sample.
+    EXPECT_EQ(1, profile.sample_count());
+    ProfileTrieWalker walker(&profile);
+
+    walker.Reset(Profile::kExclusiveCode);
+    EXPECT(walker.Down());
+    EXPECT_STREQ("_Double._add", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("_Double.+", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("foo", walker.CurrentName());
+    EXPECT(!walker.Down());
+  }
+
+  double_class.SetTraceAllocation(false);
+  result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
+  EXPECT_VALID(result);
+
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, double_class.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should still only have one allocation sample.
+    EXPECT_EQ(1, profile.sample_count());
+  }
+}
+
+
+TEST_CASE(Profiler_ArrayAllocation) {
+  const char* kScript =
+      "List foo() => new List(4);\n"
+      "List bar() => new List();\n";
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  Library& root_library = Library::Handle();
+  root_library ^= Api::UnwrapHandle(lib);
+  Isolate* isolate = Isolate::Current();
+
+  const Class& array_class =
+      Class::Handle(isolate->object_store()->array_class());
+  EXPECT(!array_class.IsNull());
+
+  Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
+  EXPECT_VALID(result);
+
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, array_class.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should have no allocation samples.
+    EXPECT_EQ(0, profile.sample_count());
+  }
+
+  array_class.SetTraceAllocation(true);
+  result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
+  EXPECT_VALID(result);
+
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, array_class.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should have one allocation sample.
+    EXPECT_EQ(1, profile.sample_count());
+    ProfileTrieWalker walker(&profile);
+
+    walker.Reset(Profile::kExclusiveCode);
+    EXPECT(walker.Down());
+    EXPECT_STREQ("_List._List", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("List.List", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("foo", walker.CurrentName());
+    EXPECT(!walker.Down());
+  }
+
+  array_class.SetTraceAllocation(false);
+  result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
+  EXPECT_VALID(result);
+
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, array_class.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should still only have one allocation sample.
+    EXPECT_EQ(1, profile.sample_count());
+  }
+
+  // Clear the samples.
+  ProfilerService::ClearSamples();
+
+  // Compile bar (many List objects allocated).
+  result = Dart_Invoke(lib, NewString("bar"), 0, NULL);
+  EXPECT_VALID(result);
+
+  // Enable again.
+  array_class.SetTraceAllocation(true);
+
+  // Run bar.
+  result = Dart_Invoke(lib, NewString("bar"), 0, NULL);
+  EXPECT_VALID(result);
+
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, array_class.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should still only have one allocation sample.
+    EXPECT_EQ(1, profile.sample_count());
+    ProfileTrieWalker walker(&profile);
+
+    walker.Reset(Profile::kExclusiveCode);
+    EXPECT(walker.Down());
+    EXPECT_STREQ("_List._List", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("_GrowableList._GrowableList", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("List.List", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("bar", walker.CurrentName());
+    EXPECT(!walker.Down());
+  }
+}
+
+
+TEST_CASE(Profiler_TypedArrayAllocation) {
+  const char* kScript =
+      "import 'dart:typed_data';\n"
+      "List foo() => new Float32List(4);\n";
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  Library& root_library = Library::Handle();
+  root_library ^= Api::UnwrapHandle(lib);
+  Isolate* isolate = Isolate::Current();
+
+  const Library& typed_data_library =
+      Library::Handle(isolate->object_store()->typed_data_library());
+
+  const Class& float32_list_class =
+      Class::Handle(GetClass(typed_data_library, "_Float32Array"));
+  EXPECT(!float32_list_class.IsNull());
+
+  Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
+  EXPECT_VALID(result);
+
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, float32_list_class.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should have no allocation samples.
+    EXPECT_EQ(0, profile.sample_count());
+  }
+
+  float32_list_class.SetTraceAllocation(true);
+  result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
+  EXPECT_VALID(result);
+
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, float32_list_class.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should have one allocation sample.
+    EXPECT_EQ(1, profile.sample_count());
+    ProfileTrieWalker walker(&profile);
+
+    walker.Reset(Profile::kExclusiveCode);
+    EXPECT(walker.Down());
+    EXPECT_STREQ("_Float32Array._new", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("_Float32Array._Float32Array", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("Float32List.Float32List", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("foo", walker.CurrentName());
+    EXPECT(!walker.Down());
+  }
+
+  float32_list_class.SetTraceAllocation(false);
+  result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
+  EXPECT_VALID(result);
+
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, float32_list_class.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should still only have one allocation sample.
+    EXPECT_EQ(1, profile.sample_count());
+  }
+
+  float32_list_class.SetTraceAllocation(true);
+  result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
+  EXPECT_VALID(result);
+
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, float32_list_class.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should now have two allocation samples.
+    EXPECT_EQ(2, profile.sample_count());
+  }
+}
+
+
+TEST_CASE(Profiler_StringAllocation) {
+  const char* kScript = "String foo(String a, String b) => a + b;";
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  Library& root_library = Library::Handle();
+  root_library ^= Api::UnwrapHandle(lib);
+  Isolate* isolate = Isolate::Current();
+
+  const Class& one_byte_string_class =
+      Class::Handle(isolate->object_store()->one_byte_string_class());
+  EXPECT(!one_byte_string_class.IsNull());
+
+  Dart_Handle args[2] = { NewString("a"), NewString("b"), };
+
+  Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
+  EXPECT_VALID(result);
+
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, one_byte_string_class.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should have no allocation samples.
+    EXPECT_EQ(0, profile.sample_count());
+  }
+
+  one_byte_string_class.SetTraceAllocation(true);
+  result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
+  EXPECT_VALID(result);
+
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, one_byte_string_class.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should still only have one allocation sample.
+    EXPECT_EQ(1, profile.sample_count());
+    ProfileTrieWalker walker(&profile);
+
+    walker.Reset(Profile::kExclusiveCode);
+    EXPECT(walker.Down());
+    EXPECT_STREQ("_StringBase.+", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("foo", walker.CurrentName());
+    EXPECT(!walker.Down());
+  }
+
+  one_byte_string_class.SetTraceAllocation(false);
+  result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
+  EXPECT_VALID(result);
+
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, one_byte_string_class.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should still only have one allocation sample.
+    EXPECT_EQ(1, profile.sample_count());
+  }
+
+  one_byte_string_class.SetTraceAllocation(true);
+  result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
+  EXPECT_VALID(result);
+
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, one_byte_string_class.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should now have two allocation samples.
+    EXPECT_EQ(2, profile.sample_count());
+  }
+}
+
+
+TEST_CASE(Profiler_StringInterpolation) {
+  const char* kScript = "String foo(String a, String b) => '$a | $b';";
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  Library& root_library = Library::Handle();
+  root_library ^= Api::UnwrapHandle(lib);
+  Isolate* isolate = Isolate::Current();
+
+  const Class& one_byte_string_class =
+      Class::Handle(isolate->object_store()->one_byte_string_class());
+  EXPECT(!one_byte_string_class.IsNull());
+
+  Dart_Handle args[2] = { NewString("a"), NewString("b"), };
+
+  Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
+  EXPECT_VALID(result);
+
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, one_byte_string_class.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should have no allocation samples.
+    EXPECT_EQ(0, profile.sample_count());
+  }
+
+  one_byte_string_class.SetTraceAllocation(true);
+  result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
+  EXPECT_VALID(result);
+
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, one_byte_string_class.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should still only have one allocation sample.
+    EXPECT_EQ(1, profile.sample_count());
+    ProfileTrieWalker walker(&profile);
+
+    walker.Reset(Profile::kExclusiveCode);
+    EXPECT(walker.Down());
+    EXPECT_STREQ("_OneByteString._allocate", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("_OneByteString._concatAll", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("_StringBase._interpolate", walker.CurrentName());
+    EXPECT(walker.Down());
+    EXPECT_STREQ("foo", walker.CurrentName());
+    EXPECT(!walker.Down());
+  }
+
+  one_byte_string_class.SetTraceAllocation(false);
+  result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
+  EXPECT_VALID(result);
+
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, one_byte_string_class.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should still only have one allocation sample.
+    EXPECT_EQ(1, profile.sample_count());
+  }
+
+  one_byte_string_class.SetTraceAllocation(true);
+  result = Dart_Invoke(lib, NewString("foo"), 2, &args[0]);
+  EXPECT_VALID(result);
+
+  {
+    StackZone zone(isolate);
+    HANDLESCOPE(isolate);
+    Profile profile(isolate);
+    AllocationFilter filter(isolate, one_byte_string_class.id());
+    profile.Build(&filter, Profile::kNoTags);
+    // We should now have two allocation samples.
+    EXPECT_EQ(2, profile.sample_count());
+  }
+}
+
 }  // namespace dart
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index c40f71e..4cbc5dd 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -1168,7 +1168,7 @@
 static RawObject* LookupHeapObject(Isolate* isolate,
                                    const char* id_original,
                                    ObjectIdRing::LookupResult* result) {
-  char* id = isolate->current_zone()->MakeCopyOfString(id_original);
+  char* id = Thread::Current()->zone()->MakeCopyOfString(id_original);
 
   // Parse the id by splitting at each '/'.
   const int MAX_PARTS = 8;
@@ -1296,7 +1296,7 @@
       MessageSnapshotReader reader(message->data(),
                                    message->len(),
                                    isolate,
-                                   isolate->current_zone());
+                                   Thread::Current()->zone());
       const Object& msg_obj = Object::Handle(reader.ReadObject());
       msg_obj.PrintJSON(js);
       return true;
diff --git a/runtime/vm/service_test.cc b/runtime/vm/service_test.cc
index 80d6ca3..8c16909 100644
--- a/runtime/vm/service_test.cc
+++ b/runtime/vm/service_test.cc
@@ -77,14 +77,12 @@
 
 
 static RawArray* EvalF(Dart_Handle lib, const char* fmt, ...) {
-  Isolate* isolate = Isolate::Current();
-
   va_list args;
   va_start(args, fmt);
   intptr_t len = OS::VSNPrint(NULL, 0, fmt, args);
   va_end(args);
 
-  char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
+  char* buffer = Thread::Current()->zone()->Alloc<char>(len + 1);
   va_list args2;
   va_start(args2, fmt);
   OS::VSNPrint(buffer, (len + 1), fmt, args2);
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index 5bcf2ff..1d6651e 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -2075,7 +2075,7 @@
     UnmarkAll();  // Unmark objects now as we are about to print stuff.
     intptr_t len = OS::SNPrint(NULL, 0, format,
                                clazz.ToCString(), errorFunc.ToCString()) + 1;
-    char* chars = isolate()->current_zone()->Alloc<char>(len);
+    char* chars = Thread::Current()->zone()->Alloc<char>(len);
     OS::SNPrint(chars, len, format, clazz.ToCString(), errorFunc.ToCString());
     SetWriteException(Exceptions::kArgument, chars);
   }
@@ -2104,7 +2104,7 @@
     UnmarkAll();  // Unmark objects now as we are about to print stuff.
     const Class& clazz = Class::Handle(isolate(), cls);
     intptr_t len = OS::SNPrint(NULL, 0, format, clazz.ToCString()) + 1;
-    char* chars = isolate()->current_zone()->Alloc<char>(len);
+    char* chars = Thread::Current()->zone()->Alloc<char>(len);
     OS::SNPrint(chars, len, format, clazz.ToCString());
     SetWriteException(Exceptions::kArgument, chars);
   }
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 3933f3dc..b314513 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -61,7 +61,7 @@
 
 static uint8_t* zone_allocator(
     uint8_t* ptr, intptr_t old_size, intptr_t new_size) {
-  Zone* zone = Isolate::Current()->current_zone();
+  Zone* zone = Thread::Current()->zone();
   return zone->Realloc<uint8_t>(ptr, old_size, new_size);
 }
 
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index a8ceedf..bf5a05d 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -30,7 +30,7 @@
 
 const char* StackFrame::ToCString() const {
   ASSERT(isolate_ == Isolate::Current());
-  Zone* zone = Isolate::Current()->current_zone();
+  Zone* zone = Thread::Current()->zone();
   if (IsDartFrame()) {
     const Code& code = Code::Handle(LookupDartCode());
     ASSERT(!code.IsNull());
diff --git a/runtime/vm/stack_frame_test.cc b/runtime/vm/stack_frame_test.cc
index fd72877..426ede7 100644
--- a/runtime/vm/stack_frame_test.cc
+++ b/runtime/vm/stack_frame_test.cc
@@ -97,13 +97,12 @@
       }
       const char* name = function.ToFullyQualifiedCString();
       // Currently all unit tests are loaded as being part of dart:core-lib.
-      Isolate* isolate = Isolate::Current();
       String& url = String::Handle(String::New(TestCase::url()));
       const Library& lib = Library::Handle(Library::LookupLibrary(url));
       ASSERT(!lib.IsNull());
       const char* lib_name = String::Handle(lib.url()).ToCString();
       intptr_t length = OS::SNPrint(NULL, 0, "%s_%s", lib_name, expected_name);
-      char* full_name = isolate->current_zone()->Alloc<char>(length + 1);
+      char* full_name = Thread::Current()->zone()->Alloc<char>(length + 1);
       ASSERT(full_name != NULL);
       OS::SNPrint(full_name, (length + 1), "%s_%s", lib_name, expected_name);
       if (strcmp(full_name, name) != 0) {
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index 38fd623..ad51097 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -58,30 +58,18 @@
 }
 
 
-void StubCode::GenerateBootstrapStubsFor(Isolate* init) {
-  // Generate initial stubs.
-  Code& code = Code::Handle();
-  BOOTSTRAP_STUB_CODE_LIST(STUB_CODE_GENERATE);
-}
-
-
 void StubCode::GenerateStubsFor(Isolate* init) {
   // Generate all the other stubs.
   Code& code = Code::Handle();
-  REST_STUB_CODE_LIST(STUB_CODE_GENERATE);
+  STUB_CODE_LIST(STUB_CODE_GENERATE);
 }
 
 #undef STUB_CODE_GENERATE
 
 
-void StubCode::InitBootstrapStubs(Isolate* isolate) {
+void StubCode::Init(Isolate* isolate) {
   StubCode* stubs = new StubCode(isolate);
   isolate->set_stub_code(stubs);
-  stubs->GenerateBootstrapStubsFor(isolate);
-}
-
-
-void StubCode::Init(Isolate* isolate) {
   isolate->stub_code()->GenerateStubsFor(isolate);
 }
 
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index 67e022d..cf25bba 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -22,32 +22,26 @@
 #define VM_STUB_CODE_LIST(V)                                                   \
   V(GetStackPointer)                                                           \
   V(JumpToExceptionHandler)                                                    \
-
-// Is it permitted for the stubs above to refer to Object::null(), which is
-// allocated in the VM isolate and shared across all isolates.
-// However, in cases where a simple GC-safe placeholder is needed on the stack,
-// using Smi 0 instead of Object::null() is slightly more efficient, since a Smi
-// does not require relocation.
-
-// List of stubs created per isolate, these stubs could potentially contain
-// embedded objects and hence cannot be shared across isolates.
-// The initial stubs are needed for loading bootstrapping scripts and have to
-// be generated before Object::Init is called.
-#define BOOTSTRAP_STUB_CODE_LIST(V)                                            \
+  V(UpdateStoreBuffer)                                                         \
   V(PrintStopMessage)                                                          \
   V(CallToRuntime)                                                             \
   V(LazyCompile)                                                               \
-
-#define REST_STUB_CODE_LIST(V)                                                 \
   V(CallBootstrapCFunction)                                                    \
   V(CallNativeCFunction)                                                       \
   V(FixCallersTarget)                                                          \
   V(CallStaticFunction)                                                        \
+  V(OptimizeFunction)                                                          \
+  V(InvokeDartCode)                                                            \
+  V(DebugStepCheck)                                                            \
+  V(MegamorphicLookup)                                                         \
   V(FixAllocationStubTarget)                                                   \
   V(FixAllocateArrayStubTarget)                                                \
-  V(CallClosureNoSuchMethod)                                                   \
-  V(AllocateContext)                                                           \
-  V(UpdateStoreBuffer)                                                         \
+  V(Deoptimize)                                                                \
+  V(DeoptimizeLazy)                                                            \
+  V(UnoptimizedIdenticalWithNumberCheck)                                       \
+  V(OptimizedIdenticalWithNumberCheck)                                         \
+  V(ICCallBreakpoint)                                                          \
+  V(RuntimeCallBreakpoint)                                                     \
   V(OneArgCheckInlineCache)                                                    \
   V(TwoArgsCheckInlineCache)                                                   \
   V(SmiAddInlineCache)                                                         \
@@ -60,23 +54,22 @@
   V(ZeroArgsUnoptimizedStaticCall)                                             \
   V(OneArgUnoptimizedStaticCall)                                               \
   V(TwoArgsUnoptimizedStaticCall)                                              \
-  V(OptimizeFunction)                                                          \
-  V(InvokeDartCode)                                                            \
   V(Subtype1TestCache)                                                         \
   V(Subtype2TestCache)                                                         \
   V(Subtype3TestCache)                                                         \
-  V(Deoptimize)                                                                \
-  V(DeoptimizeLazy)                                                            \
-  V(ICCallBreakpoint)                                                          \
-  V(RuntimeCallBreakpoint)                                                     \
-  V(UnoptimizedIdenticalWithNumberCheck)                                       \
-  V(OptimizedIdenticalWithNumberCheck)                                         \
-  V(DebugStepCheck)                                                            \
-  V(MegamorphicLookup)                                                         \
 
+// Is it permitted for the stubs above to refer to Object::null(), which is
+// allocated in the VM isolate and shared across all isolates.
+// However, in cases where a simple GC-safe placeholder is needed on the stack,
+// using Smi 0 instead of Object::null() is slightly more efficient, since a Smi
+// does not require relocation.
+
+// List of stubs created per isolate, these stubs could potentially contain
+// embedded objects and hence cannot be shared across isolates.
 #define STUB_CODE_LIST(V)                                                      \
-  BOOTSTRAP_STUB_CODE_LIST(V)                                                  \
-  REST_STUB_CODE_LIST(V)
+  V(CallClosureNoSuchMethod)                                                   \
+  V(AllocateContext)                                                           \
+
 
 // class StubEntry is used to describe stub methods generated in dart to
 // abstract out common code executed from generated dart code.
@@ -121,9 +114,6 @@
 
   // Generate all stubs which are generated on a per isolate basis as they
   // have embedded objects which are isolate specific.
-  // Bootstrap stubs are needed before Object::Init to compile the bootstrap
-  // scripts.
-  static void InitBootstrapStubs(Isolate* isolate);
   static void Init(Isolate* isolate);
 
   static void VisitObjectPointers(ObjectPointerVisitor* visitor);
@@ -185,7 +175,6 @@
       Assembler*, Register recv, Register cache, Register target);
 
  private:
-  void GenerateBootstrapStubsFor(Isolate* isolate);
   void GenerateStubsFor(Isolate* isolate);
 
   friend class MegamorphicCacheTable;
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 0d876d3..1337934 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -51,7 +51,7 @@
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to Dart VM C++ code.
-  __ StoreToOffset(kWord, FP, R9, Isolate::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, FP, THR, Thread::top_exit_frame_info_offset());
 
 #if defined(DEBUG)
   { Label ok;
@@ -101,7 +101,7 @@
 
   // Reset exit frame information in Isolate structure.
   __ LoadImmediate(R2, 0);
-  __ StoreToOffset(kWord, R2, R9, Isolate::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, R2, THR, Thread::top_exit_frame_info_offset());
 
   __ LeaveStubFrame();
   __ Ret();
@@ -146,7 +146,7 @@
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to native code.
-  __ StoreToOffset(kWord, FP, R9, Isolate::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, FP, THR, Thread::top_exit_frame_info_offset());
 
 #if defined(DEBUG)
   { Label ok;
@@ -209,7 +209,7 @@
 
   // Reset exit frame information in Isolate structure.
   __ LoadImmediate(R2, 0);
-  __ StoreToOffset(kWord, R2, R9, Isolate::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, R2, THR, Thread::top_exit_frame_info_offset());
 
   __ LeaveStubFrame();
   __ Ret();
@@ -235,7 +235,7 @@
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to native code.
-  __ StoreToOffset(kWord, FP, R9, Isolate::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, FP, THR, Thread::top_exit_frame_info_offset());
 
 #if defined(DEBUG)
   { Label ok;
@@ -289,7 +289,7 @@
 
   // Reset exit frame information in Isolate structure.
   __ LoadImmediate(R2, 0);
-  __ StoreToOffset(kWord, R2, R9, Isolate::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, R2, THR, Thread::top_exit_frame_info_offset());
 
   __ LeaveStubFrame();
   __ Ret();
@@ -632,15 +632,20 @@
     uword* entry_patch_offset, uword* patch_code_pc_offset) {
   *entry_patch_offset = assembler->CodeSize();
   Label slow_case;
-
+  Isolate* isolate = Isolate::Current();
   // Compute the size to be allocated, it is based on the array length
   // and is computed as:
   // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
   __ MoveRegister(R3, R2);   // Array length.
-
+  const Class& cls = Class::Handle(isolate->object_store()->array_class());
+  ASSERT(!cls.IsNull());
   // Check that length is a positive Smi.
   __ tst(R3, Operand(kSmiTagMask));
-  __ b(&slow_case, NE);
+  if (FLAG_use_slow_path || cls.trace_allocation()) {
+    __ b(&slow_case);
+  } else {
+    __ b(&slow_case, NE);
+  }
   __ cmp(R3, Operand(0));
   __ b(&slow_case, LT);
 
@@ -658,7 +663,6 @@
 
   // R9: Allocation size.
 
-  Isolate* isolate = Isolate::Current();
   Heap* heap = isolate->heap();
   const intptr_t cid = kArrayCid;
   Heap::Space space = heap->SpaceForAllocation(cid);
@@ -678,7 +682,7 @@
 
   // Successfully allocated the object(s), now update top to point to
   // next object start and initialize the object.
-  __ LoadAllocationStatsAddress(R3, cid, space);
+  __ LoadAllocationStatsAddress(R3, cid);
   __ str(R7, Address(R6, 0));
   __ add(R0, R0, Operand(kHeapObjectTag));
 
@@ -795,11 +799,11 @@
 
   // Save top resource and top exit frame info. Use R4-6 as temporary registers.
   // StackFrameIterator reads the top exit frame info saved in this frame.
-  __ LoadFromOffset(kWord, R5, R9, Isolate::top_exit_frame_info_offset());
-  __ LoadFromOffset(kWord, R4, R9, Isolate::top_resource_offset());
+  __ LoadFromOffset(kWord, R5, THR, Thread::top_exit_frame_info_offset());
+  __ LoadFromOffset(kWord, R4, THR, Thread::top_resource_offset());
   __ LoadImmediate(R6, 0);
-  __ StoreToOffset(kWord, R6, R9, Isolate::top_resource_offset());
-  __ StoreToOffset(kWord, R6, R9, Isolate::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, R6, THR, Thread::top_resource_offset());
+  __ StoreToOffset(kWord, R6, THR, Thread::top_exit_frame_info_offset());
 
   // kExitLinkSlotFromEntryFp must be kept in sync with the code below.
   __ Push(R4);
@@ -842,9 +846,9 @@
   // Restore the saved top exit frame info and top resource back into the
   // Isolate structure. Uses R5 as a temporary register for this.
   __ Pop(R5);
-  __ StoreToOffset(kWord, R5, R9, Isolate::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, R5, THR, Thread::top_exit_frame_info_offset());
   __ Pop(R5);
-  __ StoreToOffset(kWord, R5, R9, Isolate::top_resource_offset());
+  __ StoreToOffset(kWord, R5, THR, Thread::top_resource_offset());
 
   // Restore the current VMTag from the stack.
   __ Pop(R4);
@@ -913,7 +917,7 @@
     // R2: object size.
     // R3: next object start.
     // R5: top address.
-    __ LoadAllocationStatsAddress(R6, cid, space);
+    __ LoadAllocationStatsAddress(R6, cid);
     __ str(R3, Address(R5, 0));
     __ add(R0, R0, Operand(kHeapObjectTag));
 
@@ -1108,7 +1112,7 @@
 
     // Load the address of the allocation stats table. We split up the load
     // and the increment so that the dependent load is not too nearby.
-    __ LoadAllocationStatsAddress(R5, cls.id(), space);
+    __ LoadAllocationStatsAddress(R5, cls.id());
 
     // R0: new object start.
     // R1: next object start.
@@ -1922,7 +1926,7 @@
   __ StoreToOffset(kWord, R2, R3, Isolate::vm_tag_offset());
   // Clear top exit frame.
   __ LoadImmediate(R2, 0);
-  __ StoreToOffset(kWord, R2, R3, Isolate::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, R2, THR, Thread::top_exit_frame_info_offset());
   __ bx(LR);  // Jump to the exception handler code.
 }
 
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index 10e2411..672a82b 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -48,11 +48,11 @@
   __ EnterStubFrame();
 
   COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << R28)) != 0);
-  __ LoadIsolate(R28, kNoPP);
+  __ LoadIsolate(R28);
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to Dart VM C++ code.
-  __ StoreToOffset(FP, R28, Isolate::top_exit_frame_info_offset(), kNoPP);
+  __ StoreToOffset(FP, THR, Thread::top_exit_frame_info_offset(), kNoPP);
 
 #if defined(DEBUG)
   { Label ok;
@@ -121,7 +121,7 @@
   __ StoreToOffset(R2, R28, Isolate::vm_tag_offset(), kNoPP);
 
   // Reset exit frame information in Isolate structure.
-  __ StoreToOffset(ZR, R28, Isolate::top_exit_frame_info_offset(), kNoPP);
+  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset(), kNoPP);
 
   __ LeaveStubFrame();
   __ ret();
@@ -148,11 +148,11 @@
   __ EnterStubFrame();
 
   COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << R28)) != 0);
-  __ LoadIsolate(R28, kNoPP);
+  __ LoadIsolate(R28);
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to native code.
-  __ StoreToOffset(FP, R28, Isolate::top_exit_frame_info_offset(), kNoPP);
+  __ StoreToOffset(FP, THR, Thread::top_exit_frame_info_offset(), kNoPP);
 
 #if defined(DEBUG)
   { Label ok;
@@ -228,7 +228,7 @@
   __ StoreToOffset(R2, R28, Isolate::vm_tag_offset(), kNoPP);
 
   // Reset exit frame information in Isolate structure.
-  __ StoreToOffset(ZR, R28, Isolate::top_exit_frame_info_offset(), kNoPP);
+  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset(), kNoPP);
 
   __ LeaveStubFrame();
   __ ret();
@@ -250,11 +250,11 @@
   __ EnterStubFrame();
 
   COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << R28)) != 0);
-  __ LoadIsolate(R28, kNoPP);
+  __ LoadIsolate(R28);
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to native code.
-  __ StoreToOffset(FP, R28, Isolate::top_exit_frame_info_offset(), kNoPP);
+  __ StoreToOffset(FP, THR, Thread::top_exit_frame_info_offset(), kNoPP);
 
 #if defined(DEBUG)
   { Label ok;
@@ -321,7 +321,7 @@
   __ StoreToOffset(R2, R28, Isolate::vm_tag_offset(), kNoPP);
 
   // Reset exit frame information in Isolate structure.
-  __ StoreToOffset(ZR, R28, Isolate::top_exit_frame_info_offset(), kNoPP);
+  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset(), kNoPP);
 
   __ LeaveStubFrame();
   __ ret();
@@ -661,12 +661,15 @@
     uword* entry_patch_offset, uword* patch_code_pc_offset) {
   *entry_patch_offset = assembler->CodeSize();
   Label slow_case;
+  Isolate* isolate = Isolate::Current();
+  const Class& cls = Class::Handle(isolate->object_store()->array_class());
+  ASSERT(!cls.IsNull());
   // Compute the size to be allocated, it is based on the array length
   // and is computed as:
   // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
   // Assert that length is a Smi.
   __ tsti(R2, Immediate(kSmiTagMask));
-  if (FLAG_use_slow_path) {
+  if (FLAG_use_slow_path || cls.trace_allocation()) {
     __ b(&slow_case);
   } else {
     __ b(&slow_case, NE);
@@ -674,7 +677,6 @@
   __ cmp(R2, Operand(0));
   __ b(&slow_case, LT);
 
-  Isolate* isolate = Isolate::Current();
   Heap* heap = isolate->heap();
   const intptr_t cid = kArrayCid;
   Heap::Space space = heap->SpaceForAllocation(cid);
@@ -839,7 +841,7 @@
     __ mov(THR, R3);
   }
   // Load Isolate pointer into temporary register R5.
-  __ LoadIsolate(R5, PP);
+  __ LoadIsolate(R5);
 
   // Save the current VMTag on the stack.
   __ LoadFromOffset(R4, R5, Isolate::vm_tag_offset(), PP);
@@ -851,11 +853,11 @@
 
   // Save top resource and top exit frame info. Use R6 as a temporary register.
   // StackFrameIterator reads the top exit frame info saved in this frame.
-  __ LoadFromOffset(R6, R5, Isolate::top_resource_offset(), PP);
-  __ StoreToOffset(ZR, R5, Isolate::top_resource_offset(), PP);
+  __ LoadFromOffset(R6, THR, Thread::top_resource_offset(), PP);
+  __ StoreToOffset(ZR, THR, Thread::top_resource_offset(), PP);
   __ Push(R6);
-  __ LoadFromOffset(R6, R5, Isolate::top_exit_frame_info_offset(), PP);
-  __ StoreToOffset(ZR, R5, Isolate::top_exit_frame_info_offset(), PP);
+  __ LoadFromOffset(R6, THR, Thread::top_exit_frame_info_offset(), PP);
+  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset(), PP);
   // kExitLinkSlotFromEntryFp must be kept in sync with the code below.
   ASSERT(kExitLinkSlotFromEntryFp == -21);
   __ Push(R6);
@@ -896,14 +898,14 @@
   // Get rid of arguments pushed on the stack.
   __ AddImmediate(SP, FP, kExitLinkSlotFromEntryFp * kWordSize, PP);
 
-  __ LoadIsolate(R28, PP);
+  __ LoadIsolate(R28);
 
   // Restore the saved top exit frame info and top resource back into the
   // Isolate structure. Uses R6 as a temporary register for this.
   __ Pop(R6);
-  __ StoreToOffset(R6, R28, Isolate::top_exit_frame_info_offset(), PP);
+  __ StoreToOffset(R6, THR, Thread::top_exit_frame_info_offset(), PP);
   __ Pop(R6);
-  __ StoreToOffset(R6, R28, Isolate::top_resource_offset(), PP);
+  __ StoreToOffset(R6, THR, Thread::top_resource_offset(), PP);
 
   // Restore the current VMTag from the stack.
   __ Pop(R4);
@@ -1431,7 +1433,7 @@
   Label stepping, done_stepping;
   if (FLAG_support_debugger && !optimized) {
     __ Comment("Check single stepping");
-    __ LoadIsolate(R6, kNoPP);
+    __ LoadIsolate(R6);
     __ LoadFromOffset(
         R6, R6, Isolate::single_step_offset(), kNoPP, kUnsignedByte);
     __ CompareRegisters(R6, ZR);
@@ -1725,7 +1727,7 @@
   // Check single stepping.
   Label stepping, done_stepping;
     if (FLAG_support_debugger) {
-    __ LoadIsolate(R6, kNoPP);
+    __ LoadIsolate(R6);
     __ LoadFromOffset(
         R6, R6, Isolate::single_step_offset(), kNoPP, kUnsignedByte);
     __ CompareImmediate(R6, 0, kNoPP);
@@ -1841,7 +1843,7 @@
     Assembler* assembler) {
   // Check single stepping.
   Label stepping, done_stepping;
-  __ LoadIsolate(R1, kNoPP);
+  __ LoadIsolate(R1);
   __ LoadFromOffset(
       R1, R1, Isolate::single_step_offset(), kNoPP, kUnsignedByte);
   __ CompareImmediate(R1, 0, kNoPP);
@@ -1989,12 +1991,12 @@
   __ mov(R0, R3);  // Exception object.
   __ mov(R1, R4);  // StackTrace object.
   __ mov(THR, R5);
-  __ LoadIsolate(R5, kNoPP);
+  __ LoadIsolate(R5);
   // Set the tag.
   __ LoadImmediate(R2, VMTag::kDartTagId, kNoPP);
   __ StoreToOffset(R2, R5, Isolate::vm_tag_offset(), kNoPP);
   // Clear top exit frame.
-  __ StoreToOffset(ZR, R5, Isolate::top_exit_frame_info_offset(), kNoPP);
+  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset(), kNoPP);
   __ ret();  // Jump to the exception handler code.
 }
 
@@ -2096,7 +2098,7 @@
   // Check single stepping.
   Label stepping, done_stepping;
   if (FLAG_support_debugger) {
-    __ LoadIsolate(R1, kNoPP);
+    __ LoadIsolate(R1);
     __ LoadFromOffset(
         R1, R1, Isolate::single_step_offset(), kNoPP, kUnsignedByte);
     __ CompareImmediate(R1, 0, kNoPP);
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index 95ba111..3addb33 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -53,7 +53,7 @@
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to Dart VM C++ code.
-  __ movl(Address(EDI, Isolate::top_exit_frame_info_offset()), EBP);
+  __ movl(Address(THR, Thread::top_exit_frame_info_offset()), EBP);
 
 #if defined(DEBUG)
   { Label ok;
@@ -91,7 +91,7 @@
           Immediate(VMTag::kDartTagId));
 
   // Reset exit frame information in Isolate structure.
-  __ movl(Address(EDI, Isolate::top_exit_frame_info_offset()), Immediate(0));
+  __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
 
   __ LeaveFrame();
   __ ret();
@@ -143,7 +143,7 @@
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to dart VM code.
-  __ movl(Address(EDI, Isolate::top_exit_frame_info_offset()), EBP);
+  __ movl(Address(THR, Thread::top_exit_frame_info_offset()), EBP);
 
 #if defined(DEBUG)
   { Label ok;
@@ -185,7 +185,7 @@
           Immediate(VMTag::kDartTagId));
 
   // Reset exit frame information in Isolate structure.
-  __ movl(Address(EDI, Isolate::top_exit_frame_info_offset()), Immediate(0));
+  __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
 
   __ LeaveFrame();
   __ ret();
@@ -216,7 +216,7 @@
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to dart VM code.
-  __ movl(Address(EDI, Isolate::top_exit_frame_info_offset()), EBP);
+  __ movl(Address(THR, Thread::top_exit_frame_info_offset()), EBP);
 
 #if defined(DEBUG)
   { Label ok;
@@ -255,7 +255,7 @@
           Immediate(VMTag::kDartTagId));
 
   // Reset exit frame information in Isolate structure.
-  __ movl(Address(EDI, Isolate::top_exit_frame_info_offset()), Immediate(0));
+  __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
 
   __ LeaveFrame();
   __ ret();
@@ -589,12 +589,16 @@
   const Immediate& raw_null =
       Immediate(reinterpret_cast<intptr_t>(Object::null()));
 
+  Isolate* isolate = Isolate::Current();
+  const Class& cls = Class::Handle(isolate->object_store()->array_class());
+  ASSERT(!cls.IsNull());
   // Compute the size to be allocated, it is based on the array length
   // and is computed as:
   // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
   // Assert that length is a Smi.
   __ testl(EDX, Immediate(kSmiTagMask));
-  if (FLAG_use_slow_path) {
+
+  if (FLAG_use_slow_path || cls.trace_allocation()) {
     __ jmp(&slow_case);
   } else {
     __ j(NOT_ZERO, &slow_case);
@@ -617,7 +621,6 @@
   // EDX: array length as Smi.
   // EDI: allocation size.
 
-  Isolate* isolate = Isolate::Current();
   Heap* heap = isolate->heap();
   const intptr_t cid = kArrayCid;
   Heap::Space space = heap->SpaceForAllocation(cid);
@@ -757,15 +760,15 @@
 
   // Save top resource and top exit frame info. Use EDX as a temporary register.
   // StackFrameIterator reads the top exit frame info saved in this frame.
-  __ movl(EDX, Address(EDI, Isolate::top_resource_offset()));
+  __ movl(EDX, Address(THR, Thread::top_resource_offset()));
   __ pushl(EDX);
-  __ movl(Address(EDI, Isolate::top_resource_offset()), Immediate(0));
+  __ movl(Address(THR, Thread::top_resource_offset()), Immediate(0));
   // The constant kExitLinkSlotFromEntryFp must be kept in sync with the
   // code below.
   ASSERT(kExitLinkSlotFromEntryFp == -6);
-  __ movl(EDX, Address(EDI, Isolate::top_exit_frame_info_offset()));
+  __ movl(EDX, Address(THR, Thread::top_exit_frame_info_offset()));
   __ pushl(EDX);
-  __ movl(Address(EDI, Isolate::top_exit_frame_info_offset()), Immediate(0));
+  __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
 
   // Load arguments descriptor array into EDX.
   __ movl(EDX, Address(EBP, kArgumentsDescOffset));
@@ -809,8 +812,8 @@
   // Restore the saved top exit frame info and top resource back into the
   // Isolate structure.
   __ LoadIsolate(EDI);
-  __ popl(Address(EDI, Isolate::top_exit_frame_info_offset()));
-  __ popl(Address(EDI, Isolate::top_resource_offset()));
+  __ popl(Address(THR, Thread::top_exit_frame_info_offset()));
+  __ popl(Address(THR, Thread::top_resource_offset()));
 
   // Restore the current VMTag from the stack.
   __ popl(Address(EDI, Isolate::vm_tag_offset()));
@@ -1344,9 +1347,8 @@
   Label stepping, done_stepping;
   if (FLAG_support_debugger && !optimized) {
     __ Comment("Check single stepping");
-    uword single_step_address = reinterpret_cast<uword>(Isolate::Current()) +
-        Isolate::single_step_offset();
-    __ cmpb(Address::Absolute(single_step_address), Immediate(0));
+    __ LoadIsolate(EAX);
+    __ cmpb(Address(EAX, Isolate::single_step_offset()), Immediate(0));
     __ j(NOT_EQUAL, &stepping);
     __ Bind(&done_stepping);
   }
@@ -1646,9 +1648,8 @@
   // Check single stepping.
   Label stepping, done_stepping;
   if (FLAG_support_debugger) {
-    uword single_step_address = reinterpret_cast<uword>(Isolate::Current()) +
-        Isolate::single_step_offset();
-    __ cmpb(Address::Absolute(single_step_address), Immediate(0));
+    __ LoadIsolate(EAX);
+    __ cmpb(Address(EAX, Isolate::single_step_offset()), Immediate(0));
     __ j(NOT_EQUAL, &stepping, Assembler::kNearJump);
     __ Bind(&done_stepping);
   }
@@ -1926,7 +1927,7 @@
   __ movl(Address(EDI, Isolate::vm_tag_offset()),
           Immediate(VMTag::kDartTagId));
   // Clear top exit frame.
-  __ movl(Address(EDI, Isolate::top_exit_frame_info_offset()), Immediate(0));
+  __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
   __ jmp(EBX);  // Jump to the exception handler code.
 }
 
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index eb53d7f..a1dd725 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -52,7 +52,7 @@
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to Dart VM C++ code.
-  __ sw(FP, Address(S6, Isolate::top_exit_frame_info_offset()));
+  __ sw(FP, Address(THR, Thread::top_exit_frame_info_offset()));
 
 #if defined(DEBUG)
   { Label ok;
@@ -107,7 +107,7 @@
   __ sw(A2, Address(S6, Isolate::vm_tag_offset()));
 
   // Reset exit frame information in Isolate structure.
-  __ sw(ZR, Address(S6, Isolate::top_exit_frame_info_offset()));
+  __ sw(ZR, Address(THR, Thread::top_exit_frame_info_offset()));
 
   __ LeaveStubFrameAndReturn();
 }
@@ -153,7 +153,7 @@
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to native code.
-  __ sw(FP, Address(S6, Isolate::top_exit_frame_info_offset()));
+  __ sw(FP, Address(THR, Thread::top_exit_frame_info_offset()));
 
 #if defined(DEBUG)
   { Label ok;
@@ -216,7 +216,7 @@
   __ sw(A2, Address(S6, Isolate::vm_tag_offset()));
 
   // Reset exit frame information in Isolate structure.
-  __ sw(ZR, Address(S6, Isolate::top_exit_frame_info_offset()));
+  __ sw(ZR, Address(THR, Thread::top_exit_frame_info_offset()));
 
   __ LeaveStubFrameAndReturn();
 }
@@ -243,7 +243,7 @@
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to native code.
-  __ sw(FP, Address(S6, Isolate::top_exit_frame_info_offset()));
+  __ sw(FP, Address(THR, Thread::top_exit_frame_info_offset()));
 
 #if defined(DEBUG)
   { Label ok;
@@ -301,7 +301,7 @@
   __ sw(A2, Address(S6, Isolate::vm_tag_offset()));
 
   // Reset exit frame information in Isolate structure.
-  __ sw(ZR, Address(S6, Isolate::top_exit_frame_info_offset()));
+  __ sw(ZR, Address(THR, Thread::top_exit_frame_info_offset()));
 
   __ LeaveStubFrameAndReturn();
 }
@@ -693,6 +693,9 @@
   __ Comment("AllocateArrayStub");
   *entry_patch_offset = assembler->CodeSize();
   Label slow_case;
+  Isolate* isolate = Isolate::Current();
+  const Class& cls = Class::Handle(isolate->object_store()->array_class());
+  ASSERT(!cls.IsNull());
 
   // Compute the size to be allocated, it is based on the array length
   // and is computed as:
@@ -701,7 +704,11 @@
 
   // Check that length is a positive Smi.
   __ andi(CMPRES1, T3, Immediate(kSmiTagMask));
-  __ bne(CMPRES1, ZR, &slow_case);
+  if (FLAG_use_slow_path || cls.trace_allocation()) {
+    __ b(&slow_case);
+  } else {
+    __ bne(CMPRES1, ZR, &slow_case);
+  }
   __ bltz(T3, &slow_case);
 
   // Check for maximum allowed length.
@@ -719,7 +726,6 @@
 
   // T2: Allocation size.
 
-  Isolate* isolate = Isolate::Current();
   Heap* heap = isolate->heap();
   const intptr_t cid = kArrayCid;
   Heap::Space space = heap->SpaceForAllocation(cid);
@@ -884,11 +890,11 @@
 
   // Save top resource and top exit frame info. Use T0 as a temporary register.
   // StackFrameIterator reads the top exit frame info saved in this frame.
-  __ lw(T0, Address(T2, Isolate::top_resource_offset()));
-  __ sw(ZR, Address(T2, Isolate::top_resource_offset()));
+  __ lw(T0, Address(THR, Thread::top_resource_offset()));
+  __ sw(ZR, Address(THR, Thread::top_resource_offset()));
   __ sw(T0, Address(SP, 1 * kWordSize));
-  __ lw(T0, Address(T2, Isolate::top_exit_frame_info_offset()));
-  __ sw(ZR, Address(T2, Isolate::top_exit_frame_info_offset()));
+  __ lw(T0, Address(THR, Thread::top_exit_frame_info_offset()));
+  __ sw(ZR, Address(THR, Thread::top_exit_frame_info_offset()));
   // kExitLinkSlotFromEntryFp must be kept in sync with the code below.
   ASSERT(kExitLinkSlotFromEntryFp == -23);
   __ sw(T0, Address(SP, 0 * kWordSize));
@@ -940,9 +946,9 @@
   // Restore the saved top resource and top exit frame info back into the
   // Isolate structure. Uses T0 as a temporary register for this.
   __ lw(T0, Address(SP, 1 * kWordSize));
-  __ sw(T0, Address(S6, Isolate::top_resource_offset()));
+  __ sw(T0, Address(THR, Thread::top_resource_offset()));
   __ lw(T0, Address(SP, 0 * kWordSize));
-  __ sw(T0, Address(S6, Isolate::top_exit_frame_info_offset()));
+  __ sw(T0, Address(THR, Thread::top_exit_frame_info_offset()));
 
   // Restore C++ ABI callee-saved registers.
   for (int i = S0; i <= S7; i++) {
@@ -2087,7 +2093,7 @@
   __ LoadImmediate(A2, VMTag::kDartTagId);
   __ sw(A2, Address(A3, Isolate::vm_tag_offset()));
   // Clear top exit frame.
-  __ sw(ZR, Address(A3, Isolate::top_exit_frame_info_offset()));
+  __ sw(ZR, Address(THR, Thread::top_exit_frame_info_offset()));
 
   __ jr(A0);  // Jump to the exception handler code.
   __ delay_slot()->mov(SP, A1);  // Stack pointer.
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index c844e1f..e50c260 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -52,7 +52,7 @@
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to Dart VM C++ code.
-  __ movq(Address(R12, Isolate::top_exit_frame_info_offset()), RBP);
+  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), RBP);
 
 #if defined(DEBUG)
   { Label ok;
@@ -94,7 +94,7 @@
           Immediate(VMTag::kDartTagId));
 
   // Reset exit frame information in Isolate structure.
-  __ movq(Address(R12, Isolate::top_exit_frame_info_offset()), Immediate(0));
+  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
 
   __ LeaveStubFrame();
   __ ret();
@@ -149,7 +149,7 @@
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to native code.
-  __ movq(Address(R12, Isolate::top_exit_frame_info_offset()), RBP);
+  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), RBP);
 
 #if defined(DEBUG)
   { Label ok;
@@ -191,7 +191,7 @@
           Immediate(VMTag::kDartTagId));
 
   // Reset exit frame information in Isolate structure.
-  __ movq(Address(R12, Isolate::top_exit_frame_info_offset()), Immediate(0));
+  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
 
   __ LeaveStubFrame();
   __ ret();
@@ -223,7 +223,7 @@
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to native code.
-  __ movq(Address(R12, Isolate::top_exit_frame_info_offset()), RBP);
+  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), RBP);
 
 #if defined(DEBUG)
   { Label ok;
@@ -263,7 +263,7 @@
           Immediate(VMTag::kDartTagId));
 
   // Reset exit frame information in Isolate structure.
-  __ movq(Address(R12, Isolate::top_exit_frame_info_offset()), Immediate(0));
+  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
 
   __ LeaveStubFrame();
   __ ret();
@@ -611,13 +611,20 @@
   __ LoadPoolPointer(new_pp);
   *entry_patch_offset = assembler->CodeSize();
   Label slow_case;
+  Isolate* isolate = Isolate::Current();
+  const Class& cls = Class::Handle(isolate->object_store()->array_class());
+  ASSERT(!cls.IsNull());
   // Compute the size to be allocated, it is based on the array length
   // and is computed as:
   // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
   __ movq(RDI, R10);  // Array Length.
   // Check that length is a positive Smi.
   __ testq(RDI, Immediate(kSmiTagMask));
-  __ j(NOT_ZERO, &slow_case);
+  if (FLAG_use_slow_path || cls.trace_allocation()) {
+    __ jmp(&slow_case);
+  } else {
+    __ j(NOT_ZERO, &slow_case);
+  }
   __ cmpq(RDI, Immediate(0));
   __ j(LESS, &slow_case);
   // Check for maximum allowed length.
@@ -630,7 +637,6 @@
   ASSERT(kSmiTagShift == 1);
   __ andq(RDI, Immediate(-kObjectAlignment));
 
-  Isolate* isolate = Isolate::Current();
   Heap* heap = isolate->heap();
   const intptr_t cid = kArrayCid;
   Heap::Space space = heap->SpaceForAllocation(cid);
@@ -787,11 +793,11 @@
 
   // Save top resource and top exit frame info. Use RAX as a temporary register.
   // StackFrameIterator reads the top exit frame info saved in this frame.
-  __ movq(RAX, Address(kIsolateReg, Isolate::top_resource_offset()));
+  __ movq(RAX, Address(THR, Thread::top_resource_offset()));
   __ pushq(RAX);
-  __ movq(Address(kIsolateReg, Isolate::top_resource_offset()),
+  __ movq(Address(THR, Thread::top_resource_offset()),
           Immediate(0));
-  __ movq(RAX, Address(kIsolateReg, Isolate::top_exit_frame_info_offset()));
+  __ movq(RAX, Address(THR, Thread::top_exit_frame_info_offset()));
   // The constant kExitLinkSlotFromEntryFp must be kept in sync with the
   // code below.
   __ pushq(RAX);
@@ -805,7 +811,7 @@
     __ Bind(&ok);
   }
 #endif
-  __ movq(Address(kIsolateReg, Isolate::top_exit_frame_info_offset()),
+  __ movq(Address(THR, Thread::top_exit_frame_info_offset()),
           Immediate(0));
 
   // Load arguments descriptor array into R10, which is passed to Dart code.
@@ -849,8 +855,8 @@
   // Restore the saved top exit frame info and top resource back into the
   // Isolate structure.
   __ LoadIsolate(kIsolateReg);
-  __ popq(Address(kIsolateReg, Isolate::top_exit_frame_info_offset()));
-  __ popq(Address(kIsolateReg, Isolate::top_resource_offset()));
+  __ popq(Address(THR, Thread::top_exit_frame_info_offset()));
+  __ popq(Address(THR, Thread::top_resource_offset()));
 
   // Restore the current VMTag from the stack.
   __ popq(Address(kIsolateReg, Isolate::vm_tag_offset()));
@@ -1985,7 +1991,7 @@
   __ movq(Address(isolate_reg, Isolate::vm_tag_offset()),
           Immediate(VMTag::kDartTagId));
   // Clear top exit frame.
-  __ movq(Address(isolate_reg, Isolate::top_exit_frame_info_offset()),
+  __ movq(Address(THR, Thread::top_exit_frame_info_offset()),
           Immediate(0));
   __ jmp(CallingConventions::kArg1Reg);  // Jump to the exception handler code.
 }
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index f9b3abf..7cafda2 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -350,7 +350,7 @@
   Utf8::Type type;
   intptr_t len = Utf8::CodeUnitCount(utf8_array, array_len, &type);
   ASSERT(len != 0);
-  Zone* zone = Isolate::Current()->current_zone();
+  Zone* zone = Thread::Current()->zone();
   if (type == Utf8::kLatin1) {
     uint8_t* characters = zone->Alloc<uint8_t>(len);
     Utf8::DecodeToLatin1(utf8_array, array_len, characters, len);
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index ee38d31..ee8a711 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -66,6 +66,7 @@
   V(NoSuchMethodError, "NoSuchMethodError")                                    \
   V(CyclicInitializationError, "CyclicInitializationError")                    \
   V(ThrowNew, "_throwNew")                                                     \
+  V(ThrowNewIfNotLoaded, "_throwNewIfNotLoaded")                               \
   V(Symbol, "Symbol")                                                          \
   V(SymbolCtor, "Symbol.")                                                     \
   V(List, "List")                                                              \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index ba6db93..a82c8b3 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -4,11 +4,15 @@
 
 #include "vm/thread.h"
 
+#include "vm/growable_array.h"
 #include "vm/isolate.h"
+#include "vm/lockers.h"
+#include "vm/object.h"
 #include "vm/os_thread.h"
 #include "vm/profiler.h"
+#include "vm/stub_code.h"
 #include "vm/thread_interrupter.h"
-
+#include "vm/thread_registry.h"
 
 namespace dart {
 
@@ -23,10 +27,21 @@
 }
 
 
-void Thread::InitOnce() {
+void Thread::InitOnceBeforeIsolate() {
   ASSERT(thread_key_ == OSThread::kUnsetThreadLocalKey);
   thread_key_ = OSThread::CreateThreadLocal(DeleteThread);
   ASSERT(thread_key_ != OSThread::kUnsetThreadLocalKey);
+  ASSERT(Thread::Current() == NULL);
+  // Postpone initialization of VM constants for this first thread.
+  SetCurrent(new Thread(false));
+}
+
+
+void Thread::InitOnceAfterObjectAndStubCode() {
+  Thread* thread = Thread::Current();
+  ASSERT(thread != NULL);
+  ASSERT(thread->isolate() == Dart::vm_isolate());
+  thread->InitVMConstants();
 }
 
 
@@ -53,6 +68,51 @@
 #endif
 
 
+Thread::Thread(bool init_vm_constants)
+    : isolate_(NULL),
+      store_buffer_block_(NULL) {
+  ClearState();
+#define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value)    \
+  member_name = default_init_value;
+CACHED_CONSTANTS_LIST(DEFAULT_INIT)
+#undef DEFAULT_INIT
+  if (init_vm_constants) {
+    InitVMConstants();
+  }
+}
+
+
+void Thread::InitVMConstants() {
+#define ASSERT_VM_HEAP(type_name, member_name, init_expr, default_init_value)  \
+  ASSERT((init_expr)->IsOldObject());
+CACHED_VM_OBJECTS_LIST(ASSERT_VM_HEAP)
+#undef ASSERT_VM_HEAP
+
+#define INIT_VALUE(type_name, member_name, init_expr, default_init_value)      \
+  ASSERT(member_name == default_init_value);                                   \
+  member_name = (init_expr);
+CACHED_CONSTANTS_LIST(INIT_VALUE)
+#undef INIT_VALUE
+}
+
+
+void Thread::Schedule(Isolate* isolate) {
+  State st;
+  if (isolate->thread_registry()->RestoreStateTo(this, &st)) {
+    ASSERT(isolate->thread_registry()->Contains(this));
+    state_ = st;
+  }
+}
+
+
+void Thread::Unschedule() {
+  ThreadRegistry* reg = isolate_->thread_registry();
+  ASSERT(reg->Contains(this));
+  reg->SaveStateFrom(this, state_);
+  ClearState();
+}
+
+
 void Thread::EnterIsolate(Isolate* isolate) {
   Thread* thread = Thread::Current();
   ASSERT(thread != NULL);
@@ -74,6 +134,7 @@
   isolate->set_vm_tag(VMTag::kVMTagId);
   ASSERT(thread->store_buffer_block_ == NULL);
   thread->store_buffer_block_ = isolate->store_buffer()->PopBlock();
+  thread->Schedule(isolate);
 }
 
 
@@ -82,6 +143,7 @@
   // TODO(koda): Audit callers; they should know whether they're in an isolate.
   if (thread == NULL || thread->isolate() == NULL) return;
   Isolate* isolate = thread->isolate();
+  thread->Unschedule();
   StoreBufferBlock* block = thread->store_buffer_block_;
   thread->store_buffer_block_ = NULL;
   isolate->store_buffer()->PushBlock(block);
@@ -106,6 +168,7 @@
   // Do not update isolate->mutator_thread, but perform sanity check:
   // this thread should not be both the main mutator and helper.
   ASSERT(isolate->mutator_thread() != thread);
+  thread->Schedule(isolate);
 }
 
 
@@ -116,6 +179,7 @@
   ASSERT(thread->store_buffer_block_ == NULL);
   Isolate* isolate = thread->isolate();
   ASSERT(isolate != NULL);
+  thread->Unschedule();
   thread->isolate_ = NULL;
   ASSERT(isolate->mutator_thread() != thread);
 }
@@ -168,4 +232,24 @@
   isolate_->cha_ = value;
 }
 
+
+bool Thread::CanLoadFromThread(const Object& object) {
+#define CHECK_OBJECT(type_name, member_name, expr, default_init_value)         \
+  if (object.raw() == expr) return true;
+CACHED_VM_OBJECTS_LIST(CHECK_OBJECT)
+#undef CHECK_OBJECT
+  return false;
+}
+
+
+intptr_t Thread::OffsetFromThread(const Object& object) {
+#define COMPUTE_OFFSET(type_name, member_name, expr, default_init_value)       \
+  ASSERT((expr)->IsVMHeapObject());                                            \
+  if (object.raw() == expr) return Thread::member_name##offset();
+CACHED_VM_OBJECTS_LIST(COMPUTE_OFFSET)
+#undef COMPUTE_OFFSET
+  UNREACHABLE();
+  return -1;
+}
+
 }  // namespace dart
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 3a8dacd..00cea34 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -5,7 +5,6 @@
 #ifndef VM_THREAD_H_
 #define VM_THREAD_H_
 
-#include "vm/base_isolate.h"
 #include "vm/globals.h"
 #include "vm/os_thread.h"
 #include "vm/store_buffer.h"
@@ -14,6 +13,26 @@
 
 class CHA;
 class Isolate;
+class Object;
+class RawBool;
+class RawObject;
+class StackResource;
+class Zone;
+
+// List of VM-global objects/addresses cached in each Thread object.
+#define CACHED_VM_OBJECTS_LIST(V)                                              \
+  V(RawObject*, object_null_, Object::null(), NULL)                            \
+  V(RawBool*, bool_true_, Object::bool_true().raw(), NULL)                     \
+  V(RawBool*, bool_false_, Object::bool_false().raw(), NULL)                   \
+
+#define CACHED_ADDRESSES_LIST(V)                                               \
+  V(uword, update_store_buffer_entry_point_,                                   \
+    StubCode::UpdateStoreBufferEntryPoint(), 0)
+
+#define CACHED_CONSTANTS_LIST(V)                                               \
+  CACHED_VM_OBJECTS_LIST(V)                                                    \
+  CACHED_ADDRESSES_LIST(V)
+
 
 // A VM thread; may be executing Dart code or performing helper tasks like
 // garbage collection or compilation. The Thread structure associated with
@@ -53,12 +72,11 @@
 #endif
 
   // Called at VM startup.
-  static void InitOnce();
+  static void InitOnceBeforeIsolate();
+  static void InitOnceAfterObjectAndStubCode();
 
   // The topmost zone used for allocation in this thread.
-  Zone* zone() {
-    return reinterpret_cast<BaseIsolate*>(isolate())->current_zone();
-  }
+  Zone* zone() const { return state_.zone; }
 
   // The isolate that this thread is operating on, or NULL if none.
   Isolate* isolate() const { return isolate_; }
@@ -83,17 +101,71 @@
     return OFFSET_OF(Thread, store_buffer_block_);
   }
 
+  uword top_exit_frame_info() const { return state_.top_exit_frame_info; }
+  static intptr_t top_exit_frame_info_offset() {
+    return OFFSET_OF(Thread, state_) + OFFSET_OF(State, top_exit_frame_info);
+  }
+
+  StackResource* top_resource() const { return state_.top_resource; }
+  void set_top_resource(StackResource* value) {
+    state_.top_resource = value;
+  }
+  static intptr_t top_resource_offset() {
+    return OFFSET_OF(Thread, state_) + OFFSET_OF(State, top_resource);
+  }
+
+  // Collection of isolate-specific state of a thread that is saved/restored
+  // on isolate exit/re-entry.
+  struct State {
+    Zone* zone;
+    uword top_exit_frame_info;
+    StackResource* top_resource;
+  };
+
+#define DEFINE_OFFSET_METHOD(type_name, member_name, expr, default_init_value) \
+  static intptr_t member_name##offset() {                                      \
+    return OFFSET_OF(Thread, member_name);                                     \
+  }
+CACHED_CONSTANTS_LIST(DEFINE_OFFSET_METHOD)
+#undef DEFINE_OFFSET_METHOD
+
+  static bool CanLoadFromThread(const Object& object);
+  static intptr_t OffsetFromThread(const Object& object);
+
  private:
   static ThreadLocalKey thread_key_;
 
   Isolate* isolate_;
+  State state_;
   StoreBufferBlock* store_buffer_block_;
+#define DECLARE_MEMBERS(type_name, member_name, expr, default_init_value)      \
+  type_name member_name;
+CACHED_CONSTANTS_LIST(DECLARE_MEMBERS)
+#undef DECLARE_MEMBERS
 
-  Thread()
-      : isolate_(NULL), store_buffer_block_(NULL) {}
+  explicit Thread(bool init_vm_constants = true);
+
+  void InitVMConstants();
+
+  void ClearState() {
+    memset(&state_, 0, sizeof(state_));
+  }
+
+  void set_zone(Zone* zone) {
+    state_.zone = zone;
+  }
+
+  void set_top_exit_frame_info(uword top_exit_frame_info) {
+    state_.top_exit_frame_info = top_exit_frame_info;
+  }
 
   static void SetCurrent(Thread* current);
 
+  void Schedule(Isolate* isolate);
+  void Unschedule();
+
+  friend class Isolate;
+  friend class StackZone;
   DISALLOW_COPY_AND_ASSIGN(Thread);
 };
 
diff --git a/runtime/vm/thread_registry.h b/runtime/vm/thread_registry.h
new file mode 100644
index 0000000..d4de8a3
--- /dev/null
+++ b/runtime/vm/thread_registry.h
@@ -0,0 +1,105 @@
+// 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 VM_THREAD_REGISTRY_H_
+#define VM_THREAD_REGISTRY_H_
+
+#include "vm/globals.h"
+#include "vm/growable_array.h"
+#include "vm/isolate.h"
+#include "vm/lockers.h"
+#include "vm/thread.h"
+
+namespace dart {
+
+// Unordered collection of threads relating to a particular isolate.
+class ThreadRegistry {
+ public:
+  ThreadRegistry() : mutex_(new Mutex()), entries_() {}
+
+  bool RestoreStateTo(Thread* thread, Thread::State* state) {
+    MutexLocker ml(mutex_);
+    Entry* entry = FindEntry(thread);
+    if (entry != NULL) {
+      Thread::State st = entry->state;
+      // TODO(koda): Support same thread re-entering same isolate with
+      // Dart frames in between. For now, just assert it doesn't happen.
+      if (st.top_exit_frame_info != thread->top_exit_frame_info()) {
+        ASSERT(thread->top_exit_frame_info() == 0 ||
+               thread->top_exit_frame_info() > st.top_exit_frame_info);
+      }
+      ASSERT(!entry->scheduled);
+      entry->scheduled = true;
+#if defined(DEBUG)
+      // State field is not in use, so zap it.
+      memset(&entry->state, 0xda, sizeof(entry->state));
+#endif
+      *state = st;
+      return true;
+    }
+    Entry new_entry;
+    new_entry.thread = thread;
+    new_entry.scheduled = true;
+#if defined(DEBUG)
+    // State field is not in use, so zap it.
+    memset(&new_entry.state, 0xda, sizeof(new_entry.state));
+#endif
+    entries_.Add(new_entry);
+    return false;
+  }
+
+  void SaveStateFrom(Thread* thread, const Thread::State& state) {
+    MutexLocker ml(mutex_);
+    Entry* entry = FindEntry(thread);
+    ASSERT(entry != NULL);
+    ASSERT(entry->scheduled);
+    entry->scheduled = false;
+    entry->state = state;
+  }
+
+  bool Contains(Thread* thread) {
+    MutexLocker ml(mutex_);
+    return (FindEntry(thread) != NULL);
+  }
+
+  void VisitObjectPointers(ObjectPointerVisitor* visitor) {
+    MutexLocker ml(mutex_);
+    for (int i = 0; i < entries_.length(); ++i) {
+      const Entry& entry = entries_[i];
+      Zone* zone = entry.scheduled ? entry.thread->zone() : entry.state.zone;
+      if (zone != NULL) {
+        zone->VisitObjectPointers(visitor);
+      }
+    }
+  }
+
+ private:
+  struct Entry {
+    Thread* thread;
+    bool scheduled;
+    Thread::State state;
+  };
+
+  // Returns Entry corresponding to thread in registry or NULL.
+  // Note: Lock should be taken before this function is called.
+  Entry* FindEntry(Thread* thread) {
+    DEBUG_ASSERT(mutex_->IsOwnedByCurrentThread());
+    for (int i = 0; i < entries_.length(); ++i) {
+      if (entries_[i].thread == thread) {
+        return &entries_[i];
+      }
+    }
+    return NULL;
+  }
+
+  Mutex* mutex_;
+  MallocGrowableArray<Entry> entries_;
+
+
+  DISALLOW_COPY_AND_ASSIGN(ThreadRegistry);
+};
+
+}  // namespace dart
+
+#endif  // VM_THREAD_REGISTRY_H_
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index 5cb270b6b..0eccd64 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -7,6 +7,8 @@
 #include "vm/lockers.h"
 #include "vm/unit_test.h"
 #include "vm/profiler.h"
+#include "vm/thread_pool.h"
+#include "vm/thread_registry.h"
 
 namespace dart {
 
@@ -82,4 +84,142 @@
   delete monitor;
 }
 
+
+class ObjectCounter : public ObjectPointerVisitor {
+ public:
+  explicit ObjectCounter(Isolate* isolate, const Object* obj)
+      : ObjectPointerVisitor(isolate), obj_(obj), count_(0) { }
+
+  virtual void VisitPointers(RawObject** first, RawObject** last) {
+    for (RawObject** current = first; current <= last; ++current) {
+      if (*current == obj_->raw()) {
+        ++count_;
+      }
+    }
+  }
+
+  intptr_t count() const { return count_; }
+
+ private:
+  const Object* obj_;
+  intptr_t count_;
+};
+
+
+class TaskWithZoneAllocation : public ThreadPool::Task {
+ public:
+  TaskWithZoneAllocation(Isolate* isolate,
+                         const String& foo,
+                         Monitor* monitor,
+                         bool* done,
+                         intptr_t id)
+      : isolate_(isolate), foo_(foo), monitor_(monitor), done_(done), id_(id) {}
+  virtual void Run() {
+    Thread::EnterIsolateAsHelper(isolate_);
+    {
+      // Create a zone (which is also a stack resource) and exercise it a bit.
+      StackZone stack_zone(Thread::Current());
+      Zone* zone = Thread::Current()->zone();
+      EXPECT_EQ(zone, stack_zone.GetZone());
+      ZoneGrowableArray<bool>* a0 = new(zone) ZoneGrowableArray<bool>(zone, 1);
+      GrowableArray<bool> a1(zone, 1);
+      for (intptr_t i = 0; i < 100000; ++i) {
+        a0->Add(true);
+        a1.Add(true);
+      }
+      // Check that we can create handles (but not yet allocate heap objects).
+      String& str = String::Handle(zone, foo_.raw());
+      EXPECT(str.Equals("foo"));
+      const intptr_t unique_smi = id_ + 928327281;
+      Smi& smi = Smi::Handle(zone, Smi::New(unique_smi));
+      EXPECT(smi.Value() == unique_smi);
+      ObjectCounter counter(isolate_, &smi);
+      // Ensure that our particular zone is visited.
+      // TODO(koda): Remove "->thread_registry()" after updating stack walker.
+      isolate_->thread_registry()->VisitObjectPointers(&counter);
+      EXPECT_EQ(1, counter.count());
+    }
+    Thread::ExitIsolateAsHelper();
+    {
+      MonitorLocker ml(monitor_);
+      *done_ = true;
+      ml.Notify();
+    }
+  }
+
+ private:
+  Isolate* isolate_;
+  const String& foo_;
+  Monitor* monitor_;
+  bool* done_;
+  intptr_t id_;
+};
+
+
+TEST_CASE(ManyTasksWithZones) {
+  const int kTaskCount = 100;
+  Monitor sync[kTaskCount];
+  bool done[kTaskCount];
+  Isolate* isolate = Thread::Current()->isolate();
+  String& foo = String::Handle(String::New("foo"));
+
+  for (int i = 0; i < kTaskCount; i++) {
+    done[i] = false;
+    Dart::thread_pool()->Run(
+        new TaskWithZoneAllocation(isolate, foo, &sync[i], &done[i], i));
+  }
+  for (int i = 0; i < kTaskCount; i++) {
+    // Check that main mutator thread can still freely use its own zone.
+    String& bar = String::Handle(String::New("bar"));
+    if (i % 10 == 0) {
+      // Mutator thread is free to independently move in/out/between isolates.
+      Thread::ExitIsolate();
+    }
+    MonitorLocker ml(&sync[i]);
+    while (!done[i]) {
+      ml.Wait();
+    }
+    EXPECT(done[i]);
+    if (i % 10 == 0) {
+      Thread::EnterIsolate(isolate);
+    }
+    EXPECT(bar.Equals("bar"));
+  }
+}
+
+
+TEST_CASE(ThreadRegistry) {
+  Isolate* orig = Thread::Current()->isolate();
+  Zone* orig_zone = Thread::Current()->zone();
+  char* orig_str = orig_zone->PrintToString("foo");
+  Thread::ExitIsolate();
+  Isolate::Flags vm_flags;
+  Dart_IsolateFlags api_flags;
+  vm_flags.CopyTo(&api_flags);
+  Isolate* isos[2];
+  // Create and enter a new isolate.
+  isos[0] = Isolate::Init(NULL, api_flags);
+  Zone* zone0 = Thread::Current()->zone();
+  EXPECT(zone0 != orig_zone);
+  isos[0]->Shutdown();
+  Thread::ExitIsolate();
+  // Create and enter yet another isolate.
+  isos[1] = Isolate::Init(NULL, api_flags);
+  {
+    // Create a stack resource this time, and exercise it.
+    StackZone stack_zone(Thread::Current());
+    Zone* zone1 = Thread::Current()->zone();
+    EXPECT(zone1 != zone0);
+    EXPECT(zone1 != orig_zone);
+  }
+  isos[1]->Shutdown();
+  Thread::ExitIsolate();
+  Thread::EnterIsolate(orig);
+  // Original zone should be preserved.
+  EXPECT_EQ(orig_zone, Thread::Current()->zone());
+  EXPECT_STREQ("foo", orig_str);
+  delete isos[0];
+  delete isos[1];
+}
+
 }  // namespace dart
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index 2fc1440..3d5e179 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -371,7 +371,7 @@
   intptr_t pid = OS::ProcessId();
   intptr_t len = OS::SNPrint(NULL, 0, format,
                              directory, pid, isolate->main_port());
-  char* filename = isolate->current_zone()->Alloc<char>(len + 1);
+  char* filename = Thread::Current()->zone()->Alloc<char>(len + 1);
   OS::SNPrint(filename, len + 1, format,
               directory, pid, isolate->main_port());
   void* file = (*file_open)(filename, true);
diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi
index 886e14c..88b8cb2 100644
--- a/runtime/vm/vm_sources.gypi
+++ b/runtime/vm/vm_sources.gypi
@@ -452,6 +452,7 @@
     'thread_pool.cc',
     'thread_pool.h',
     'thread_pool_test.cc',
+    'thread_registry.h',
     'thread_test.cc',
     'timeline.cc',
     'timeline.h',
diff --git a/runtime/vm/weak_code.cc b/runtime/vm/weak_code.cc
index fa11174..3177ba6 100644
--- a/runtime/vm/weak_code.cc
+++ b/runtime/vm/weak_code.cc
@@ -8,6 +8,7 @@
 
 #include "vm/code_generator.h"
 #include "vm/code_patcher.h"
+#include "vm/compiler.h"
 #include "vm/object.h"
 #include "vm/stack_frame.h"
 
@@ -60,6 +61,7 @@
   if (code_objects.IsNull()) {
     return;
   }
+  ASSERT(Compiler::allow_recompilation());
   UpdateArrayTo(Object::null_array());
   // Disable all code on stack.
   Code& code = Code::Handle();
diff --git a/runtime/vm/zone.cc b/runtime/vm/zone.cc
index b16c030..58fb1d1 100644
--- a/runtime/vm/zone.cc
+++ b/runtime/vm/zone.cc
@@ -215,5 +215,4 @@
   return buffer;
 }
 
-
 }  // namespace dart
diff --git a/runtime/vm/zone.h b/runtime/vm/zone.h
index 0d89c5d..ee0add5 100644
--- a/runtime/vm/zone.h
+++ b/runtime/vm/zone.h
@@ -174,27 +174,21 @@
 
 class StackZone : public StackResource {
  public:
-  // Create an empty zone and set is at the current zone for the Isolate.
-  explicit StackZone(Isolate* isolate)
-    : StackResource(isolate),
-      zone_() {
-#ifdef DEBUG
-    if (FLAG_trace_zones) {
-      OS::PrintErr("*** Starting a new Stack zone 0x%" Px "(0x%" Px ")\n",
-                   reinterpret_cast<intptr_t>(this),
-                   reinterpret_cast<intptr_t>(&zone_));
-    }
-#endif
-    BaseIsolate* base_isolate = reinterpret_cast<BaseIsolate*>(isolate);
-    zone_.Link(base_isolate->current_zone());
-    base_isolate->set_current_zone(&zone_);
+  // Create an empty zone and set is at the current zone for the Thread.
+  explicit StackZone(Thread* thread) : StackResource(thread), zone_() {
+    Initialize();
+  }
+
+  // DEPRECATED: Use Thread-based interface. During migration, this defaults
+  // to using the mutator thread (which must also be the current thread).
+  explicit StackZone(Isolate* isolate) : StackResource(isolate), zone_() {
+    Initialize();
   }
 
   // Delete all memory associated with the zone.
   ~StackZone() {
-    BaseIsolate* base_isolate = reinterpret_cast<BaseIsolate*>(isolate());
-    ASSERT(base_isolate->current_zone() == &zone_);
-    base_isolate->set_current_zone(zone_.previous_);
+    ASSERT(thread()->zone() == &zone_);
+    thread()->set_zone(zone_.previous_);
 #ifdef DEBUG
     if (FLAG_trace_zones) {
       OS::PrintErr("*** Deleting Stack zone 0x%" Px "(0x%" Px ")\n",
@@ -213,6 +207,18 @@
  private:
   Zone zone_;
 
+  void Initialize() {
+#ifdef DEBUG
+    if (FLAG_trace_zones) {
+      OS::PrintErr("*** Starting a new Stack zone 0x%" Px "(0x%" Px ")\n",
+                   reinterpret_cast<intptr_t>(this),
+                   reinterpret_cast<intptr_t>(&zone_));
+    }
+#endif
+    zone_.Link(thread()->zone());
+    thread()->set_zone(&zone_);
+  }
+
   template<typename T> friend class GrowableArray;
   template<typename T> friend class ZoneGrowableArray;
 
diff --git a/sdk/lib/_internal/js_runtime/lib/foreign_helper.dart b/sdk/lib/_internal/js_runtime/lib/foreign_helper.dart
index 5ce8113..b298e0d 100644
--- a/sdk/lib/_internal/js_runtime/lib/foreign_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/foreign_helper.dart
@@ -184,9 +184,9 @@
 external RAW_DART_FUNCTION_REF(Function function);
 
 /**
- * Sets the current isolate to [isolate].
+ * Sets the current static state to [staticState].
  */
-external void JS_SET_CURRENT_ISOLATE(isolate);
+external void JS_SET_STATIC_STATE(staticState);
 
 /**
  * Returns the interceptor for class [type].  The interceptor is the type's
@@ -197,9 +197,9 @@
 external JS_INTERCEPTOR_CONSTANT(Type type);
 
 /**
- * Returns the object corresponding to Namer.CURRENT_ISOLATE.
+ * Returns the object corresponding to Namer.staticStateHolder.
  */
-external JS_CURRENT_ISOLATE();
+external JS_GET_STATIC_STATE();
 
 /// Returns the JS name for [name] from the Namer.
 external String JS_GET_NAME(JsGetName name);
diff --git a/sdk/lib/_internal/js_runtime/lib/isolate_helper.dart b/sdk/lib/_internal/js_runtime/lib/isolate_helper.dart
index e3f13bf..5ff44bb 100644
--- a/sdk/lib/_internal/js_runtime/lib/isolate_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/isolate_helper.dart
@@ -31,9 +31,8 @@
 import 'dart:_foreign_helper' show DART_CLOSURE_TO_JS,
                                    JS,
                                    JS_CURRENT_ISOLATE_CONTEXT,
-                                   JS_CURRENT_ISOLATE,
                                    JS_EMBEDDED_GLOBAL,
-                                   JS_SET_CURRENT_ISOLATE,
+                                   JS_SET_STATIC_STATE,
                                    IsolateContext;
 
 import 'dart:_interceptors' show Interceptor,
@@ -482,7 +481,7 @@
   }
 
   void _setGlobals() {
-    JS_SET_CURRENT_ISOLATE(isolateStatics);
+    JS_SET_STATIC_STATE(isolateStatics);
   }
 
   /**
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 291e178..92ea4ba 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -44,7 +44,7 @@
     JS_BUILTIN,
     JS_CALL_IN_ISOLATE,
     JS_CONST,
-    JS_CURRENT_ISOLATE,
+    JS_GET_STATIC_STATEC,
     JS_CURRENT_ISOLATE_CONTEXT,
     JS_EFFECT,
     JS_EMBEDDED_GLOBAL,
diff --git a/sdk/lib/_internal/js_runtime/lib/js_mirrors.dart b/sdk/lib/_internal/js_runtime/lib/js_mirrors.dart
index 5815a32..e5c8495 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_mirrors.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_mirrors.dart
@@ -23,7 +23,7 @@
 import 'dart:_foreign_helper' show
     JS,
     JS_GET_FLAG,
-    JS_CURRENT_ISOLATE,
+    JS_GET_STATIC_STATE,
     JS_CURRENT_ISOLATE_CONTEXT,
     JS_EMBEDDED_GLOBAL,
     JS_GET_NAME,
@@ -447,17 +447,17 @@
     // TODO(ahe): What about lazily initialized fields? See
     // [JsClassMirror.getField].
 
-    // '$' (JS_CURRENT_ISOLATE()) stores state which is read directly, so we
+    // '$' (JS_GET_STATIC_STATE()) stores state which is read directly, so we
     // shouldn't use [_globalObject] here.
-    assert(JS('bool', '# in #', name, JS_CURRENT_ISOLATE()));
-    return JS('', '#[#]', JS_CURRENT_ISOLATE(), name);
+    assert(JS('bool', '# in #', name, JS_GET_STATIC_STATE()));
+    return JS('', '#[#]', JS_GET_STATIC_STATE(), name);
   }
 
   void _storeField(String name, Object arg) {
-    // '$' (JS_CURRENT_ISOLATE()) stores state which is stored directly, so we
+    // '$' (JS_GET_STATIC_STATE()) stores state which is stored directly, so we
     // shouldn't use [_globalObject] here.
-    assert(JS('bool', '# in #', name, JS_CURRENT_ISOLATE()));
-    JS('void', '#[#] = #', JS_CURRENT_ISOLATE(), name, arg);
+    assert(JS('bool', '# in #', name, JS_GET_STATIC_STATE()));
+    JS('void', '#[#] = #', JS_GET_STATIC_STATE(), name, arg);
   }
 
   List<JsMethodMirror> get _functionMirrors {
@@ -1859,13 +1859,13 @@
   InstanceMirror setField(Symbol fieldName, Object arg) {
     JsVariableMirror mirror = __variables[fieldName];
     if (mirror != null && mirror.isStatic && !mirror.isFinal) {
-      // '$' (JS_CURRENT_ISOLATE()) stores state which is stored directly, so
+      // '$' (JS_GET_STATIC_STATE()) stores state which is stored directly, so
       // we shouldn't use [JsLibraryMirror._globalObject] here.
       String jsName = mirror._jsName;
-      if (!JS('bool', '# in #', jsName, JS_CURRENT_ISOLATE())) {
+      if (!JS('bool', '# in #', jsName, JS_GET_STATIC_STATE())) {
         throw new RuntimeError('Cannot find "$jsName" in current isolate.');
       }
-      JS('void', '#[#] = #', JS_CURRENT_ISOLATE(), jsName, arg);
+      JS('void', '#[#] = #', JS_GET_STATIC_STATE(), jsName, arg);
       return reflect(arg);
     }
     Symbol setterName = setterSymbol(fieldName);
@@ -1890,17 +1890,17 @@
     JsVariableMirror mirror = __variables[fieldName];
     if (mirror != null && mirror.isStatic) {
       String jsName = mirror._jsName;
-      // '$' (JS_CURRENT_ISOLATE()) stores state which is read directly, so
+      // '$' (JS_GET_STATIC_STATE()) stores state which is read directly, so
       // we shouldn't use [JsLibraryMirror._globalObject] here.
-      if (!JS('bool', '# in #', jsName, JS_CURRENT_ISOLATE())) {
+      if (!JS('bool', '# in #', jsName, JS_GET_STATIC_STATE())) {
         throw new RuntimeError('Cannot find "$jsName" in current isolate.');
       }
       var lazies = JS_EMBEDDED_GLOBAL('', LAZIES);
       if (JS('bool', '# in #', jsName, lazies)) {
         String getterName = JS('String', '#[#]', lazies, jsName);
-        return reflect(JS('', '#[#]()', JS_CURRENT_ISOLATE(), getterName));
+        return reflect(JS('', '#[#]()', JS_GET_STATIC_STATE(), getterName));
       } else {
-        return reflect(JS('', '#[#]', JS_CURRENT_ISOLATE(), jsName));
+        return reflect(JS('', '#[#]', JS_GET_STATIC_STATE(), jsName));
       }
     }
     JsMethodMirror getter = __getters[fieldName];
@@ -2449,11 +2449,11 @@
         positionalArguments.add(parameter.defaultValue.reflectee);
       }
     }
-    // Using JS_CURRENT_ISOLATE() ('$') here is actually correct, although
+    // Using JS_GET_STATIC_STATE() ('$') here is actually correct, although
     // _jsFunction may not be a property of '$', most static functions do not
     // care who their receiver is. But to lazy getters, it is important that
     // 'this' is '$'.
-    return JS('', r'#.apply(#, #)', _jsFunction, JS_CURRENT_ISOLATE(),
+    return JS('', r'#.apply(#, #)', _jsFunction, JS_GET_STATIC_STATE(),
               new List.from(positionalArguments));
   }
 
diff --git a/sdk/lib/core/uri.dart b/sdk/lib/core/uri.dart
index fee73b2..5cf49b0 100644
--- a/sdk/lib/core/uri.dart
+++ b/sdk/lib/core/uri.dart
@@ -157,13 +157,12 @@
    * to `end` is parsed as a URI.
    *
    * If the string is not valid as a URI or URI reference,
-   * invalid characters will be percent escaped where possible.
-   * The resulting `Uri` will represent a valid URI or URI reference.
+   * a [FormatException] is thrown.
    */
   static Uri parse(String uri, [int start = 0, int end]) {
-    // This parsing will not validate percent-encoding, IPv6, etc. When done
-    // it will call `new Uri(...)` which will perform these validations.
-    // This is purely splitting up the URI string into components.
+    // This parsing will not validate percent-encoding, IPv6, etc.
+    // When done splitting into parts, it will call, e.g., [_makeFragment]
+    // to do the final parsing.
     //
     // Important parts of the RFC 3986 used here:
     // URI           = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
diff --git a/sdk/lib/developer/developer.dart b/sdk/lib/developer/developer.dart
index 4df565e..03c75c1 100644
--- a/sdk/lib/developer/developer.dart
+++ b/sdk/lib/developer/developer.dart
@@ -2,9 +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.
 
-/// ## Status: Unstable
+/// Interact with developer tools such as the debugger and inspector.
 ///
-/// The dart:developer library is unstable and its API might change slightly
+/// The dart:developer library is _unstable_ and its API might change slightly
 /// as a result of developer feedback. This library is platform dependent and
 /// therefore it has implementations for both dart2js and the Dart VM. Both are
 /// under development and may not support all operations yet.
@@ -15,9 +15,12 @@
 
 part 'profiler.dart';
 
-/// If [when] is true, stop the program as if a breakpoint where hit at the
-/// following statement. Returns the value of [when]. Some debuggers may
+/// If [when] is true, stop the program as if a breakpoint were hit at the
+/// following statement.
+/// 
+/// Returns the value of [when]. Some debuggers may
 /// display [msg].
+/// 
 /// NOTE: When invoked, the isolate will not return until a debugger
 /// continues execution. When running in the Dart VM the behaviour is the same
 /// regardless of whether or not a debugger is connected. When compiled to
@@ -25,6 +28,7 @@
 /// that does.
 external bool debugger({bool when: true, String msg});
 
-/// Send a reference to [object] to any attached debuggers so they may open an
-/// inspector on the object. Returns the argument.
+/// Send a reference to [object] to any attached debuggers.
+/// 
+/// Debuggers may open an inspector on the object. Returns the argument.
 external inspect(object);
diff --git a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
index 5fe0383..ee73b5f 100644
--- a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
+++ b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
@@ -1,3 +1,75 @@
+/**
+ * A client-side key-value store with support for indexes.
+ *
+ * Many browsers support IndexedDB&mdash;a web standard for
+ * an indexed database.
+ * By storing data on the client in an IndexedDB,
+ * a web app gets some advantages, such as faster performance and persistence.
+ * To find out which browsers support IndexedDB,
+ * refer to [Can I Use?](http://caniuse.com/#feat=indexeddb)
+ *
+ * In IndexedDB, each record is identified by a unique index or key,
+ * making data retrieval speedy.
+ * You can store structured data,
+ * such as images, arrays, and maps using IndexedDB.
+ * The standard does not specify size limits for individual data items
+ * or for the database itself, but browsers may impose storage limits.
+ *
+ * ## Using indexed_db
+ *
+ * The classes in this library provide an interface
+ * to the browser's IndexedDB, if it has one.
+ * To use this library in your code:
+ *
+ *     import 'dart:indexed_db';
+ *
+ * A web app can determine if the browser supports
+ * IndexedDB with [IdbFactory.supported]:
+ *
+ *     if (IdbFactory.supported)
+ *       // Use indexeddb.
+ *     else
+ *       // Find an alternative.
+ *
+ * Access to the browser's IndexedDB is provided by the app's top-level
+ * [Window] object, which your code can refer to with `window.indexedDB`.
+ * So, for example,
+ * here's how to use window.indexedDB to open a database:
+ *
+ *     Future open() {
+ *       return window.indexedDB.open('myIndexedDB',
+ *           version: 1,
+ *           onUpgradeNeeded: _initializeDatabase)
+ *         .then(_loadFromDB);
+ *     }
+ *     void _initializeDatabase(VersionChangeEvent e) {
+ *       ...
+ *     }
+ *     Future _loadFromDB(Database db) {
+ *       ...
+ *     }
+ *
+ *
+ * All data in an IndexedDB is stored within an [ObjectStore].
+ * To manipulate the database use [Transaction]s.
+ *
+ * ## Other resources
+ *
+ * Other options for client-side data storage include:
+ *
+ * * [Window.localStorage]&mdash;a
+ * basic mechanism that stores data as a [Map],
+ * and where both the keys and the values are strings.
+ *
+ * * [dart:web_sql]&mdash;a database that can be queried with SQL.
+ * 
+ * For a tutorial about using the indexed_db library with Dart,
+ * check out
+ * [Use IndexedDB](http://www.dartlang.org/docs/tutorials/indexeddb/).
+ *
+ * [IndexedDB reference](http://docs.webplatform.org/wiki/apis/indexeddb)
+ * provides wiki-style docs about indexedDB
+ */
 library dart.dom.indexed_db;
 
 import 'dart:async';
diff --git a/sdk/lib/math/math.dart b/sdk/lib/math/math.dart
index 95ed261..d167d80 100644
--- a/sdk/lib/math/math.dart
+++ b/sdk/lib/math/math.dart
@@ -220,13 +220,15 @@
 
 /**
  * Converts [x] to a double and returns the arc sine of the value.
+ * 
  * Returns a value in the range -PI..PI, or  NaN if [x] is outside
  * the range -1..1.
  */
 external double asin(num x);
 
 /**
- * Converts [x] to a dobule and returns the arc tangent of the vlaue.
+ * Converts [x] to a dobule and returns the arc tangent of the value.
+ * 
  * Returns a value in the range -PI/2..PI/2, or NaN if [x] is NaN.
  */
 external double atan(num x);
@@ -241,12 +243,14 @@
 /**
  * Converts [x] to a double and returns the natural exponent, [E],
  * to the power [x].
+ * 
  * Returns NaN if [x] is NaN.
  */
 external double exp(num x);
 
 /**
  * Converts [x] to a double and returns the natural logarithm of the value.
+ * 
  * Returns negative infinity if [x] is equal to zero.
  * Returns NaN if [x] is NaN or less than zero.
  */
diff --git a/sdk/lib/typed_data/typed_data.dart b/sdk/lib/typed_data/typed_data.dart
index 628cb2d..b04675c 100644
--- a/sdk/lib/typed_data/typed_data.dart
+++ b/sdk/lib/typed_data/typed_data.dart
@@ -10,6 +10,7 @@
 
 /**
  * A sequence of bytes underlying a typed data object.
+ * 
  * Used to process large quantities of binary or numerical data
  * more efficiently using a typed view.
  */
@@ -403,6 +404,7 @@
  * A fixed-length, random-access sequence of bytes that also provides random
  * and unaligned access to the fixed-width integers and floating point
  * numbers represented by those bytes.
+ * 
  * `ByteData` may be used to pack and unpack data from external sources
  * (such as networks or files systems), and to process large quantities
  * of numerical data more efficiently than would be possible
@@ -448,7 +450,9 @@
   /**
    * Returns the (possibly negative) integer represented by the byte at the
    * specified [byteOffset] in this object, in two's complement binary
-   * representation. The return value will be between -128 and 127, inclusive.
+   * representation.
+   * 
+   * The return value will be between -128 and 127, inclusive.
    *
    * Throws [RangeError] if [byteOffset] is negative, or
    * greater than or equal to the length of this object.
@@ -458,8 +462,9 @@
   /**
    * Sets the byte at the specified [byteOffset] in this object to the
    * two's complement binary representation of the specified [value], which
-   * must fit in a single byte. In other words, [value] must be between
-   * -128 and 127, inclusive.
+   * must fit in a single byte.
+   * 
+   * In other words, [value] must be between -128 and 127, inclusive.
    *
    * Throws [RangeError] if [byteOffset] is negative, or
    * greater than or equal to the length of this object.
@@ -468,8 +473,9 @@
 
   /**
    * Returns the positive integer represented by the byte at the specified
-   * [byteOffset] in this object, in unsigned binary form. The
-   * return value will be between 0 and 255, inclusive.
+   * [byteOffset] in this object, in unsigned binary form.
+   * 
+   * The return value will be between 0 and 255, inclusive.
    *
    * Throws [RangeError] if [byteOffset] is negative, or
    * greater than or equal to the length of this object.
@@ -479,8 +485,9 @@
   /**
    * Sets the byte at the specified [byteOffset] in this object to the
    * unsigned binary representation of the specified [value], which must fit
-   * in a single byte. in other words, [value] must be between 0 and 255,
-   * inclusive.
+   * in a single byte.
+   * 
+   * In other words, [value] must be between 0 and 255, inclusive.
    *
    * Throws [RangeError] if [byteOffset] is negative,
    * or greater than or equal to the length of this object.
@@ -491,6 +498,7 @@
    * Returns the (possibly negative) integer represented by the two bytes at
    * the specified [byteOffset] in this object, in two's complement binary
    * form.
+   * 
    * The return value will be between 2<sup>15</sup> and 2<sup>15</sup> - 1,
    * inclusive.
    *
@@ -502,7 +510,9 @@
   /**
    * Sets the two bytes starting at the specified [byteOffset] in this
    * object to the two's complement binary representation of the specified
-   * [value], which must fit in two bytes. In other words, [value] must lie
+   * [value], which must fit in two bytes.
+   * 
+   * In other words, [value] must lie
    * between 2<sup>15</sup> and 2<sup>15</sup> - 1, inclusive.
    *
    * Throws [RangeError] if [byteOffset] is negative, or
@@ -516,6 +526,7 @@
    * Returns the positive integer represented by the two bytes starting
    * at the specified [byteOffset] in this object, in unsigned binary
    * form.
+   * 
    * The return value will be between 0 and  2<sup>16</sup> - 1, inclusive.
    *
    * Throws [RangeError] if [byteOffset] is negative, or
@@ -526,7 +537,9 @@
   /**
    * Sets the two bytes starting at the specified [byteOffset] in this object
    * to the unsigned binary representation of the specified [value],
-   * which must fit in two bytes. in other words, [value] must be between
+   * which must fit in two bytes.
+   * 
+   * In other words, [value] must be between
    * 0 and 2<sup>16</sup> - 1, inclusive.
    *
    * Throws [RangeError] if [byteOffset] is negative, or
@@ -540,6 +553,7 @@
    * Returns the (possibly negative) integer represented by the four bytes at
    * the specified [byteOffset] in this object, in two's complement binary
    * form.
+   * 
    * The return value will be between 2<sup>31</sup> and 2<sup>31</sup> - 1,
    * inclusive.
    *
@@ -551,7 +565,9 @@
   /**
    * Sets the four bytes starting at the specified [byteOffset] in this
    * object to the two's complement binary representation of the specified
-   * [value], which must fit in four bytes. In other words, [value] must lie
+   * [value], which must fit in four bytes.
+   * 
+   * In other words, [value] must lie
    * between 2<sup>31</sup> and 2<sup>31</sup> - 1, inclusive.
    *
    * Throws [RangeError] if [byteOffset] is negative, or
@@ -565,6 +581,7 @@
    * Returns the positive integer represented by the four bytes starting
    * at the specified [byteOffset] in this object, in unsigned binary
    * form.
+   * 
    * The return value will be between 0 and  2<sup>32</sup> - 1, inclusive.
    *
    * Throws [RangeError] if [byteOffset] is negative, or
@@ -575,7 +592,9 @@
   /**
    * Sets the four bytes starting at the specified [byteOffset] in this object
    * to the unsigned binary representation of the specified [value],
-   * which must fit in four bytes. in other words, [value] must be between
+   * which must fit in four bytes.
+   * 
+   * In other words, [value] must be between
    * 0 and 2<sup>32</sup> - 1, inclusive.
    *
    * Throws [RangeError] if [byteOffset] is negative, or
@@ -589,6 +608,7 @@
    * Returns the (possibly negative) integer represented by the eight bytes at
    * the specified [byteOffset] in this object, in two's complement binary
    * form.
+   * 
    * The return value will be between 2<sup>63</sup> and 2<sup>63</sup> - 1,
    * inclusive.
    *
@@ -600,7 +620,9 @@
   /**
    * Sets the eight bytes starting at the specified [byteOffset] in this
    * object to the two's complement binary representation of the specified
-   * [value], which must fit in eight bytes. In other words, [value] must lie
+   * [value], which must fit in eight bytes.
+   * 
+   * In other words, [value] must lie
    * between 2<sup>63</sup> and 2<sup>63</sup> - 1, inclusive.
    *
    * Throws [RangeError] if [byteOffset] is negative, or
@@ -614,6 +636,7 @@
    * Returns the positive integer represented by the eight bytes starting
    * at the specified [byteOffset] in this object, in unsigned binary
    * form.
+   * 
    * The return value will be between 0 and  2<sup>64</sup> - 1, inclusive.
    *
    * Throws [RangeError] if [byteOffset] is negative, or
@@ -624,7 +647,9 @@
   /**
    * Sets the eight bytes starting at the specified [byteOffset] in this object
    * to the unsigned binary representation of the specified [value],
-   * which must fit in eight bytes. in other words, [value] must be between
+   * which must fit in eight bytes.
+   * 
+   * In other words, [value] must be between
    * 0 and 2<sup>64</sup> - 1, inclusive.
    *
    * Throws [RangeError] if [byteOffset] is negative, or
@@ -693,6 +718,7 @@
 
 /**
  * A fixed-length list of 8-bit signed integers.
+ * 
  * For long lists, this implementation can be considerably
  * more space- and time-efficient than the default [List] implementation.
  */
@@ -734,6 +760,7 @@
 
 /**
  * A fixed-length list of 8-bit unsigned integers.
+ * 
  * For long lists, this implementation can be considerably
  * more space- and time-efficient than the default [List] implementation.
  */
@@ -775,6 +802,7 @@
 
 /**
  * A fixed-length list of 8-bit unsigned integers.
+ * 
  * For long lists, this implementation can be considerably
  * more space- and time-efficient than the default [List] implementation.
  * Indexed store clamps the value to range 0..0xFF.
@@ -818,7 +846,9 @@
 
 /**
  * A fixed-length list of 16-bit signed integers that is viewable as a
- * [TypedData]. For long lists, this implementation can be considerably
+ * [TypedData].
+ * 
+ * For long lists, this implementation can be considerably
  * more space- and time-efficient than the default [List] implementation.
  */
 abstract class Int16List implements List<int>, TypedData {
@@ -862,7 +892,9 @@
 
 /**
  * A fixed-length list of 16-bit unsigned integers that is viewable as a
- * [TypedData]. For long lists, this implementation can be considerably
+ * [TypedData].
+ * 
+ * For long lists, this implementation can be considerably
  * more space- and time-efficient than the default [List] implementation.
  */
 abstract class Uint16List implements List<int>, TypedData {
@@ -907,7 +939,9 @@
 
 /**
  * A fixed-length list of 32-bit signed integers that is viewable as a
- * [TypedData]. For long lists, this implementation can be considerably
+ * [TypedData].
+ * 
+ * For long lists, this implementation can be considerably
  * more space- and time-efficient than the default [List] implementation.
  */
 abstract class Int32List implements List<int>, TypedData {
@@ -951,7 +985,9 @@
 
 /**
  * A fixed-length list of 32-bit unsigned integers that is viewable as a
- * [TypedData]. For long lists, this implementation can be considerably
+ * [TypedData].
+ * 
+ * For long lists, this implementation can be considerably
  * more space- and time-efficient than the default [List] implementation.
  */
 abstract class Uint32List implements List<int>, TypedData {
@@ -996,7 +1032,9 @@
 
 /**
  * A fixed-length list of 64-bit signed integers that is viewable as a
- * [TypedData]. For long lists, this implementation can be considerably
+ * [TypedData].
+ * 
+ * For long lists, this implementation can be considerably
  * more space- and time-efficient than the default [List] implementation.
  */
 abstract class Int64List implements List<int>, TypedData {
@@ -1040,7 +1078,9 @@
 
 /**
  * A fixed-length list of 64-bit unsigned integers that is viewable as a
- * [TypedData]. For long lists, this implementation can be considerably
+ * [TypedData].
+ * 
+ * For long lists, this implementation can be considerably
  * more space- and time-efficient than the default [List] implementation.
  */
 abstract class Uint64List implements List<int>, TypedData {
@@ -1085,7 +1125,9 @@
 
 /**
  * A fixed-length list of IEEE 754 single-precision binary floating-point
- * numbers  that is viewable as a [TypedData]. For long lists, this
+ * numbers  that is viewable as a [TypedData].
+ * 
+ * For long lists, this
  * implementation can be considerably more space- and time-efficient than
  * the default [List] implementation.
  */
@@ -1130,7 +1172,9 @@
 
 /**
  * A fixed-length list of IEEE 754 double-precision binary floating-point
- * numbers  that is viewable as a [TypedData]. For long lists, this
+ * numbers  that is viewable as a [TypedData].
+ * 
+ * For long lists, this
  * implementation can be considerably more space- and time-efficient than
  * the default [List] implementation.
  */
@@ -1175,7 +1219,9 @@
 
 /**
  * A fixed-length list of Float32x4 numbers that is viewable as a
- * [TypedData]. For long lists, this implementation will be considerably more
+ * [TypedData].
+ * 
+ * For long lists, this implementation will be considerably more
  * space- and time-efficient than the default [List] implementation.
  */
 abstract class Float32x4List implements List<Float32x4>, TypedData {
@@ -1219,7 +1265,9 @@
 
 /**
  * A fixed-length list of Int32x4 numbers that is viewable as a
- * [TypedData]. For long lists, this implementation will be considerably more
+ * [TypedData].
+ * 
+ * For long lists, this implementation will be considerably more
  * space- and time-efficient than the default [List] implementation.
  */
 abstract class Int32x4List implements List<Int32x4>, TypedData {
@@ -1263,7 +1311,9 @@
 
 /**
  * A fixed-length list of Float64x2 numbers that is viewable as a
- * [TypedData]. For long lists, this implementation will be considerably more
+ * [TypedData].
+ * 
+ * For long lists, this implementation will be considerably more
  * space- and time-efficient than the default [List] implementation.
  */
 abstract class Float64x2List implements List<Float64x2>, TypedData {
@@ -1307,6 +1357,7 @@
 
 /**
  * Float32x4 immutable value type and operations.
+ * 
  * Float32x4 stores 4 32-bit floating point values in "lanes".
  * The lanes are "x", "y", "z", and "w" respectively.
  */
@@ -1661,6 +1712,7 @@
 
 /**
  * Int32x4 and operations.
+ * 
  * Int32x4 stores 4 32-bit bit-masks in "lanes".
  * The lanes are "x", "y", "z", and "w" respectively.
  */
@@ -1997,6 +2049,7 @@
 
 /**
  * Float64x2 immutable value type and operations.
+ * 
  * Float64x2 stores 2 64-bit floating point values in "lanes".
  * The lanes are "x" and "y" respectively.
  */
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 97a467e..922066a 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -46,8 +46,6 @@
 Language/13_Statements/04_Local_Function_Declaration_A04_t01: MissingCompileTimeError # Issue 21050
 Language/13_Statements/04_Local_Function_Declaration_A04_t03: MissingCompileTimeError # Issue 21050
 Language/14_Libraries_and_Scripts/1_Imports_A03_t08: fail # Issue 21171
-Language/14_Libraries_and_Scripts/1_Imports_A03_t09: fail # Issue 21171
-Language/14_Libraries_and_Scripts/1_Imports_A03_t10: fail # Issue 21171
 Language/14_Libraries_and_Scripts/1_Imports_A03_t28: fail # Issue 21171
 Language/15_Types/4_Interface_Types_A11_t01: crash # Issue 21174
 Language/15_Types/4_Interface_Types_A11_t02: crash # Issue 21174
@@ -9606,296 +9604,299 @@
 Language/12_Expressions/13_Property_Extraction_A03_t01: RuntimeError # Cannot read property 'call' of undefined
 Language/12_Expressions/13_Property_Extraction_A03_t02: RuntimeError # Cannot read property 'call' of undefined
 Language/12_Expressions/13_Property_Extraction_A03_t03: RuntimeError # Cannot read property 'call' of undefined
-Language/12_Expressions/13_Spawning_an_Isolate_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+Language/12_Expressions/13_Spawning_an_Isolate_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
 Language/12_Expressions/15_Method_Invocation/4_Super_Invocation_A01_t01: RuntimeError # Cannot read property 'call' of undefined
 Language/12_Expressions/30_Identifier_Reference_A09_t03: Crash # (i=0): For-loop variable captured in loop header
 Language/13_Statements/06_For_A01_t07: Crash # unsupported operation on erroneous element
 Language/13_Statements/12_Labels_A03_t04: Crash # (switch (i){L:case 0:flag=true;break;case 2:continue L;}): continue to a labeled switch case
 Language/13_Statements/14_Continue_A02_t12: Crash # (switch (2){L:case 1:flag=true;break;case 2:continue L;}): continue to a labeled switch case
 Language/13_Statements/14_Continue_A02_t13: Crash # (switch (2){case 2:continue L;L:case 1:flag=true;}): continue to a labeled switch case
-Language/14_Libraries_and_Scripts/4_Scripts_A03_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Completer/Completer.sync_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Completer/completeError_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Completer/completeError_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Completer/completeError_A01_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Completer/completeError_A01_t04: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Completer/completeError_A03_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Completer/completeError_A03_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Completer/complete_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Completer/complete_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Completer/complete_A01_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Completer/complete_A01_t04: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Completer/complete_A01_t05: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Completer/complete_A01_t06: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Completer/complete_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Completer/complete_A02_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Completer/isCompleted_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/DeferredLibrary/DeferredLibrary_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/Future.delayed_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/Future.delayed_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/Future.delayed_A03_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/Future.error_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/Future.microtask_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/Future.microtask_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/Future.microtask_A01_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/Future.microtask_A01_t04: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/Future.sync_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/Future.sync_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/Future.sync_A01_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/Future.sync_A01_t04: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/Future.value_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/Future.value_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/Future_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/Future_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/Future_A01_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/Future_A01_t04: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/asStream_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/asStream_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/asStream_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/asStream_A02_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/catchError_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/catchError_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/catchError_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/catchError_A03_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/catchError_A03_t02: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Future/catchError_A03_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/catchError_A03_t04: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/catchError_A03_t05: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/forEach_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/forEach_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/forEach_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Future/then_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/then_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/then_A01_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/then_A01_t04: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/then_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/then_A03_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/then_A03_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/then_A04_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/then_A05_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/then_A05_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/then_A05_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/wait_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Future/wait_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Future/wait_A01_t04: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Future/wait_A01_t05: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Future/wait_A01_t06: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Future/wait_A01_t07: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Future/wait_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/wait_A02_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/whenComplete_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/whenComplete_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/whenComplete_A03_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/whenComplete_A04_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Future/whenComplete_A04_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/Stream.eventTransformed_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Stream/Stream.eventTransformed_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Stream/Stream.fromFuture_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/Stream.fromFuture_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/Stream.fromFuture_A02_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/Stream.fromIterable_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/Stream.fromIterable_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/Stream.fromIterable_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/Stream.periodic_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/Stream.periodic_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/Stream.periodic_A03_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/Stream_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/any_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/any_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/any_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/asBroadcastStream_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Stream/asBroadcastStream_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/asBroadcastStream_A01_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/asBroadcastStream_A01_t04: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/asBroadcastStream_A03_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/asBroadcastStream_A03_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/asBroadcastStream_A03_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/asBroadcastStream_A04_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/asBroadcastStream_A04_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/asBroadcastStream_A04_t03: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Stream/contains_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/contains_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/contains_A03_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/distinct_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/distinct_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/drain_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/drain_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/drain_A02_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/elementAt_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/elementAt_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/elementAt_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/elementAt_A03_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/every_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/every_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/expand_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Stream/firstWhere_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/firstWhere_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/firstWhere_A03_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/firstWhere_A03_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/first_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/first_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/first_A02_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/first_A03_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/fold_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/fold_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/forEach_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Stream/forEach_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/forEach_A02_t02: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Stream/handleError_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Stream/handleError_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Stream/handleError_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Stream/handleError_A04_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/handleError_A04_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/handleError_A04_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/isBroadcast_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/isBroadcast_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/isEmpty_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/join_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/join_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/join_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/join_A02_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/lastWhere_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/lastWhere_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/lastWhere_A03_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/lastWhere_A04_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/last_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/last_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/last_A03_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/length_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/listen_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Stream/listen_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/listen_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Stream/listen_A04_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/listen_A05_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/listen_A05_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/listen_A05_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/listen_A06_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/map_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Stream/pipe_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Stream/reduce_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/reduce_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/reduce_A01_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/singleWhere_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/singleWhere_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/single_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/single_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/skipWhile_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/skip_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/takeWhile_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/take_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/take_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/take_A01_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/toList_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Stream/toSet_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/transform_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Stream/transform_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Stream/where_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Stream/where_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/StreamController/StreamController.broadcast_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/StreamController/StreamController.broadcast_A03_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/StreamController.broadcast_A04_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/StreamController.broadcast_A05_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/StreamController.broadcast_A06_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/StreamController.broadcast_A07_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/StreamController.broadcast_A07_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/StreamController.broadcast_A08_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/StreamController_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/StreamController_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/StreamController_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/StreamController/StreamController_A04_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/StreamController_A05_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/StreamController_A06_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/StreamController_A06_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/addError_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/addError_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/addStream_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/StreamController/addStream_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/StreamController/addStream_A02_t02: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/StreamController/addStream_A03_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/StreamController/addStream_A03_t02: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/StreamController/add_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/close_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/close_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/done_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/done_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/done_A01_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/hasListener_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/hasListener_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/isClosed_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/isClosed_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/isPaused_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/isPaused_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/isPaused_A01_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/sink_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamController/stream_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamIterator/StreamIterator_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamIterator/cancel_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/StreamIterator/current_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamIterator/moveNext_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamIterator/moveNext_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamSink/addError_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamSink/addStream_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/StreamSink/addStream_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/StreamSink/addStream_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/StreamSink/addStream_A01_t04: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamSink/addStream_A01_t05: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/StreamSink/add_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/StreamSink/close_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/StreamSink/done_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/StreamTransformer/StreamTransformer.fromHandlers_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamTransformer/StreamTransformer.fromHandlers_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamTransformer/StreamTransformer.fromHandlers_A01_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamTransformer/StreamTransformer.fromHandlers_A01_t04: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/StreamTransformer/StreamTransformer_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamTransformer/StreamTransformer_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamTransformer/StreamTransformer_A01_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamTransformer/StreamTransformer_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamTransformer/StreamTransformer_A02_t02: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/StreamTransformer/StreamTransformer_A03_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/StreamTransformer/StreamTransformer_A03_t02: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/StreamTransformer/bind_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Timer/Timer.periodic_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Timer/Timer.periodic_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Timer/Timer_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Timer/Timer_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Timer/cancel_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Timer/isActive_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Timer/isActive_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Timer/run_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Timer/run_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/bindBinaryCallback_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/bindBinaryCallback_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/bindCallback_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/bindCallback_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/bindUnaryCallback_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/bindUnaryCallback_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/createPeriodicTimer_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/createTimer_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/current_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/current_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/fork_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/handleUncaughtError_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/handleUncaughtError_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/handleUncaughtError_A01_t03: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Zone/handleUncaughtError_A01_t04: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/inSameErrorZone_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/inSameErrorZone_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/inSameErrorZone_A01_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/inSameErrorZone_A01_t04: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/inSameErrorZone_A01_t05: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/operator_subscript_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/async/Zone/parent_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/registerBinaryCallback_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/registerCallback_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/registerUnaryCallback_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/runBinaryGuarded_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/runBinary_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/runGuarded_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/runUnaryGuarded_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/runUnary_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/run_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/scheduleMicrotask_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/async/Zone/scheduleMicrotask_A01_t02: RuntimeError # receiver.get$_nums is not a function
+Language/14_Libraries_and_Scripts/13_Libraries_and_Scripts_A05_t04: Crash # The null object does not have a getter 'name'.
+Language/14_Libraries_and_Scripts/4_Scripts_A03_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LayoutTests/fast/canvas/webgl/framebuffer-object-attachment_t01: Crash # The null object does not have a getter 'name'.
+LayoutTests/fast/canvas/webgl/webgl-specific_t01: Crash # The null object does not have a getter 'name'.
+LibTest/async/Completer/Completer.sync_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Completer/completeError_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Completer/completeError_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Completer/completeError_A01_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Completer/completeError_A01_t04: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Completer/completeError_A03_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Completer/completeError_A03_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Completer/complete_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Completer/complete_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Completer/complete_A01_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Completer/complete_A01_t04: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Completer/complete_A01_t05: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Completer/complete_A01_t06: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Completer/complete_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Completer/complete_A02_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Completer/isCompleted_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/DeferredLibrary/DeferredLibrary_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/Future.delayed_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/Future.delayed_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/Future.delayed_A03_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/Future.error_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/Future.microtask_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/Future.microtask_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/Future.microtask_A01_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/Future.microtask_A01_t04: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/Future.sync_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/Future.sync_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/Future.sync_A01_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/Future.sync_A01_t04: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/Future.value_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/Future.value_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/Future_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/Future_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/Future_A01_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/Future_A01_t04: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/asStream_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/asStream_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/asStream_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/asStream_A02_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/catchError_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/catchError_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/catchError_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/catchError_A03_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/catchError_A03_t02: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Future/catchError_A03_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/catchError_A03_t04: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/catchError_A03_t05: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/forEach_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/forEach_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/forEach_A03_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Future/then_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/then_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/then_A01_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/then_A01_t04: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/then_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/then_A03_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/then_A03_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/then_A04_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/then_A05_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/then_A05_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/then_A05_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/wait_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Future/wait_A01_t03: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Future/wait_A01_t04: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Future/wait_A01_t05: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Future/wait_A01_t06: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Future/wait_A01_t07: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Future/wait_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/wait_A02_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/whenComplete_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/whenComplete_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/whenComplete_A03_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/whenComplete_A04_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Future/whenComplete_A04_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/Stream.eventTransformed_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Stream/Stream.eventTransformed_A01_t02: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Stream/Stream.fromFuture_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/Stream.fromFuture_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/Stream.fromFuture_A02_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/Stream.fromIterable_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/Stream.fromIterable_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/Stream.fromIterable_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/Stream.periodic_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/Stream.periodic_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/Stream.periodic_A03_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/Stream_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/any_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/any_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/any_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/asBroadcastStream_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Stream/asBroadcastStream_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/asBroadcastStream_A01_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/asBroadcastStream_A01_t04: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/asBroadcastStream_A03_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/asBroadcastStream_A03_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/asBroadcastStream_A03_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/asBroadcastStream_A04_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/asBroadcastStream_A04_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/asBroadcastStream_A04_t03: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Stream/contains_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/contains_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/contains_A03_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/distinct_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/distinct_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/drain_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/drain_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/drain_A02_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/elementAt_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/elementAt_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/elementAt_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/elementAt_A03_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/every_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/every_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/expand_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Stream/firstWhere_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/firstWhere_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/firstWhere_A03_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/firstWhere_A03_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/first_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/first_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/first_A02_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/first_A03_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/fold_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/fold_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/forEach_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Stream/forEach_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/forEach_A02_t02: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Stream/handleError_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Stream/handleError_A02_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Stream/handleError_A03_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Stream/handleError_A04_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/handleError_A04_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/handleError_A04_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/isBroadcast_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/isBroadcast_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/isEmpty_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/join_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/join_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/join_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/join_A02_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/lastWhere_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/lastWhere_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/lastWhere_A03_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/lastWhere_A04_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/last_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/last_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/last_A03_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/length_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/listen_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Stream/listen_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/listen_A03_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Stream/listen_A04_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/listen_A05_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/listen_A05_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/listen_A05_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/listen_A06_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/map_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Stream/pipe_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Stream/reduce_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/reduce_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/reduce_A01_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/singleWhere_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/singleWhere_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/single_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/single_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/skipWhile_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/skip_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/takeWhile_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/take_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/take_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/take_A01_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/toList_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Stream/toSet_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/transform_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Stream/transform_A01_t02: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Stream/where_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Stream/where_A01_t02: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/StreamController/StreamController.broadcast_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/StreamController/StreamController.broadcast_A03_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/StreamController.broadcast_A04_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/StreamController.broadcast_A05_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/StreamController.broadcast_A06_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/StreamController.broadcast_A07_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/StreamController.broadcast_A07_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/StreamController.broadcast_A08_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/StreamController_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/StreamController_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/StreamController_A03_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/StreamController/StreamController_A04_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/StreamController_A05_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/StreamController_A06_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/StreamController_A06_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/addError_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/addError_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/addStream_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/StreamController/addStream_A02_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/StreamController/addStream_A02_t02: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/StreamController/addStream_A03_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/StreamController/addStream_A03_t02: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/StreamController/add_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/close_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/close_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/done_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/done_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/done_A01_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/hasListener_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/hasListener_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/isClosed_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/isClosed_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/isPaused_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/isPaused_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/isPaused_A01_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/sink_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamController/stream_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamIterator/StreamIterator_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamIterator/cancel_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/StreamIterator/current_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamIterator/moveNext_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamIterator/moveNext_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamSink/addError_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamSink/addStream_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/StreamSink/addStream_A01_t02: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/StreamSink/addStream_A01_t03: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/StreamSink/addStream_A01_t04: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamSink/addStream_A01_t05: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/StreamSink/add_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/StreamSink/close_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/StreamSink/done_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/StreamTransformer/StreamTransformer.fromHandlers_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamTransformer/StreamTransformer.fromHandlers_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamTransformer/StreamTransformer.fromHandlers_A01_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamTransformer/StreamTransformer.fromHandlers_A01_t04: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/StreamTransformer/StreamTransformer_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamTransformer/StreamTransformer_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamTransformer/StreamTransformer_A01_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamTransformer/StreamTransformer_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamTransformer/StreamTransformer_A02_t02: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/StreamTransformer/StreamTransformer_A03_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/StreamTransformer/StreamTransformer_A03_t02: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/StreamTransformer/bind_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Timer/Timer.periodic_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Timer/Timer.periodic_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Timer/Timer_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Timer/Timer_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Timer/cancel_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Timer/isActive_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Timer/isActive_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Timer/run_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Timer/run_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/bindBinaryCallback_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/bindBinaryCallback_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/bindCallback_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/bindCallback_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/bindUnaryCallback_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/bindUnaryCallback_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/createPeriodicTimer_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/createTimer_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/current_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/current_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/fork_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/handleUncaughtError_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/handleUncaughtError_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/handleUncaughtError_A01_t03: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Zone/handleUncaughtError_A01_t04: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/inSameErrorZone_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/inSameErrorZone_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/inSameErrorZone_A01_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/inSameErrorZone_A01_t04: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/inSameErrorZone_A01_t05: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/operator_subscript_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/async/Zone/parent_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/registerBinaryCallback_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/registerCallback_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/registerUnaryCallback_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/runBinaryGuarded_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/runBinary_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/runGuarded_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/runUnaryGuarded_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/runUnary_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/run_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/scheduleMicrotask_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/async/Zone/scheduleMicrotask_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
 LibTest/collection/ListBase/ListBase_class_A01_t02: Crash # Stack Overflow
 LibTest/collection/ListMixin/ListMixin_class_A01_t02: Crash # Stack Overflow
 LibTest/core/Invocation/isAccessor_A01_t01: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
@@ -9908,108 +9909,108 @@
 LibTest/core/Invocation/namedArguments_A01_t01: RuntimeError # Please triage this failure.
 LibTest/core/Invocation/positionalArguments_A01_t01: RuntimeError # Please triage this failure.
 LibTest/core/List/List_class_A01_t02: Crash # Stack Overflow
-LibTest/core/Stopwatch/elapsedInMs_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/core/Stopwatch/elapsedInUs_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/core/Stopwatch/elapsedTicks_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/core/Stopwatch/elapsedTicks_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/core/Stopwatch/elapsedTicks_A01_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/core/Stopwatch/elapsed_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/core/Stopwatch/elapsed_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/core/Stopwatch/elapsed_A01_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/core/Stopwatch/start_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/core/Stopwatch/start_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/core/Stopwatch/start_A01_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/core/Stopwatch/stop_A01_t01: RuntimeError # receiver.get$_nums is not a function
+LibTest/core/Stopwatch/elapsedInMs_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/core/Stopwatch/elapsedInUs_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/core/Stopwatch/elapsedTicks_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/core/Stopwatch/elapsedTicks_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/core/Stopwatch/elapsedTicks_A01_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/core/Stopwatch/elapsed_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/core/Stopwatch/elapsed_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/core/Stopwatch/elapsed_A01_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/core/Stopwatch/start_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/core/Stopwatch/start_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/core/Stopwatch/start_A01_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/core/Stopwatch/stop_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
 LibTest/core/Symbol/Symbol_A01_t03: RuntimeError # Please triage this failure.
 LibTest/core/Symbol/Symbol_A01_t05: RuntimeError # Please triage this failure.
 LibTest/core/double/INFINITY_A01_t04: Pass # Please triage this failure.
 LibTest/core/double/NEGATIVE_INFINITY_A01_t04: Pass # Please triage this failure.
-LibTest/isolate/Isolate/spawnUri_A02_t02: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/Isolate/spawnUri_A02_t03: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/Isolate/spawnUri_A02_t04: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/Isolate/spawn_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/Isolate/spawn_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/Isolate/spawn_A01_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/Isolate/spawn_A01_t04: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/Isolate/spawn_A01_t05: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/Isolate/spawn_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/RawReceivePort/RawReceivePort_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/RawReceivePort/RawReceivePort_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/RawReceivePort/close_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/RawReceivePort/handler_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/RawReceivePort/sendPort_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/ReceivePort/ReceivePort.fromRawReceivePort_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/ReceivePort/ReceivePort.fromRawReceivePort_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/ReceivePort/ReceivePort_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/ReceivePort/any_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/any_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/asBroadcastStream_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/ReceivePort/asBroadcastStream_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/asBroadcastStream_A01_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/asBroadcastStream_A01_t04: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/asBroadcastStream_A03_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/asBroadcastStream_A03_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/asBroadcastStream_A03_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/asBroadcastStream_A04_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/asBroadcastStream_A04_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/asBroadcastStream_A04_t03: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/ReceivePort/close_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/ReceivePort/close_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/ReceivePort/contains_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/distinct_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/distinct_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/drain_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/drain_A02_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/elementAt_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/elementAt_A03_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/every_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/expand_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/ReceivePort/firstWhere_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/firstWhere_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/firstWhere_A03_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/first_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/first_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/first_A02_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/fold_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/fold_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/forEach_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/ReceivePort/isBroadcast_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/isBroadcast_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/isEmpty_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/join_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/join_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/lastWhere_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/lastWhere_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/lastWhere_A04_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/last_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/last_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/length_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/listen_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/ReceivePort/map_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/ReceivePort/pipe_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/ReceivePort/reduce_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/reduce_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/reduce_A01_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/singleWhere_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/singleWhere_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/single_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/single_A02_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/skipWhile_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/skip_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/ReceivePort/takeWhile_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/take_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/ReceivePort/take_A01_t02: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/take_A01_t03: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/toList_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/ReceivePort/toSet_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/transform_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/ReceivePort/transform_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/ReceivePort/where_A01_t01: RuntimeError # receiver.get$_nums is not a function
-LibTest/isolate/ReceivePort/where_A01_t02: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/SendPort/hashCode_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/SendPort/operator_equality_A01_t01: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/SendPort/send_A01_t04: RuntimeError # receiver.get$_collection$_nums is not a function
-LibTest/isolate/SendPort/send_A02_t01: RuntimeError # receiver.get$_collection$_nums is not a function
+LibTest/isolate/Isolate/spawnUri_A02_t02: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/Isolate/spawnUri_A02_t03: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/Isolate/spawnUri_A02_t04: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/Isolate/spawn_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/Isolate/spawn_A01_t02: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/Isolate/spawn_A01_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/Isolate/spawn_A01_t04: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/Isolate/spawn_A01_t05: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/Isolate/spawn_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/RawReceivePort/RawReceivePort_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/RawReceivePort/RawReceivePort_A01_t02: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/RawReceivePort/close_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/RawReceivePort/handler_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/RawReceivePort/sendPort_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/ReceivePort.fromRawReceivePort_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/ReceivePort.fromRawReceivePort_A02_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/ReceivePort_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/any_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/any_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/asBroadcastStream_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/asBroadcastStream_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/asBroadcastStream_A01_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/asBroadcastStream_A01_t04: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/asBroadcastStream_A03_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/asBroadcastStream_A03_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/asBroadcastStream_A03_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/asBroadcastStream_A04_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/asBroadcastStream_A04_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/asBroadcastStream_A04_t03: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/close_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/close_A02_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/contains_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/distinct_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/distinct_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/drain_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/drain_A02_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/elementAt_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/elementAt_A03_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/every_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/expand_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/firstWhere_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/firstWhere_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/firstWhere_A03_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/first_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/first_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/first_A02_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/fold_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/fold_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/forEach_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/isBroadcast_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/isBroadcast_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/isEmpty_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/join_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/join_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/lastWhere_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/lastWhere_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/lastWhere_A04_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/last_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/last_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/length_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/listen_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/map_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/pipe_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/reduce_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/reduce_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/reduce_A01_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/singleWhere_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/singleWhere_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/single_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/single_A02_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/skipWhile_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/skip_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/takeWhile_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/take_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/take_A01_t02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/take_A01_t03: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/toList_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/toSet_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/transform_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/transform_A01_t02: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/where_A01_t01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+LibTest/isolate/ReceivePort/where_A01_t02: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/SendPort/hashCode_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/SendPort/operator_equality_A01_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/SendPort/send_A01_t04: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+LibTest/isolate/SendPort/send_A02_t01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
 LibTest/typed_data/Float32List/setAll_A01_t01: RuntimeError # this.get$length is not a function
 LibTest/typed_data/Float32List/setRange_A01_t01: RuntimeError # this.get$length is not a function
 LibTest/typed_data/Float32List/setRange_A02_t01: RuntimeError # this.get$length is not a function
diff --git a/tests/compiler/dart2js/backend_dart/sexpr_unstringifier.dart b/tests/compiler/dart2js/backend_dart/sexpr_unstringifier.dart
index 809aa99..8b7b7cd 100644
--- a/tests/compiler/dart2js/backend_dart/sexpr_unstringifier.dart
+++ b/tests/compiler/dart2js/backend_dart/sexpr_unstringifier.dart
@@ -150,6 +150,9 @@
   static const String GET_STATIC = "GetStatic";
   static const String TYPE_TEST = "TypeTest";
   static const String APPLY_BUILTIN_OPERATOR = "ApplyBuiltinOperator";
+  static const String GET_LENGTH = "GetLength";
+  static const String GET_INDEX = "GetIndex";
+  static const String SET_INDEX = "SetIndex";
 
   // Other
   static const String FUNCTION_DEFINITION = "FunctionDefinition";
@@ -610,6 +613,33 @@
     return new ApplyBuiltinOperator(operator, arguments);
   }
 
+  /// (GetLength object)
+  GetLength parseGetLength() {
+    tokens.consumeStart(GET_LENGTH);
+    Primitive object = name2variable[tokens.read()];
+    tokens.consumeEnd();
+    return new GetLength(object);
+  }
+
+  /// (GetIndex object index)
+  GetIndex parseGetIndex() {
+    tokens.consumeStart(GET_INDEX);
+    Primitive object = name2variable[tokens.read()];
+    Primitive index = name2variable[tokens.read()];
+    tokens.consumeEnd();
+    return new GetIndex(object, index);
+  }
+
+  /// (SetIndex object index value)
+  SetIndex parseSetIndex() {
+    tokens.consumeStart(SET_INDEX);
+    Primitive object = name2variable[tokens.read()];
+    Primitive index = name2variable[tokens.read()];
+    Primitive value = name2variable[tokens.read()];
+    tokens.consumeEnd();
+    return new SetIndex(object, index, value);
+  }
+
   /// (SetStatic field value body)
   SetStatic parseSetStatic() {
     tokens.consumeStart(SET_STATIC);
@@ -684,6 +714,12 @@
         return parseTypeTest();
       case APPLY_BUILTIN_OPERATOR:
         return parseApplyBuiltinOperator();
+      case GET_LENGTH:
+        return parseGetLength();
+      case GET_INDEX:
+        return parseGetIndex();
+      case SET_INDEX:
+        return parseSetIndex();
       default:
         assert(false);
     }
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index 82511ce..096a7bc 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -45,6 +45,7 @@
 # These tests run the compiler multiple times.
 js_backend_cps_ir_basic_test: Pass, Slow
 js_backend_cps_ir_closures_test: Pass, Slow
+js_backend_cps_ir_constructor_test: Pass, Slow
 
 [ $unchecked ]
 exit_code_test: Skip # This tests requires checked mode.
diff --git a/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart b/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
index 1927db0..a3624f0 100644
--- a/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
+++ b/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
@@ -61,7 +61,6 @@
     var lib4 = lookupLibrary("memory:lib4.dart");
     var bar1 = lib4.find("bar1");
     var bar2 = lib4.find("bar2");
-    var outputClassLists = backend.emitter.outputClassLists;
 
     OutputUnit ou_lib1 = outputUnitForElement(foo1);
     OutputUnit ou_lib2 = outputUnitForElement(foo2);
diff --git a/tests/compiler/dart2js/deferred_not_in_main_test.dart b/tests/compiler/dart2js/deferred_not_in_main_test.dart
index 9999881..a4b8435 100644
--- a/tests/compiler/dart2js/deferred_not_in_main_test.dart
+++ b/tests/compiler/dart2js/deferred_not_in_main_test.dart
@@ -51,8 +51,6 @@
     var foo1 = lib1.find("foo1");
     var foo2 = lib2.find("foo2");
 
-    var outputClassLists = backend.emitter.outputClassLists;
-
     Expect.notEquals(mainOutputUnit, outputUnitForElement(foo2));
   }));
 }
diff --git a/tests/compiler/dart2js/diagnose_ambiguous_test.dart b/tests/compiler/dart2js/diagnose_ambiguous_test.dart
index c6b3061..d70c8e4 100644
--- a/tests/compiler/dart2js/diagnose_ambiguous_test.dart
+++ b/tests/compiler/dart2js/diagnose_ambiguous_test.dart
@@ -29,7 +29,7 @@
                                    diagnosticHandler,
                                    libraryRoot,
                                    packageRoot,
-                                   ['--analyze-only'],
+                                   ['--analyze-all'],
                                    {});
   asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
     diagnostics.sort();
@@ -38,10 +38,10 @@
         "memory:library.dart:41:45:'hest' is defined here.:info",
         "memory:main.dart:0:22:'hest' is imported here.:info",
         "memory:main.dart:23:46:'hest' is imported here.:info",
-        "memory:main.dart:86:92:Duplicate import of 'hest'.:error"
+        "memory:main.dart:86:92:Duplicate import of 'hest'.:warning",
     ];
     Expect.listEquals(expected, diagnostics);
-    Expect.isTrue(compiler.compilationFailed);
+    Expect.isFalse(compiler.compilationFailed);
   }));
 }
 
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_control_flow_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_control_flow_test.dart
index b16a1a8..adf8db7 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_control_flow_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_control_flow_test.dart
@@ -57,13 +57,12 @@
 }""", """
 function() {
   var i = 0;
-  L2:
-    while (P.identical(V.foo(true), true)) {
-      P.print(1);
-      if (P.identical(V.foo(false), true))
-        break L2;
-      i = V.foo(i);
-    }
+  while (P.identical(V.foo(true), true)) {
+    P.print(1);
+    if (P.identical(V.foo(false), true))
+      break;
+    i = V.foo(i);
+  }
   P.print(2);
 }"""),
 const TestEntry("""
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_interceptors_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_interceptors_test.dart
index 60f9717..374b751 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_interceptors_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_interceptors_test.dart
@@ -34,9 +34,11 @@
 r"""
 function() {
   var l = ["hest", ["h", "e", "s", "t"]], i = 0, x, j;
-  P.print(J.getInterceptor$as(l).get$length(l));
-  while (i < J.getInterceptor$as(l).get$length(l)) {
-    x = J.getInterceptor$as(l).$index(l, i);
+  P.print(l.length);
+  while (i < l.length) {
+    if (i < 0 || i >= l.length)
+      H.ioore(l, i);
+    x = l[i];
     j = 0;
     while (j < J.getInterceptor$as(x).get$length(x)) {
       P.print(J.getInterceptor$as(x).$index(x, j));
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart
index 577dca0..138e684 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart
@@ -14,17 +14,16 @@
 foo() => foo();
 main() {
   print(foo() ? "hello world" : "bad bad");
-}""",
-"""function() {
-  V.foo();
-  P.print("bad bad");
+}""","""
+function() {
+  P.print(V.foo() ? "hello world" : "bad bad");
 }"""),
   const TestEntry("""
 foo() => null;
 main() {
   print(foo() ? "hello world" : "bad bad");
-}""",
-"""function() {
+}""","""
+function() {
   V.foo();
   P.print("bad bad");
 }"""),
@@ -32,25 +31,23 @@
 get foo => foo;
 main() {
   print(foo ? "hello world" : "bad bad");
-}""",
-"""function() {
-  V.foo();
-  P.print("bad bad");
+}""","""
+function() {
+  P.print(V.foo() ? "hello world" : "bad bad");
 }"""),
   const TestEntry("""
 get foo => foo;
-main() { print(foo && foo); }""",
-"""function() {
-  V.foo();
-  P.print(false);
+main() { print(foo && foo); }
+""", """
+function() {
+  P.print(V.foo() ? !!P.identical(V.foo(), true) : false);
 }"""),
   const TestEntry("""
 get foo => foo;
-main() { print(foo || foo); }""",
-"""function() {
-  V.foo();
-  V.foo();
-  P.print(false);
+main() { print(foo || foo); }
+""","""
+function() {
+  P.print(V.foo() ? true : !!P.identical(V.foo(), true));
 }"""),
 
 // Needs interceptor calling convention
@@ -76,8 +73,10 @@
   print(list);
 }""", r"""
 function() {
-  var list = [1, 2, 3];
-  J.getInterceptor$a(list).$indexSet(list, 1, 6);
+  var list = [1, 2, 3], v0 = 1;
+  if (v0 < 0 || v0 >= list.length)
+    H.ioore(list, v0);
+  list[v0] = 6;
   P.print(list);
 }"""),
 ];
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_supercall_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_supercall_test.dart
index 332af73..7d9283e 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_supercall_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_supercall_test.dart
@@ -53,7 +53,7 @@
 
 const TestEntry.forMethod('function(Sub#m)', """
 class Base {
-  var field;
+  var field = 123;
 }
 class Sub extends Base {
   m(x) => x + super.field;
@@ -63,7 +63,7 @@
 }""",
 r"""
 function(x) {
-  return J.getInterceptor$ns(x).$add(x, this.field);
+  return x + this.field;
 }"""),
 
 
diff --git a/tests/compiler/dart2js/mirrors_used_test.dart b/tests/compiler/dart2js/mirrors_used_test.dart
index 3b2bb39..e79df96 100644
--- a/tests/compiler/dart2js/mirrors_used_test.dart
+++ b/tests/compiler/dart2js/mirrors_used_test.dart
@@ -26,6 +26,9 @@
 import 'package:compiler/src/js_backend/js_backend.dart' show
     JavaScriptBackend;
 
+import 'package:compiler/src/js_emitter/full_emitter/emitter.dart'
+    as full show Emitter;
+
 void expectOnlyVerboseInfo(Uri uri, int begin, int end, String message, kind) {
   if (kind.name == 'verbose info') {
     print(message);
@@ -89,10 +92,13 @@
     expectedNames = expectedNames.map(backend.namer.asName).toList();
     expectedNames.addAll(nativeNames);
 
+    // Mirrors only work in the full emitter. We can thus be certain that the
+    // emitter is the full emitter.
+    full.Emitter fullEmitter = backend.emitter.emitter;
     Set recordedNames = new Set()
-        ..addAll(backend.emitter.oldEmitter.recordedMangledNames)
-        ..addAll(backend.emitter.oldEmitter.mangledFieldNames.keys)
-        ..addAll(backend.emitter.oldEmitter.mangledGlobalFieldNames.keys);
+        ..addAll(fullEmitter.recordedMangledNames)
+        ..addAll(fullEmitter.mangledFieldNames.keys)
+        ..addAll(fullEmitter.mangledGlobalFieldNames.keys);
     Expect.setEquals(new Set.from(expectedNames), recordedNames);
 
     for (var library in compiler.libraryLoader.libraries) {
diff --git a/tests/compiler/dart2js/parser_helper.dart b/tests/compiler/dart2js/parser_helper.dart
index acd2c030..ad7550c 100644
--- a/tests/compiler/dart2js/parser_helper.dart
+++ b/tests/compiler/dart2js/parser_helper.dart
@@ -65,7 +65,7 @@
 }
 
 Token scan(String text) =>
-    new StringScanner.fromString(text, enableNullAwareOperators: true)
+    new StringScanner.fromString(text)
     .tokenize();
 
 Node parseBodyCode(String text, Function parseMethod,
diff --git a/tests/compiler/dart2js/semantic_visitor_test_send_data.dart b/tests/compiler/dart2js/semantic_visitor_test_send_data.dart
index 514aa2a..7ffca23 100644
--- a/tests/compiler/dart2js/semantic_visitor_test_send_data.dart
+++ b/tests/compiler/dart2js/semantic_visitor_test_send_data.dart
@@ -749,7 +749,6 @@
         ''',
         const Visit(VisitKind.VISIT_TOP_LEVEL_GETTER_GET,
                     element: 'getter(o)')),
-    // TODO(johnniwinther): Expect [VISIT_TOP_LEVEL_SETTER_GET] instead.
     const Test(
         '''
         set o(_) {}
@@ -764,8 +763,8 @@
         '''
         m() => p.o;
         ''',
-        const Visit(VisitKind.VISIT_UNRESOLVED_GET,
-                    name: 'o')),
+        const Visit(VisitKind.VISIT_TOP_LEVEL_SETTER_GET,
+                    element: 'setter(o)')),
     // TODO(johnniwinther): Expect [VISIT_TOP_LEVEL_GETTER_SET] instead.
     const Test(
         '''
@@ -815,7 +814,6 @@
         const Visit(VisitKind.VISIT_TOP_LEVEL_GETTER_INVOKE,
                     element: 'getter(o)',
                     arguments: '(null,42)')),
-    // TODO(johnniwinther): Expected [VISIT_TOP_LEVEL_SETTER_INVOKE] instead.
     const Test(
         '''
         set o(_) {}
@@ -829,8 +827,8 @@
         set o(_) {}
         ''',
         'm() { p.o(null, 42); }',
-        const Visit(VisitKind.VISIT_UNRESOLVED_INVOKE,
-                    name: 'o',
+        const Visit(VisitKind.VISIT_TOP_LEVEL_SETTER_INVOKE,
+                    element: 'setter(o)',
                     arguments: '(null,42)')),
   ],
   'Top level functions': const [
diff --git a/tests/compiler/dart2js/source_mapping_test.dart b/tests/compiler/dart2js/source_mapping_test.dart
index a54caac..9c350f6 100644
--- a/tests/compiler/dart2js/source_mapping_test.dart
+++ b/tests/compiler/dart2js/source_mapping_test.dart
@@ -10,6 +10,9 @@
 import 'package:compiler/src/io/source_information.dart';
 import "mock_compiler.dart";
 import 'package:compiler/src/js_backend/js_backend.dart';
+import 'package:compiler/src/js_emitter/js_emitter.dart';
+import 'package:compiler/src/js_emitter/full_emitter/emitter.dart'
+    as full show Emitter;
 
 Future<CodeBuffer> compileAll(SourceFile sourceFile) {
   MockCompiler compiler = new MockCompiler.internal();
@@ -17,7 +20,10 @@
   compiler.sourceFiles[uri.toString()] = sourceFile;
   JavaScriptBackend backend = compiler.backend;
   return compiler.runCompiler(uri).then((_) {
-    return backend.emitter.oldEmitter
+    // TODO(floitsch): the outputBuffers are only accessible in the full
+    // emitter.
+    full.Emitter fullEmitter = backend.emitter.emitter;
+    return fullEmitter
         .outputBuffers[compiler.deferredLoadTask.mainOutputUnit];
   });
 }
diff --git a/tests/compiler/dart2js/sourcemaps/invokes_test_file.dart b/tests/compiler/dart2js/sourcemaps/invokes_test_file.dart
index 9c06550..83a5ef3 100644
--- a/tests/compiler/dart2js/sourcemaps/invokes_test_file.dart
+++ b/tests/compiler/dart2js/sourcemaps/invokes_test_file.dart
@@ -36,6 +36,7 @@
   parameter();
   localVariable();
   localFunction();
+  (parameter)();
 
   parameter.dynamicInvoke();
   new C(parameter).instanceInvokes();
diff --git a/tests/compiler/dart2js/sourcemaps/source_mapping_test.dart b/tests/compiler/dart2js/sourcemaps/source_mapping_test.dart
index 831299f..551bf40 100644
--- a/tests/compiler/dart2js/sourcemaps/source_mapping_test.dart
+++ b/tests/compiler/dart2js/sourcemaps/source_mapping_test.dart
@@ -2,6 +2,7 @@
 // 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 'dart:async';
 import 'package:async_helper/async_helper.dart';
 import 'package:expect/expect.dart';
 import 'sourcemap_helper.dart';
@@ -10,42 +11,134 @@
 
 main(List<String> arguments) {
   bool showAll = false;
+  bool measure = false;
   Uri outputUri;
-  if (arguments.isNotEmpty) {
-    outputUri = Uri.base.resolve(nativeToUriPath(arguments.last));
-    showAll = arguments.contains('-a');
+  Set<String> configurations = new Set<String>();
+  for (String argument in arguments) {
+    if (argument.startsWith('-')) {
+      if (argument == '-a') {
+        /// Generate visualization for all user methods.
+        showAll = true;
+      } else if (argument == '-m') {
+        /// Measure instead of reporting the number of missing code points.
+        measure = true;
+      } else if (argument.startsWith('--out=')) {
+        /// Generate visualization for the first configuration.
+        outputUri = Uri.base.resolve(
+            nativeToUriPath(argument.substring('--out='.length)));
+      } else if (argument.startsWith('-o')) {
+        /// Generate visualization for the first configuration.
+        outputUri = Uri.base.resolve(
+            nativeToUriPath(argument.substring('-o'.length)));
+      } else {
+        print("Unknown option '$argument'.");
+        return;
+      }
+    } else {
+      if (TEST_CONFIGURATIONS.containsKey(argument)) {
+        configurations.add(argument);
+      } else {
+        print("Unknown configuration '$argument'. "
+              "Must be one of '${TEST_CONFIGURATIONS.keys.join("', '")}'");
+        return;
+      }
+    }
   }
+
+  if (configurations.isEmpty) {
+    configurations.addAll(TEST_CONFIGURATIONS.keys);
+  }
+  String outputConfig = configurations.first;
+
   asyncTest(() async {
-    String filename =
-        'tests/compiler/dart2js/sourcemaps/invokes_test_file.dart';
-    SourceMapProcessor processor = new SourceMapProcessor(filename);
-    List<SourceMapInfo> infoList = await processor.process(
-        ['--use-new-source-info', '--csp', '--disable-inlining']);
-    List<SourceMapInfo> userInfoList = <SourceMapInfo>[];
-    List<SourceMapInfo> failureList = <SourceMapInfo>[];
-    for (SourceMapInfo info in infoList) {
-      if (info.element.library.isPlatformLibrary) continue;
-      userInfoList.add(info);
-      Iterable<CodePoint> missingCodePoints =
-          info.codePoints.where((c) => c.isMissing);
+    List<Measurement> measurements = <Measurement>[];
+    for (String config in configurations) {
+      List<String> options = TEST_CONFIGURATIONS[config];
+      Measurement measurement = await runTests(
+          config,
+          options,
+          showAll: showAll,
+          measure: measure,
+          outputUri: outputConfig == config ? outputUri : null);
+      if (measurement != null) {
+        measurements.add(measurement);
+      }
+    }
+    for (Measurement measurement in measurements) {
+      print(measurement);
+    }
+  });
+}
+
+const Map<String, List<String>> TEST_CONFIGURATIONS = const {
+  'old': const [],
+  'ssa': const ['--use-new-source-info', ],
+  'cps': const ['--use-new-source-info', '--use-cps-ir'],
+};
+
+Future<Measurement> runTests(
+    String config,
+    List<String> options,
+    {bool showAll: false,
+     Uri outputUri,
+     bool measure: false}) async {
+  if (config == 'old' && !measure) return null;
+
+  String filename =
+      'tests/compiler/dart2js/sourcemaps/invokes_test_file.dart';
+  SourceMapProcessor processor = new SourceMapProcessor(filename);
+  List<SourceMapInfo> infoList = await processor.process(
+      ['--csp', '--disable-inlining']
+      ..addAll(options),
+      verbose: !measure);
+  List<SourceMapInfo> userInfoList = <SourceMapInfo>[];
+  List<SourceMapInfo> failureList = <SourceMapInfo>[];
+  Measurement measurement = new Measurement(config);
+  for (SourceMapInfo info in infoList) {
+    if (info.element.library.isPlatformLibrary) continue;
+    userInfoList.add(info);
+    Iterable<CodePoint> missingCodePoints =
+        info.codePoints.where((c) => c.isMissing);
+    measurement.missing += missingCodePoints.length;
+    measurement.count += info.codePoints.length;
+    if (!measure) {
       if (!missingCodePoints.isEmpty) {
-        print('Missing code points ${missingCodePoints} for '
-              '${info.element} in $filename');
+        print("Missing code points for ${info.element} in '$filename':");
+        for (CodePoint codePoint in missingCodePoints) {
+          print("  $codePoint");
+        }
         failureList.add(info);
       }
     }
-    if (failureList.isNotEmpty) {
-      if (outputUri == null) {
+  }
+  if (failureList.isNotEmpty) {
+    if (outputUri == null) {
+      if (!measure) {
         Expect.fail(
             "Missing code points found. "
-            "Run the test with a URI option, `source_mapping_test <uri>`, to "
+            "Run the test with a URI option, "
+            "`source_mapping_test --out=<uri> $config`, to "
             "create a html visualization of the missing code points.");
-      } else {
-        createTraceSourceMapHtml(outputUri, processor,
-                                 showAll ? userInfoList : failureList);
       }
-    } else if (outputUri != null) {
-      createTraceSourceMapHtml(outputUri, processor, userInfoList);
+    } else {
+      createTraceSourceMapHtml(outputUri, processor,
+                               showAll ? userInfoList : failureList);
     }
-  });
+  } else if (outputUri != null) {
+    createTraceSourceMapHtml(outputUri, processor, userInfoList);
+  }
+  return measurement;
+}
+
+class Measurement {
+  final String config;
+  int missing = 0;
+  int count = 0;
+
+  Measurement(this.config);
+
+  String toString() {
+    double percentage = 100 * missing / count;
+    return "Config '${config}': $missing of $count ($percentage%) missing";
+  }
 }
diff --git a/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart b/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart
index d7aa763..b0dfb21 100644
--- a/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart
@@ -7,7 +7,8 @@
 import 'dart:async';
 import 'package:compiler/src/apiimpl.dart' as api;
 import 'package:compiler/src/dart2jslib.dart' show NullSink;
-import "package:compiler/src/elements/elements.dart";
+import 'package:compiler/src/elements/elements.dart';
+import 'package:compiler/src/helpers/helpers.dart';
 import 'package:compiler/src/filenames.dart';
 import 'package:compiler/src/io/source_file.dart';
 import 'package:compiler/src/io/source_information.dart';
@@ -106,20 +107,23 @@
   }
 
   /// Computes the [SourceMapInfo] for the compiled elements.
-  Future<List<SourceMapInfo>> process(List<String> options) async {
+  Future<List<SourceMapInfo>> process(
+      List<String> options,
+      {bool verbose: true}) async {
     OutputProvider outputProvider = outputToFile
         ? new OutputProvider()
         : new CloningOutputProvider(targetUri, sourceMapFileUri);
     if (options.contains('--use-new-source-info')) {
-      print('Using the new source information system.');
+      if (verbose) print('Using the new source information system.');
       useNewSourceInfo = true;
     }
     api.Compiler compiler = await compilerFor({},
         outputProvider: outputProvider,
+        // TODO(johnniwinther): Use [verbose] to avoid showing diagnostics.
         options: ['--out=$targetUri', '--source-map=$sourceMapFileUri']
             ..addAll(options));
     if (options.contains('--disable-inlining')) {
-      print('Inlining disabled');
+      if (verbose) print('Inlining disabled');
       compiler.disableInlining = true;
     }
 
diff --git a/tests/compiler/dart2js/world_test.dart b/tests/compiler/dart2js/world_test.dart
new file mode 100644
index 0000000..436b3d7
--- /dev/null
+++ b/tests/compiler/dart2js/world_test.dart
@@ -0,0 +1,130 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library world_test;
+
+import 'package:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+import 'type_test_helper.dart';
+import 'package:compiler/src/elements/elements.dart'
+       show Element, ClassElement;
+import 'package:compiler/src/dart2jslib.dart';
+
+void main() {
+  asyncTest(() => TypeEnvironment.create(r"""
+      class A {}
+      class B {}
+      class C extends A {}
+      class D implements A {}
+      class E extends B implements A {}
+      class F extends Object with A implements B {}
+      class G extends Object with A, B {}
+      """,
+      mainSource: r"""
+      main() {
+        new A();
+        new B();
+        new C();
+        new D();
+        new E();
+        new F();
+        new G();
+      }
+      """,
+      useMockCompiler: false).then((env) {
+    ClassWorld classWorld = env.compiler.world;
+
+    ClassElement Object_ = env.getElement("Object");
+    ClassElement A = env.getElement("A");
+    ClassElement B = env.getElement("B");
+    ClassElement C = env.getElement("C");
+    ClassElement D = env.getElement("D");
+    ClassElement E = env.getElement("E");
+    ClassElement F = env.getElement("F");
+    ClassElement G = env.getElement("G");
+
+    void check(
+        String property,
+        ClassElement cls,
+        Iterable<ClassElement> foundClasses,
+        List<ClassElement> expectedClasses,
+        {bool exact: true}) {
+      for (ClassElement expectedClass in expectedClasses) {
+        Expect.isTrue(foundClasses.contains(expectedClass),
+            "Expect $expectedClass in '$property' on $cls. "
+            "Found:\n ${foundClasses.join('\n ')}");
+      }
+      if (exact) {
+        Expect.equals(expectedClasses.length, foundClasses.length,
+            "Unexpected classes "
+            "${foundClasses.where((c) => !expectedClasses.contains(c))} "
+            "in '$property' on $cls.");
+      }
+    }
+
+    void testStrictSubclasses(
+        ClassElement cls,
+        List<ClassElement> expectedClasses,
+        {bool exact: true}) {
+      check(
+        'strictSubclassesOf',
+        cls,
+        classWorld.strictSubclassesOf(cls),
+        expectedClasses,
+        exact: exact);
+    }
+
+    void testStrictSubtypes(
+        ClassElement cls,
+        List<ClassElement> expectedClasses,
+        {bool exact: true}) {
+      check(
+        'strictSubtypesOf',
+        cls,
+        classWorld.strictSubtypesOf(cls),
+        expectedClasses,
+        exact: exact);
+    }
+
+    void testMixinUses(
+        ClassElement cls,
+        List<ClassElement> expectedClasses,
+        {bool exact: true}) {
+      check(
+        'mixinUsesOf',
+        cls,
+        classWorld.mixinUsesOf(cls),
+        expectedClasses,
+        exact: exact);
+    }
+
+    testStrictSubclasses(Object_, [A, B, C, D, E, F, G], exact: false);
+    testStrictSubclasses(A, [C]);
+    testStrictSubclasses(B, [E]);
+    testStrictSubclasses(C, []);
+    testStrictSubclasses(D, []);
+    testStrictSubclasses(E, []);
+    testStrictSubclasses(F, []);
+    testStrictSubclasses(G, []);
+
+    testStrictSubtypes(Object_, [A, B, C, D, E, F, G], exact: false);
+    testStrictSubtypes(A, [C, D, E, F, G]);
+    testStrictSubtypes(B, [E, F, G]);
+    testStrictSubtypes(C, []);
+    testStrictSubtypes(D, []);
+    testStrictSubtypes(E, []);
+    testStrictSubtypes(F, []);
+    testStrictSubtypes(G, []);
+
+    testMixinUses(Object_, []);
+    testMixinUses(A, [F.superclass, G.superclass.superclass]);
+    testMixinUses(B, [G.superclass]);
+    testMixinUses(C, []);
+    testMixinUses(D, []);
+    testMixinUses(E, []);
+    testMixinUses(F, []);
+    testMixinUses(G, []);
+
+  }));
+}
diff --git a/tests/compiler/dart2js_extra/23486_test.dart b/tests/compiler/dart2js_extra/23486_test.dart
index 1d8eb39..41fcf2d 100644
--- a/tests/compiler/dart2js_extra/23486_test.dart
+++ b/tests/compiler/dart2js_extra/23486_test.dart
@@ -33,6 +33,6 @@
 main() {
   Expect.throws(new A().m);          /// 01: continued
   Expect.throws(() => new D.name()); /// 02: continued
-  Expect.throws(() => (p).x);        /// 03: static type warning
+  Expect.throws(() => (p).x);        /// 03: compile-time error
 }
 
diff --git a/tests/compiler/dart2js_extra/23804_test.dart b/tests/compiler/dart2js_extra/23804_test.dart
new file mode 100644
index 0000000..2fad1d5
--- /dev/null
+++ b/tests/compiler/dart2js_extra/23804_test.dart
@@ -0,0 +1,15 @@
+// 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.
+
+// Regression test for http://dartbug.com/23804/
+// Inference incorrectly assumed that `any` and `every` didn't escape the values
+// in the collections.
+
+import 'package:expect/expect.dart';
+
+test(n) => n == 1;
+run(f) => f(1);
+main() {
+  Expect.equals([test].any(run), true);
+}
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index d3968e2..5c61219 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -71,21 +71,20 @@
 async_stacktrace_test/asyncStar: Crash # (runTests()async{awa...  cannot handle async/sync*/async* functions
 async_stacktrace_test/none: Crash # (runTests()async{awa...  cannot handle async/sync*/async* functions
 closure_capture5_test: Crash # (i=0): For-loop variable captured in loop header
-conditional_send_test: RuntimeError # receiver.get$_nums is not a function
-deferred/deferred_class_test: RuntimeError # receiver.get$_nums is not a function
-deferred/deferred_constant2_test: RuntimeError # receiver.get$_nums is not a function
-deferred/deferred_constant3_test: RuntimeError # receiver.get$_nums is not a function
-deferred/deferred_constant4_test: RuntimeError # receiver.get$_nums is not a function
-deferred/deferred_function_test: RuntimeError # receiver.get$_nums is not a function
-deferred/deferred_mirrors1_test: RuntimeError # receiver.get$_nums is not a function
-deferred/deferred_mirrors2_test: RuntimeError # receiver.get$_collection$_nums is not a function
-deferred/deferred_overlapping_test: RuntimeError # receiver.get$_nums is not a function
-if_null_test: RuntimeError # receiver.get$_nums is not a function
-mirror_printer_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirror_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors_used_warning2_test: RuntimeError # receiver.get$_nums is not a function
-mirrors_used_warning_test/minif: RuntimeError # receiver.get$_nums is not a function
-mirrors_used_warning_test/none: RuntimeError # receiver.get$_nums is not a function
-reflect_native_types_test: Crash # (=_EmptyStream<T>;): Unhandled node
+conditional_send_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred/deferred_class_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred/deferred_constant2_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred/deferred_constant3_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred/deferred_constant4_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred/deferred_function_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred/deferred_mirrors1_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred/deferred_mirrors2_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+deferred/deferred_overlapping_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+if_null_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+mirror_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors_used_warning2_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+mirrors_used_warning_test/minif: RuntimeError # receiver._addHashTableEntry$2 is not a function
+mirrors_used_warning_test/none: RuntimeError # receiver._addHashTableEntry$2 is not a function
+reflect_native_types_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
 switch_test/none: Crash # (switch (val){foo:ba...  continue to a labeled switch case
-timer_test: RuntimeError # receiver.get$_nums is not a function
+timer_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
diff --git a/tests/compiler/dart2js_extra/interceptor_named_arguments_test.dart b/tests/compiler/dart2js_extra/interceptor_named_arguments_test.dart
new file mode 100644
index 0000000..6911a96
--- /dev/null
+++ b/tests/compiler/dart2js_extra/interceptor_named_arguments_test.dart
@@ -0,0 +1,56 @@
+// 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.
+
+
+// Test that the proper one-shot interceptor is used for different
+// combinations of named arguments.
+import "package:expect/expect.dart";
+
+// Use dart:html to get interceptors into play.
+import "dart:html";
+
+// [createFragment] has the same signature as in [Element].
+class Other {
+  createFragment(html, {validator, treeSanitizer}) {
+    int result = 0;
+    result += validator == null ? 0 : 2;
+    result += treeSanitizer == null ? 0 : 1;
+    return result;
+  }
+}
+
+@NoInline()
+bool wontTell(bool x) => x;
+
+
+// Ensure that we use the interceptor only once per context so that we
+// actually get a one-shot interceptor. This is a little brittle...
+@NoInline()
+testA(thing) {
+  Expect.equals(0, thing.createFragment(null));
+}
+
+@NoInline()
+testB(thing) {
+  Expect.equals(2, thing.createFragment(null, validator: 1));
+}
+
+@NoInline()
+testC(thing) {
+  Expect.equals(1, thing.createFragment(null, treeSanitizer: 1));
+}
+
+@NoInline()
+testD(thing) {
+  Expect.equals(3, thing.createFragment(null, validator: 1, treeSanitizer: 1));
+}
+
+main () {
+  // Ensure we get interceptors into play.
+  var thing = wontTell(true) ? new Other() : new DivElement();
+  testA(thing);
+  testB(thing);
+  testC(thing);
+  testD(thing);
+}
diff --git a/tests/compiler/dart2js_native/dart2js_native.status b/tests/compiler/dart2js_native/dart2js_native.status
index 2b3774c..bacc7ed 100644
--- a/tests/compiler/dart2js_native/dart2js_native.status
+++ b/tests/compiler/dart2js_native/dart2js_native.status
@@ -21,14 +21,14 @@
 compute_this_script_test: Skip # Issue 17458
 
 [ $compiler == dart2js && $cps_ir ]
-compute_this_script_test: RuntimeError # receiver.get$_nums is not a function
-event_loop_test: RuntimeError # receiver.get$_nums is not a function
-internal_library_test: RuntimeError # receiver.get$_nums is not a function
-mirror_intercepted_field_test: Crash # (=_EmptyStream<T>;): Unhandled node
+compute_this_script_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+event_loop_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+internal_library_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+mirror_intercepted_field_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
 native_closure_identity_frog_test: RuntimeError # invoke is not a function
 native_exception_test: RuntimeError # J.getInterceptor(...).toString$0 is not a function
 native_method_inlining_test: RuntimeError # Please triage this failure.
-native_mirror_test: Crash # (=_EmptyStream<T>;): Unhandled node
+native_mirror_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
 native_no_such_method_exception3_frog_test: RuntimeError # Please triage this failure.
 native_wrapping_function3_frog_test: RuntimeError # invoke is not a function
 native_wrapping_function_frog_test: RuntimeError # invoke is not a function
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 4f9274e..2061caf 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -221,13 +221,13 @@
 iterable_to_set_test: RuntimeError # Please triage this failure.
 list_test/01: RuntimeError # this.get$length is not a function
 list_test/none: RuntimeError # this.get$length is not a function
-main_test: RuntimeError # receiver.get$_nums is not a function
+main_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
 map_values2_test: RuntimeError # Please triage this failure.
 map_values3_test: RuntimeError # Please triage this failure.
 map_values4_test: RuntimeError # Please triage this failure.
 regexp/pcre_test: Crash # Stack Overflow
 shuffle_test: RuntimeError # this.get$length is not a function
-stacktrace_fromstring_test: RuntimeError # receiver.get$_nums is not a function
+stacktrace_fromstring_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
 string_fromcharcodes_test: RuntimeError # this.get$length is not a function
 symbol_operator_test/03: RuntimeError # Please triage this failure.
 symbol_reserved_word_test/03: Pass # Please triage this failure.
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index 2472eb6..ca463e5 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -126,55 +126,55 @@
 package_root_test: SkipByDesign # Uses dart:io.
 
 [ $compiler == dart2js && $cps_ir ]
-bool_from_environment_default_value_test: RuntimeError # receiver.get$_collection$_nums is not a function
-capability_test: RuntimeError # receiver.get$_collection$_nums is not a function
-compile_time_error_test/none: RuntimeError # receiver.get$_collection$_nums is not a function
-count_test: RuntimeError # receiver.get$_nums is not a function
-cross_isolate_message_test: RuntimeError # receiver.get$_nums is not a function
-deferred_in_isolate2_test: RuntimeError # receiver.get$_collection$_nums is not a function
-deferred_in_isolate_test: RuntimeError # receiver.get$_collection$_nums is not a function
-function_send_test: RuntimeError # receiver.get$_nums is not a function
-handle_error2_test: RuntimeError # receiver.get$_collection$_nums is not a function
-handle_error3_test: RuntimeError # receiver.get$_collection$_nums is not a function
-handle_error_test: RuntimeError # receiver.get$_collection$_nums is not a function
-illegal_msg_function_test: RuntimeError # receiver.get$_nums is not a function
-illegal_msg_mirror_test: RuntimeError # receiver.get$_nums is not a function
-int_from_environment_default_value_test: RuntimeError # receiver.get$_collection$_nums is not a function
-isolate_complex_messages_test: RuntimeError # receiver.get$_nums is not a function
-isolate_current_test: RuntimeError # receiver.get$_nums is not a function
-isolate_import_test/none: RuntimeError # receiver.get$_collection$_nums is not a function
-issue_22778_test: RuntimeError # receiver.get$_collection$_nums is not a function
-kill2_test: RuntimeError # receiver.get$_collection$_nums is not a function
-kill_self_test: RuntimeError # receiver.get$_collection$_nums is not a function
-kill_test: RuntimeError # receiver.get$_collection$_nums is not a function
-mandel_isolate_test: RuntimeError # receiver.get$_collection$_nums is not a function
-message2_test: RuntimeError # receiver.get$_nums is not a function
-message3_test/byteBuffer: RuntimeError # receiver.get$_collection$_nums is not a function
-message3_test/fun: RuntimeError # receiver.get$_collection$_nums is not a function
-message3_test/int32x4: RuntimeError # receiver.get$_collection$_nums is not a function
-message3_test/none: RuntimeError # receiver.get$_collection$_nums is not a function
-message_enum_test: RuntimeError # receiver.get$_collection$_nums is not a function
-message_test: RuntimeError # receiver.get$_nums is not a function
-mint_maker_test: RuntimeError # receiver.get$_nums is not a function
-nested_spawn2_test: RuntimeError # receiver.get$_nums is not a function
-nested_spawn_test: RuntimeError # receiver.get$_nums is not a function
-object_leak_test: RuntimeError # receiver.get$_collection$_nums is not a function
-ondone_test: RuntimeError # receiver.get$_nums is not a function
-pause_test: RuntimeError # receiver.get$_nums is not a function
-ping_pause_test: RuntimeError # receiver.get$_collection$_nums is not a function
-ping_test: RuntimeError # receiver.get$_collection$_nums is not a function
-port_test: RuntimeError # receiver.get$_collection$_nums is not a function
-raw_port_test: RuntimeError # receiver.get$_nums is not a function
-request_reply_test: RuntimeError # receiver.get$_nums is not a function
-simple_message_test/none: RuntimeError # receiver.get$_collection$_nums is not a function
-spawn_function_custom_class_test: RuntimeError # receiver.get$_nums is not a function
-spawn_function_test: RuntimeError # receiver.get$_nums is not a function
-spawn_uri_missing_from_isolate_test: RuntimeError # receiver.get$_collection$_nums is not a function
-spawn_uri_missing_test: RuntimeError # receiver.get$_collection$_nums is not a function
-stacktrace_message_test: RuntimeError # receiver.get$_nums is not a function
-start_paused_test: RuntimeError # receiver.get$_nums is not a function
-static_function_test: RuntimeError # receiver.get$_nums is not a function
-string_from_environment_default_value_test: RuntimeError # receiver.get$_collection$_nums is not a function
-timer_isolate_test: RuntimeError # receiver.get$_collection$_nums is not a function
-typed_message_test: RuntimeError # receiver.get$_nums is not a function
-unresolved_ports_test: RuntimeError # receiver.get$_nums is not a function
+bool_from_environment_default_value_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+capability_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+compile_time_error_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+count_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+cross_isolate_message_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_in_isolate2_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+deferred_in_isolate_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+function_send_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+handle_error2_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+handle_error3_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+handle_error_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+illegal_msg_function_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+illegal_msg_mirror_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+int_from_environment_default_value_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+isolate_complex_messages_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+isolate_current_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+isolate_import_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+issue_22778_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+kill2_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+kill_self_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+kill_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mandel_isolate_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+message2_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+message3_test/byteBuffer: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+message3_test/fun: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+message3_test/int32x4: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+message3_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+message_enum_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+message_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+mint_maker_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+nested_spawn2_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+nested_spawn_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+object_leak_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+ondone_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+pause_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+ping_pause_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+ping_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+port_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+raw_port_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+request_reply_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+simple_message_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+spawn_function_custom_class_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+spawn_function_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+spawn_uri_missing_from_isolate_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+spawn_uri_missing_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+stacktrace_message_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+start_paused_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+static_function_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+string_from_environment_default_value_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+timer_isolate_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+typed_message_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+unresolved_ports_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
diff --git a/tests/language/deferred_static_seperate_test.dart b/tests/language/deferred_static_seperate_test.dart
index f5e59f0..080c753 100644
--- a/tests/language/deferred_static_seperate_test.dart
+++ b/tests/language/deferred_static_seperate_test.dart
@@ -14,6 +14,7 @@
 
 void main() {
   asyncStart();
+  Expect.throws(() => new lib1.C());
   lib1.loadLibrary().then((_) {
     lib2.loadLibrary().then((_) {
       print("HERE");
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index f728a01..0a9e2cf 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -33,10 +33,6 @@
 stacktrace_rethrow_nonerror_test: Pass, RuntimeError # Issue 12698
 stacktrace_rethrow_error_test: Pass, RuntimeError # Issue 12698
 instantiate_type_variable_test/01: CompileTimeError # Issue 13631
-library_ambiguous_test/00: CompileTimeError # Issue 13632
-library_ambiguous_test/01: CompileTimeError # Issue 13632
-library_ambiguous_test/02: CompileTimeError # Issue 13632
-library_ambiguous_test/03: CompileTimeError # Issue 13632
 type_variable_conflict_test/01: Fail # Issue 13702
 type_variable_conflict_test/02: Fail # Issue 13702
 type_variable_conflict_test/03: Fail # Issue 13702
@@ -64,21 +60,12 @@
 if_null_assignment_behavior_test/14: Crash # Issue 23491
 nullaware_opt_test: Fail # Fails at e?.f ??= 200;
 
-conditional_method_invocation_test/11: MissingCompileTimeError # Issue 23611
-conditional_property_access_test/09: MissingCompileTimeError # Issue 23611
-conditional_property_assignment_test/20: MissingCompileTimeError # Issue 23611
-conditional_property_assignment_test/21: MissingCompileTimeError # Issue 23611
-conditional_property_assignment_test/22: MissingCompileTimeError # Issue 23611
 if_null_assignment_behavior_test/29: Crash # Issue 23611
 if_null_assignment_behavior_test/30: Crash # Issue 23611
 prefix_assignment_test/01: Crash # Issue 23611
 prefix_assignment_test/02: Crash # Issue 23611
-prefix_identifier_reference_test/01: MissingCompileTimeError # Issue 23611
-prefix_identifier_reference_test/02: MissingCompileTimeError # Issue 23611
-prefix_identifier_reference_test/03: MissingCompileTimeError # Issue 23611
 prefix_identifier_reference_test/04: Crash # Issue 23611
 prefix_identifier_reference_test/05: Crash # Issue 23611
-prefix_unqualified_invocation_test/01: RuntimeError # Issue 23611
 
 const_error_multiply_initialized_test/02: CompileTimeError # Issue 23618
 const_error_multiply_initialized_test/04: CompileTimeError # Issue 23618
@@ -206,10 +193,6 @@
 bit_operations_test: RuntimeError, OK # Issue 1533
 expect_test: RuntimeError, OK # Issue 13080
 
-illegal_invocation_test/01: MissingCompileTimeError # Issue 23611
-prefix_unqualified_invocation_test/01: MissingCompileTimeError # Issue 23611
-prefix_unqualified_invocation_test/02: MissingCompileTimeError # Issue 23611
-
 [ $compiler == dart2js && $runtime == none ]
 *: Fail, Pass # TODO(ahe): Triage these tests.
 
@@ -360,55 +343,56 @@
 await_postfix_expr_test: Crash # (test()async{Expect....  cannot handle async/sync*/async* functions
 await_regression_test: Crash # (main()async{testNes...  cannot handle async/sync*/async* functions
 await_test: Crash # (others()async{var a...  cannot handle async/sync*/async* functions
-cha_deopt1_test: RuntimeError # receiver.get$_nums is not a function
-cha_deopt2_test: RuntimeError # receiver.get$_nums is not a function
-cha_deopt3_test: RuntimeError # receiver.get$_nums is not a function
-closure_cycles_test: RuntimeError # receiver.get$_nums is not a function
+cha_deopt1_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+cha_deopt2_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+cha_deopt3_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+closure_cycles_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
 closure_in_constructor_test: Crash # Invalid argument(s)
 closure_type_variables_test: Crash # Invalid argument(s)
-const_evaluation_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
+const_evaluation_test/01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
 constructor12_test: RuntimeError # Please triage this failure.
 crash_6725_test/01: Crash # The null object does not have a getter '_element'.
 custom_await_stack_trace_test: Crash # (main()async{try {va...  cannot handle async/sync*/async* functions
-deferred_closurize_load_library_test: RuntimeError # receiver.get$_nums is not a function
-deferred_constant_list_test: RuntimeError # receiver.get$_nums is not a function
-deferred_constraints_constants_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-deferred_constraints_constants_test/reference_after_load: Crash # (=_EmptyStream<T>;): Unhandled node
-deferred_constraints_type_annotation_test/as_operation: RuntimeError # receiver.get$_nums is not a function
+deferred_closurize_load_library_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_constant_list_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_constraints_constants_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+deferred_constraints_constants_test/reference_after_load: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+deferred_constraints_type_annotation_test/as_operation: RuntimeError # receiver._addHashTableEntry$2 is not a function
 deferred_constraints_type_annotation_test/catch_check: Crash # The null object does not have a getter '_element'.
-deferred_constraints_type_annotation_test/is_check: RuntimeError # receiver.get$_nums is not a function
-deferred_constraints_type_annotation_test/new: RuntimeError # receiver.get$_nums is not a function
-deferred_constraints_type_annotation_test/new_before_load: RuntimeError # receiver.get$_nums is not a function
-deferred_constraints_type_annotation_test/new_generic1: RuntimeError # receiver.get$_nums is not a function
-deferred_constraints_type_annotation_test/new_generic2: RuntimeError # receiver.get$_nums is not a function
-deferred_constraints_type_annotation_test/new_generic3: RuntimeError # receiver.get$_nums is not a function
-deferred_constraints_type_annotation_test/none: RuntimeError # receiver.get$_nums is not a function
-deferred_constraints_type_annotation_test/static_method: RuntimeError # receiver.get$_nums is not a function
-deferred_constraints_type_annotation_test/type_annotation1: RuntimeError # receiver.get$_nums is not a function
-deferred_constraints_type_annotation_test/type_annotation_generic1: RuntimeError # receiver.get$_nums is not a function
-deferred_constraints_type_annotation_test/type_annotation_generic2: RuntimeError # receiver.get$_nums is not a function
-deferred_constraints_type_annotation_test/type_annotation_generic3: RuntimeError # receiver.get$_nums is not a function
-deferred_constraints_type_annotation_test/type_annotation_generic4: RuntimeError # receiver.get$_nums is not a function
-deferred_constraints_type_annotation_test/type_annotation_non_deferred: RuntimeError # receiver.get$_nums is not a function
-deferred_constraints_type_annotation_test/type_annotation_null: RuntimeError # receiver.get$_nums is not a function
-deferred_constraints_type_annotation_test/type_annotation_top_level: RuntimeError # receiver.get$_nums is not a function
-deferred_function_type_test: RuntimeError # receiver.get$_nums is not a function
-deferred_global_test: RuntimeError # receiver.get$_collection$_nums is not a function
-deferred_inlined_test: RuntimeError # receiver.get$_nums is not a function
-deferred_load_constants_test/none: RuntimeError # receiver.get$_nums is not a function
-deferred_load_inval_code_test: RuntimeError # receiver.get$_nums is not a function
-deferred_load_library_wrong_args_test/none: RuntimeError # receiver.get$_nums is not a function
-deferred_mixin_test: RuntimeError # receiver.get$_nums is not a function
-deferred_no_such_method_test: RuntimeError # receiver.get$_nums is not a function
+deferred_constraints_type_annotation_test/is_check: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_constraints_type_annotation_test/new: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_constraints_type_annotation_test/new_before_load: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_constraints_type_annotation_test/new_generic1: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_constraints_type_annotation_test/new_generic2: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_constraints_type_annotation_test/new_generic3: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_constraints_type_annotation_test/none: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_constraints_type_annotation_test/static_method: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_constraints_type_annotation_test/type_annotation1: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_constraints_type_annotation_test/type_annotation_generic1: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_constraints_type_annotation_test/type_annotation_generic2: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_constraints_type_annotation_test/type_annotation_generic3: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_constraints_type_annotation_test/type_annotation_generic4: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_constraints_type_annotation_test/type_annotation_non_deferred: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_constraints_type_annotation_test/type_annotation_null: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_constraints_type_annotation_test/type_annotation_top_level: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_function_type_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_global_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_inlined_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_load_constants_test/none: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_load_inval_code_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_load_library_wrong_args_test/none: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_mixin_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_no_such_method_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
 deferred_not_loaded_check_test: RuntimeError # Please triage this failure.
-deferred_only_constant_test: RuntimeError # receiver.get$_nums is not a function
-deferred_optimized_test: RuntimeError # receiver.get$_nums is not a function
+deferred_only_constant_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_optimized_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
 deferred_redirecting_factory_test: Crash # (test()async{await t...  cannot handle async/sync*/async* functions
-deferred_regression_22995_test: RuntimeError # receiver.get$_nums is not a function
-deferred_shadow_load_library_test: RuntimeError # receiver.get$_nums is not a function
-deferred_shared_and_unshared_classes_test: RuntimeError # receiver.get$_nums is not a function
-deferred_static_seperate_test: RuntimeError # receiver.get$_collection$_nums is not a function
-enum_mirror_test: Crash # (=_EmptyStream<T>;): Unhandled node
+deferred_regression_22995_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_shadow_load_library_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_shared_and_unshared_classes_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+deferred_static_seperate_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+dynamic_prefix_core_test/01: Crash # The null object does not have a getter 'name'.
+enum_mirror_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
 final_super_field_set_test/01: RuntimeError # Please triage this failure.
 flatten_test/01: Crash # (test()async{int x=await new Derived<int>();}): cannot handle async/sync*/async* functions
 flatten_test/02: Crash # (test()async{Future<int> f()async=>new Derived<int>();}): cannot handle async/sync*/async* functions
@@ -426,34 +410,41 @@
 for2_test: Crash # The null object does not have a getter 'field'.
 for_variable_capture_test: Crash # (i=0): For-loop variable captured in loop header
 generic_field_mixin3_test: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/12: RuntimeError # Please triage this failure.
+if_null_assignment_behavior_test/28: RuntimeError # Please triage this failure.
 if_null_assignment_static_test/01: RuntimeError # v0.get$a is not a function
 if_null_assignment_static_test/03: RuntimeError # v0.get$a is not a function
 if_null_assignment_static_test/04: RuntimeError # v0.get$b is not a function
 if_null_assignment_static_test/05: RuntimeError # v0.get$a is not a function
+if_null_assignment_static_test/29: RuntimeError # v0.get$a is not a function
+if_null_assignment_static_test/31: RuntimeError # v0.get$a is not a function
+if_null_assignment_static_test/32: RuntimeError # v0.get$b is not a function
+if_null_assignment_static_test/33: RuntimeError # v0.get$a is not a function
 if_null_assignment_static_test/36: RuntimeError # v0.get$a is not a function
 if_null_assignment_static_test/38: RuntimeError # v0.get$a is not a function
 if_null_assignment_static_test/39: RuntimeError # v0.get$b is not a function
 if_null_assignment_static_test/40: RuntimeError # v0.get$a is not a function
+import_self_test/01: Crash # The null object does not have a getter 'name'.
 infinite_switch_label_test: Crash # (switch (target){l0:...  continue to a labeled switch case
-instance_creation_in_function_annotation_test: Crash # (=_EmptyStream<T>;): Unhandled node
+instance_creation_in_function_annotation_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
 instanceof4_test/01: RuntimeError # Please triage this failure.
 invocation_mirror_invoke_on_test: RuntimeError # Please triage this failure.
 invocation_mirror_test: Crash # (super[37]=42): visitUnresolvedSuperIndexSet
-issue_1751477_test: RuntimeError # receiver.get$_nums is not a function
+issue_1751477_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
 large_class_declaration_test: Crash # Stack Overflow
 list_test: RuntimeError # Please triage this failure.
-main_test/01: RuntimeError # receiver.get$_nums is not a function
-main_test/02: RuntimeError # receiver.get$_nums is not a function
-main_test/04: RuntimeError # receiver.get$_nums is not a function
-main_test/05: RuntimeError # receiver.get$_nums is not a function
-main_test/20: RuntimeError # receiver.get$_nums is not a function
-main_test/21: RuntimeError # receiver.get$_nums is not a function
-main_test/22: RuntimeError # receiver.get$_nums is not a function
-main_test/41: RuntimeError # receiver.get$_nums is not a function
-main_test/42: RuntimeError # receiver.get$_nums is not a function
-main_test/43: RuntimeError # receiver.get$_nums is not a function
-main_test/44: RuntimeError # receiver.get$_nums is not a function
-main_test/45: RuntimeError # receiver.get$_nums is not a function
+main_test/01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+main_test/02: RuntimeError # receiver._addHashTableEntry$2 is not a function
+main_test/04: RuntimeError # receiver._addHashTableEntry$2 is not a function
+main_test/05: RuntimeError # receiver._addHashTableEntry$2 is not a function
+main_test/20: RuntimeError # receiver._addHashTableEntry$2 is not a function
+main_test/21: RuntimeError # receiver._addHashTableEntry$2 is not a function
+main_test/22: RuntimeError # receiver._addHashTableEntry$2 is not a function
+main_test/41: RuntimeError # receiver._addHashTableEntry$2 is not a function
+main_test/42: RuntimeError # receiver._addHashTableEntry$2 is not a function
+main_test/43: RuntimeError # receiver._addHashTableEntry$2 is not a function
+main_test/44: RuntimeError # receiver._addHashTableEntry$2 is not a function
+main_test/45: RuntimeError # receiver._addHashTableEntry$2 is not a function
 many_overridden_no_such_method_test: RuntimeError # Please triage this failure.
 mixin_type_parameters_mixin_extends_test: Crash # The null object does not have a getter '_element'.
 mixin_type_parameters_mixin_test: Crash # The null object does not have a getter '_element'.
@@ -461,18 +452,22 @@
 mixin_type_parameters_super_test: Crash # The null object does not have a getter '_element'.
 nested_switch_label_test: Crash # (switch (target){out...  continue to a labeled switch case
 no_such_method_test: RuntimeError # Please triage this failure.
-null_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
+null_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
 overridden_no_such_method_test: RuntimeError # Please triage this failure.
-regress_18535_test: Crash # (=_EmptyStream<T>;): Unhandled node
+prefix12_negative_test: Crash # The null object does not have a getter 'name'.
+prefix2_negative_test: Crash # The null object does not have a getter 'name'.
+private_access_test/02: Crash # The null object does not have a getter 'name'.
+redirecting_factory_reflection_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+regress_18535_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
 regress_22438_test: Crash # (main()async{var err...  cannot handle async/sync*/async* functions
-regress_22443_test: RuntimeError # receiver.get$_nums is not a function
+regress_22443_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
 regress_22445_test: Crash # (main()async{var err...  cannot handle async/sync*/async* functions
 regress_22579_test: Crash # (main()async{var err...  cannot handle async/sync*/async* functions
 regress_22728_test: Crash # (main()async{bool fa...  cannot handle async/sync*/async* functions
 regress_22777_test: Crash # (test()async{try {te...  cannot handle async/sync*/async* functions
 regress_22936_test/01: Crash # The null object does not have a getter '_element'.
 regress_22936_test/none: Crash # The null object does not have a getter '_element'.
-regress_23408_test: RuntimeError # receiver.get$_nums is not a function
+regress_23408_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
 regress_23498_test: Crash # (main()async{var err...  cannot handle async/sync*/async* functions
 regress_23500_test/01: Crash # (main()async{var err...  cannot handle async/sync*/async* functions
 regress_23500_test/02: Crash # (main()async{var err...  cannot handle async/sync*/async* functions
diff --git a/tests/language/nullaware_opt_test.dart b/tests/language/nullaware_opt_test.dart
index aafb7ac..625ccc9 100644
--- a/tests/language/nullaware_opt_test.dart
+++ b/tests/language/nullaware_opt_test.dart
@@ -36,7 +36,7 @@
   Expect.equals(d, d ?? bomb());
 
   var e;
-  // The assginment to e is not executed since d != null.
+  // The assignment to e is not executed since d != null.
   d ??= e ??= new C(100);
   Expect.equals(null, e);
   e ??= new C(100);
diff --git a/tests/language/redirecting_factory_reflection_test.dart b/tests/language/redirecting_factory_reflection_test.dart
new file mode 100644
index 0000000..af39373
--- /dev/null
+++ b/tests/language/redirecting_factory_reflection_test.dart
@@ -0,0 +1,22 @@
+// 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.
+
+import 'dart:mirrors';
+import 'package:expect/expect.dart';
+
+abstract class A<T> {
+  get t;
+  factory A() = B<T, A<T>>;
+}
+
+class B<X, Y> implements A<X> {
+  final t;
+  B() : t = Y;
+}
+
+main() {
+  ClassMirror m = reflectClass(A);
+  var i = m.newInstance(const Symbol(''), []).reflectee;
+  Expect.equals(i.t.toString(), 'A');
+}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index e63fadf..02a9e192 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -327,380 +327,297 @@
 convert/streamed_conversion_json_utf8_decode_test: Skip  # Timeout.
 
 [ $compiler == dart2js && $cps_ir ]
-async/catch_errors11_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors12_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors13_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors14_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors15_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors16_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors17_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors18_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors19_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors20_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors21_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors22_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors23_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors24_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors25_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors26_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors27_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors28_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors2_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors3_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors4_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors5_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors6_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors7_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors8_test: RuntimeError # receiver.get$_nums is not a function
-async/catch_errors_test: RuntimeError # receiver.get$_nums is not a function
-async/first_regression_test: RuntimeError # receiver.get$_nums is not a function
-async/future_constructor_test: RuntimeError # receiver.get$_nums is not a function
-async/future_delayed_error_test: RuntimeError # receiver.get$_nums is not a function
-async/future_microtask_test: RuntimeError # receiver.get$_nums is not a function
+async/catch_errors11_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors12_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors13_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors14_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors15_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors16_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors17_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors18_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors19_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors20_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors21_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors22_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors23_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors24_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors25_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors26_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors27_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors28_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors2_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors3_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors4_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors5_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors6_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors7_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors8_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/catch_errors_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/first_regression_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/future_constructor_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/future_delayed_error_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/future_microtask_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
 async/future_test/01: Crash # (()async=>new Future.value(value)): cannot handle async/sync*/async* functions
-async/future_test/none: RuntimeError # receiver.get$_nums is not a function
-async/future_timeout_test: RuntimeError # receiver.get$_nums is not a function
-async/future_value_chain2_test: RuntimeError # receiver.get$_nums is not a function
-async/future_value_chain3_test: RuntimeError # receiver.get$_nums is not a function
-async/future_value_chain4_test: RuntimeError # receiver.get$_nums is not a function
-async/future_value_chain_test: RuntimeError # receiver.get$_nums is not a function
-async/futures_test: RuntimeError # receiver.get$_nums is not a function
-async/intercept_print1_test: RuntimeError # receiver.get$_collection$_nums is not a function
-async/intercept_schedule_microtask1_test: RuntimeError # receiver.get$_nums is not a function
-async/intercept_schedule_microtask2_test: RuntimeError # receiver.get$_nums is not a function
-async/intercept_schedule_microtask3_test: RuntimeError # receiver.get$_nums is not a function
-async/intercept_schedule_microtask4_test: RuntimeError # receiver.get$_nums is not a function
-async/intercept_schedule_microtask5_test: RuntimeError # receiver.get$_nums is not a function
-async/intercept_schedule_microtask6_test: RuntimeError # receiver.get$_nums is not a function
-async/multiple_timer_test: RuntimeError # receiver.get$_nums is not a function
-async/print_test/none: RuntimeError # receiver.get$_nums is not a function
-async/run_zoned1_test: RuntimeError # receiver.get$_nums is not a function
-async/run_zoned4_test: RuntimeError # receiver.get$_nums is not a function
-async/run_zoned5_test: RuntimeError # receiver.get$_nums is not a function
-async/run_zoned6_test/none: RuntimeError # receiver.get$_nums is not a function
-async/run_zoned7_test: RuntimeError # receiver.get$_nums is not a function
-async/run_zoned8_test: RuntimeError # receiver.get$_nums is not a function
-async/run_zoned9_test/none: RuntimeError # receiver.get$_nums is not a function
-async/schedule_microtask2_test: RuntimeError # receiver.get$_nums is not a function
-async/schedule_microtask3_test: RuntimeError # receiver.get$_nums is not a function
-async/schedule_microtask5_test: RuntimeError # receiver.get$_nums is not a function
-async/schedule_microtask_test: RuntimeError # receiver.get$_nums is not a function
-async/slow_consumer2_test: RuntimeError # receiver.get$_nums is not a function
-async/slow_consumer3_test: RuntimeError # receiver.get$_nums is not a function
-async/slow_consumer_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace01_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace02_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace03_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace04_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace05_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace06_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace07_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace08_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace09_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace10_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace11_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace12_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace13_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace14_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace15_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace16_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace17_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace18_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace19_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace20_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace21_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace22_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace23_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace24_test: RuntimeError # receiver.get$_nums is not a function
-async/stack_trace25_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_controller_async_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_controller_test: RuntimeError # receiver.get$_nums is not a function
+async/future_test/none: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/future_timeout_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/future_value_chain2_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/future_value_chain3_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/future_value_chain4_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/future_value_chain_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/futures_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/intercept_print1_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+async/intercept_schedule_microtask1_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/intercept_schedule_microtask2_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/intercept_schedule_microtask3_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/intercept_schedule_microtask4_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/intercept_schedule_microtask5_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/intercept_schedule_microtask6_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/multiple_timer_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/print_test/none: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/run_zoned1_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/run_zoned4_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/run_zoned5_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/run_zoned6_test/none: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/run_zoned7_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/run_zoned8_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/run_zoned9_test/none: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/schedule_microtask2_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/schedule_microtask3_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/schedule_microtask5_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/schedule_microtask_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/slow_consumer2_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/slow_consumer3_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/slow_consumer_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace01_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace02_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace03_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace04_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace05_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace06_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace07_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace08_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace09_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace10_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace11_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace12_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace13_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace14_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace15_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace16_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace17_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace18_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace19_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace20_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace21_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace22_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace23_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace24_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stack_trace25_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_controller_async_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_controller_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
 async/stream_empty_test: Crash # (Future runTest()asy...  cannot handle async/sync*/async* functions
-async/stream_event_transformed_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_first_where_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_from_iterable_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_iterator_double_cancel_test: RuntimeError # receiver.get$_nums is not a function
+async/stream_event_transformed_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_first_where_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_from_iterable_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_iterator_double_cancel_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
 async/stream_iterator_test: Crash # (()async{var stream=...  cannot handle async/sync*/async* functions
-async/stream_join_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_last_where_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_listen_zone_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_periodic2_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_periodic3_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_periodic4_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_periodic5_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_periodic_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_single_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_single_to_multi_subscriber_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_state_nonzero_timer_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_state_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_subscription_as_future_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_subscription_cancel_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_timeout_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_transform_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_transformation_broadcast_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_transformer_from_handlers_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_transformer_test: RuntimeError # receiver.get$_nums is not a function
-async/stream_zones_test: RuntimeError # receiver.get$_nums is not a function
-async/timer_cancel1_test: RuntimeError # receiver.get$_nums is not a function
-async/timer_cancel2_test: RuntimeError # receiver.get$_nums is not a function
-async/timer_cancel_test: RuntimeError # receiver.get$_nums is not a function
-async/timer_isActive_test: RuntimeError # receiver.get$_nums is not a function
-async/timer_regress22626_test: RuntimeError # receiver.get$_nums is not a function
-async/timer_repeat_test: RuntimeError # receiver.get$_nums is not a function
-async/timer_test: RuntimeError # receiver.get$_nums is not a function
-async/zone_bind_callback_test: RuntimeError # receiver.get$_nums is not a function
-async/zone_bind_callback_unary_test: RuntimeError # receiver.get$_nums is not a function
-async/zone_bind_test: RuntimeError # receiver.get$_nums is not a function
-async/zone_create_periodic_timer_test: RuntimeError # receiver.get$_nums is not a function
-async/zone_create_timer2_test: RuntimeError # receiver.get$_nums is not a function
-async/zone_create_timer_test: RuntimeError # receiver.get$_nums is not a function
-async/zone_debug_test: RuntimeError # receiver.get$_nums is not a function
-async/zone_empty_description2_test: RuntimeError # receiver.get$_nums is not a function
-async/zone_empty_description_test: RuntimeError # receiver.get$_nums is not a function
-async/zone_error_callback_test: RuntimeError # receiver.get$_nums is not a function
-async/zone_fork_test: RuntimeError # receiver.get$_nums is not a function
-async/zone_future_schedule_microtask_test: RuntimeError # receiver.get$_nums is not a function
-async/zone_register_callback_test: RuntimeError # receiver.get$_nums is not a function
-async/zone_register_callback_unary_test: RuntimeError # receiver.get$_nums is not a function
-async/zone_root_bind_test: RuntimeError # receiver.get$_nums is not a function
-async/zone_run_guarded_test: RuntimeError # receiver.get$_nums is not a function
-async/zone_run_test: RuntimeError # receiver.get$_nums is not a function
-async/zone_run_unary_test: RuntimeError # receiver.get$_nums is not a function
-async/zone_value_test: RuntimeError # receiver.get$_collection$_nums is not a function
+async/stream_join_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_last_where_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_listen_zone_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_periodic2_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_periodic3_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_periodic4_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_periodic5_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_periodic_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_single_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_single_to_multi_subscriber_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_state_nonzero_timer_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_state_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_subscription_as_future_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_subscription_cancel_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_timeout_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_transform_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_transformation_broadcast_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_transformer_from_handlers_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_transformer_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/stream_zones_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/timer_cancel1_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/timer_cancel2_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/timer_cancel_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/timer_isActive_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/timer_regress22626_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/timer_repeat_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/timer_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/zone_bind_callback_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/zone_bind_callback_unary_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/zone_bind_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/zone_create_periodic_timer_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/zone_create_timer2_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/zone_create_timer_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/zone_debug_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/zone_empty_description2_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/zone_empty_description_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/zone_error_callback_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/zone_fork_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/zone_future_schedule_microtask_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/zone_register_callback_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/zone_register_callback_unary_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/zone_root_bind_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/zone_run_guarded_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/zone_run_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/zone_run_unary_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+async/zone_value_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
 convert/ascii_test: RuntimeError # this.get$length is not a function
-convert/encoding_test: RuntimeError # receiver.get$_nums is not a function
-convert/html_escape_test: RuntimeError # receiver.get$_nums is not a function
-convert/json_lib_test: RuntimeError # receiver.get$_nums is not a function
+convert/encoding_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+convert/html_escape_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+convert/json_lib_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
 convert/latin1_test: RuntimeError # this.get$length is not a function
-convert/line_splitter_test: RuntimeError # receiver.get$_nums is not a function
-convert/streamed_conversion_json_decode1_test: RuntimeError # receiver.get$_collection$_nums is not a function
-convert/streamed_conversion_json_encode1_test: RuntimeError # receiver.get$_collection$_nums is not a function
-convert/streamed_conversion_json_utf8_decode_test: RuntimeError # receiver.get$_collection$_nums is not a function
-convert/streamed_conversion_json_utf8_encode_test: RuntimeError # receiver.get$_collection$_nums is not a function
-convert/streamed_conversion_utf8_decode_test: RuntimeError # receiver.get$_nums is not a function
-convert/streamed_conversion_utf8_encode_test: RuntimeError # receiver.get$_nums is not a function
-math/pi_test: RuntimeError # receiver.get$_nums is not a function
-math/point_test: RuntimeError # receiver.get$_nums is not a function
-math/rectangle_test: RuntimeError # receiver.get$_nums is not a function
-mirrors/abstract_class_test/00: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/abstract_class_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/abstract_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/accessor_cache_overflow_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/array_tracing2_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/array_tracing_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/basic_types_in_dart_core_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/circular_factory_redirection_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/class_declarations_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/class_declarations_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/class_mirror_location_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/class_mirror_type_variables_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/closures_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/closurization_equivalence_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/constructor_kinds_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/constructor_kinds_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/constructors_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/dart2js_mirrors_test: Crash # (=Class.faktory;): Unhandled node
-mirrors/declarations_type_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/deferred_mirrors_metadata_test: RuntimeError # receiver.get$_collection$_nums is not a function
-mirrors/deferred_mirrors_metatarget_test: RuntimeError # receiver.get$_collection$_nums is not a function
-mirrors/deferred_mirrors_update_test: RuntimeError # receiver.get$_collection$_nums is not a function
-mirrors/deferred_type_test: Crash # (=_EmptyStream<T>;): Unhandled node
+convert/line_splitter_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+convert/streamed_conversion_json_decode1_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+convert/streamed_conversion_json_encode1_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+convert/streamed_conversion_json_utf8_decode_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+convert/streamed_conversion_json_utf8_encode_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+convert/streamed_conversion_utf8_decode_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+convert/streamed_conversion_utf8_encode_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+math/pi_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+math/point_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+math/rectangle_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+mirrors/abstract_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/accessor_cache_overflow_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/array_tracing2_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/array_tracing_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/basic_types_in_dart_core_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/circular_factory_redirection_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/class_declarations_test/01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+mirrors/class_mirror_type_variables_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/closures_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/constructors_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/dart2js_mirrors_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+mirrors/declarations_type_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/deferred_mirrors_metadata_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/deferred_mirrors_metatarget_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/deferred_mirrors_update_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
 mirrors/delegate_call_through_getter_test: RuntimeError # Please triage this failure.
 mirrors/delegate_test: RuntimeError # Please triage this failure.
-mirrors/disable_tree_shaking_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/empty_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/enum_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/equality_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/fake_function_with_call_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/fake_function_without_call_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/field_type_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/function_type_mirror_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generic_bounded_by_type_parameter_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generic_bounded_by_type_parameter_test/02: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generic_bounded_by_type_parameter_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generic_bounded_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generic_bounded_test/02: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generic_bounded_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generic_class_declaration_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generic_f_bounded_mixin_application_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generic_f_bounded_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generic_f_bounded_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generic_function_typedef_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generic_interface_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generic_interface_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generic_list_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generic_local_function_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generic_mixin_applications_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generic_mixin_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generic_superclass_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generic_superclass_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generic_type_mirror_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generics_double_substitution_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generics_double_substitution_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generics_dynamic_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generics_special_types_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generics_substitution_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generics_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/generics_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/globalized_closures2_test/00: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/globalized_closures2_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/globalized_closures_test/00: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/globalized_closures_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/hierarchy_invariants_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/immutable_collections_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/inherit_field_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/initializing_formals_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/initializing_formals_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/instance_members_easier_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/instance_members_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/instance_members_unimplemented_interface_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/instance_members_with_override_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/instantiate_abstract_class_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/intercepted_cache_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/intercepted_class_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/intercepted_object_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/intercepted_superclass_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/invocation_fuzz_test/emptyarray: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/invocation_fuzz_test/false: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/invocation_fuzz_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/invocation_fuzz_test/smi: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/invocation_fuzz_test/string: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/invoke_call_on_closure_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/invoke_call_through_getter_previously_accessed_test/named: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/invoke_call_through_getter_previously_accessed_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/invoke_call_through_getter_test/named: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/invoke_call_through_getter_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/invoke_call_through_implicit_getter_previously_accessed_test/named: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/invoke_call_through_implicit_getter_previously_accessed_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/invoke_call_through_implicit_getter_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/invoke_closurization2_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/invoke_closurization_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/invoke_import_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/invoke_named_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/invoke_named_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/invoke_natives_malicious_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/invoke_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/invoke_throws_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/is_odd_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/lazy_static_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/libraries_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/library_declarations_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/library_declarations_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/library_enumeration_deferred_loading_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/library_exports_hidden_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/library_exports_shown_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/library_import_deferred_loading_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/library_imports_bad_metadata_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/library_imports_deferred_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/library_imports_hidden_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/library_imports_metadata_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/library_imports_prefixed_show_hide_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/library_imports_prefixed_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/library_imports_shown_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/library_metadata2_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/library_metadata_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/library_uri_package_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/list_constructor_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/list_constructor_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/load_library_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/local_function_is_static_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/local_isolate_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/metadata_allowed_values_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/metadata_allowed_values_test/05: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/metadata_allowed_values_test/10: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/metadata_allowed_values_test/11: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/metadata_allowed_values_test/13: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/metadata_allowed_values_test/14: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/metadata_allowed_values_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/metadata_class_mirror_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/metadata_constructed_constant_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/metadata_constructor_arguments_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/metadata_nested_constructor_call_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/metadata_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/method_mirror_location_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/method_mirror_name_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/method_mirror_properties_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/method_mirror_returntype_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/method_mirror_source_line_ending_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/method_mirror_source_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/mirror_in_static_init_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/mirrors_nsm_mismatch_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/mirrors_nsm_test/dart2js: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/mirrors_nsm_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/mirrors_reader_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/mirrors_resolve_fields_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/mirrors_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/mixin_application_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/mixin_members_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/mixin_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/native_class_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/new_instance_with_type_arguments_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/no_metadata_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/null2_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/null_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/operator_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/parameter_is_const_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/parameter_metadata_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/parameter_of_mixin_app_constructor_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/private_symbol_mangling_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/private_types_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/proxy_type_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/raw_type_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/raw_type_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/redirecting_factory_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/redirecting_factory_test/02: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/redirecting_factory_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/reflect_class_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/reflect_class_test/02: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/reflect_class_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/reflect_model_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/reflect_runtime_type_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/reflect_uninstantiated_class_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/reflected_type_classes_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/reflected_type_classes_test/02: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/reflected_type_classes_test/03: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/reflected_type_classes_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/reflected_type_function_type_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/reflected_type_special_types_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/reflected_type_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/reflected_type_test/02: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/reflected_type_test/03: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/reflected_type_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/reflected_type_typedefs_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/reflected_type_typevars_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/reflectively_instantiate_uninstantiated_class_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/regress_14304_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/regress_16321_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/regress_16321_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/regress_19731_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/relation_assignable_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/relation_subclass_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/relation_subtype_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/removed_api_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/repeated_private_anon_mixin_app_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/set_field_with_final_inheritance_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/set_field_with_final_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/spawn_function_root_library_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/static_members_easier_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/static_members_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/static_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/superclass2_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/superclass_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/symbol_validation_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
+mirrors/disable_tree_shaking_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/equality_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/field_type_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/generic_bounded_by_type_parameter_test/01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/generic_bounded_by_type_parameter_test/02: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/generic_bounded_by_type_parameter_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/generic_bounded_test/01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/generic_bounded_test/02: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/generic_bounded_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/generic_class_declaration_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+mirrors/generic_f_bounded_test/01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/generic_f_bounded_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/generic_list_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/generic_superclass_test/01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/generic_superclass_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/generic_type_mirror_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/generics_double_substitution_test/01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/generics_double_substitution_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/generics_dynamic_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/generics_special_types_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/generics_substitution_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/generics_test/01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/generics_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/globalized_closures2_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/globalized_closures_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/inherit_field_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/initializing_formals_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/instance_members_easier_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+mirrors/instance_members_unimplemented_interface_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+mirrors/instance_members_with_override_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+mirrors/intercepted_cache_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/intercepted_class_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/intercepted_object_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/intercepted_superclass_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/invocation_fuzz_test/emptyarray: RuntimeError # receiver._addHashTableEntry$2 is not a function
+mirrors/invocation_fuzz_test/false: RuntimeError # receiver._addHashTableEntry$2 is not a function
+mirrors/invocation_fuzz_test/none: RuntimeError # receiver._addHashTableEntry$2 is not a function
+mirrors/invocation_fuzz_test/smi: RuntimeError # receiver._addHashTableEntry$2 is not a function
+mirrors/invocation_fuzz_test/string: RuntimeError # receiver._addHashTableEntry$2 is not a function
+mirrors/invoke_call_through_getter_previously_accessed_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/invoke_call_through_getter_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/invoke_call_through_implicit_getter_previously_accessed_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/invoke_closurization2_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/invoke_closurization_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/invoke_import_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/invoke_named_test/01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/invoke_natives_malicious_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/invoke_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/invoke_throws_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/is_odd_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/lazy_static_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/libraries_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/library_declarations_test/01: RuntimeError # receiver._addHashTableEntry$2 is not a function
+mirrors/library_enumeration_deferred_loading_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/library_metadata2_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/library_metadata_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/library_uri_package_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+mirrors/list_constructor_test/01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/list_constructor_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/local_isolate_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/metadata_allowed_values_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/metadata_class_mirror_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/metadata_constructed_constant_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/metadata_constructor_arguments_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/metadata_nested_constructor_call_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/metadata_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/method_mirror_returntype_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/mirror_in_static_init_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/mirrors_nsm_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/mirrors_resolve_fields_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/mixin_members_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/new_instance_with_type_arguments_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/no_metadata_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/null2_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/null_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/operator_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/parameter_is_const_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/parameter_metadata_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/private_symbol_mangling_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/proxy_type_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/raw_type_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/redirecting_factory_test/01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/reflect_class_test/01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/reflect_class_test/02: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/reflect_class_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/reflect_model_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/reflect_runtime_type_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/reflect_uninstantiated_class_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/reflected_type_classes_test/01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/reflected_type_classes_test/02: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/reflected_type_classes_test/03: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/reflected_type_classes_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/reflected_type_test/01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/reflected_type_test/02: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/reflected_type_test/03: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/reflected_type_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/reflectively_instantiate_uninstantiated_class_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/regress_14304_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/regress_16321_test/01: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/regress_16321_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/regress_19731_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+mirrors/relation_subclass_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/removed_api_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/set_field_with_final_inheritance_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/set_field_with_final_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/spawn_function_root_library_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/static_members_easier_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+mirrors/static_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/superclass2_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/superclass_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
 mirrors/symbol_validation_test/none: RuntimeError # Please triage this failure.
-mirrors/syntax_error_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/synthetic_accessor_properties_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/to_string_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/top_level_accessors_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/type_argument_is_type_variable_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/type_variable_is_static_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/type_variable_owner_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/type_variable_owner_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/typearguments_mirror_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/typedef_deferred_library_test: RuntimeError # receiver.get$_collection$_nums is not a function
-mirrors/typedef_metadata_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/typedef_reflected_type_test/01: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/typedef_reflected_type_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/unnamed_library_test: Crash # (=_EmptyStream<T>;): Unhandled node
-mirrors/variable_is_const_test/none: Crash # (=_EmptyStream<T>;): Unhandled node
+mirrors/syntax_error_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/synthetic_accessor_properties_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/to_string_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/top_level_accessors_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/type_argument_is_type_variable_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/type_variable_owner_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/typearguments_mirror_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/typedef_deferred_library_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/typedef_reflected_type_test/none: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
+mirrors/unnamed_library_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
 typed_data/typed_data_list_test: RuntimeError # this.get$length is not a function
diff --git a/tests/lib/mirrors/static_const_field_test.dart b/tests/lib/mirrors/static_const_field_test.dart
new file mode 100644
index 0000000..f6fd959
--- /dev/null
+++ b/tests/lib/mirrors/static_const_field_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2013, 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.
+
+// Test that static const fields are accessible by reflection.
+// Regression test for http://dartbug.com/23811.
+
+@MirrorsUsed(targets: const [A])
+import "dart:mirrors";
+import "package:expect/expect.dart";
+
+class A {
+  static const ONE = 1;
+}
+
+main() {
+  Expect.equals(1, reflectClass(A).getField(#ONE).reflectee);
+}
diff --git a/tests/standalone/io/stdio_nonblocking_test.dart b/tests/standalone/io/stdio_nonblocking_test.dart
index 0740dbe..05f5fde 100644
--- a/tests/standalone/io/stdio_nonblocking_test.dart
+++ b/tests/standalone/io/stdio_nonblocking_test.dart
@@ -17,12 +17,7 @@
                   print(result.stdout);
                   print(result.stderr);
     Expect.equals(1, result.exitCode);
-    if (Platform.isWindows) {
-      Expect.equals('stdout\r\n\r\ntuodts\r\nABCDEFGHIJKLM\r\n', result.stdout);
-      Expect.equals('stderr\r\n\r\nrredts\r\nABCDEFGHIJKLM\r\n', result.stderr);
-    } else {
-      Expect.equals('stdout\n\ntuodts\nABCDEFGHIJKLM\n', result.stdout);
-      Expect.equals('stderr\n\nrredts\nABCDEFGHIJKLM\n', result.stderr);
-    }
+    Expect.equals('stdout\n\ntuodts\nABCDEFGHIJKLM\n', result.stdout);
+    Expect.equals('stderr\n\nrredts\nABCDEFGHIJKLM\n', result.stderr);
   });
 }
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 3dd8e64..e095467 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -173,12 +173,11 @@
 io/file_test: Crash # (static testWriteFro...  cannot handle async/sync*/async* functions
 io/file_write_only_test: Crash # (main()async{asyncSt...  cannot handle async/sync*/async* functions
 io/http_bind_test: Crash # (testBindShared(Stri...  cannot handle async/sync*/async* functions
-io/http_parser_test: RuntimeError # receiver.get$_nums is not a function
+io/http_parser_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
 io/https_bad_certificate_test: Crash # (main()async{var cli...  cannot handle async/sync*/async* functions
 io/issue_22636_test: Crash # (test()async{server=...  cannot handle async/sync*/async* functions
 io/issue_22637_test: Crash # (test()async{server=...  cannot handle async/sync*/async* functions
-io/observatory_test: Crash # (=_ByteCallbackSink;): Unhandled node
 io/socket_bind_test: Crash # (testListenCloseList...  cannot handle async/sync*/async* functions
 io/socket_source_address_test: Crash # (Future testConnect(...  cannot handle async/sync*/async* functions
-priority_queue_stress_test: RuntimeError # receiver.get$_nums is not a function
-typed_array_test: RuntimeError # receiver.get$_collection$_nums is not a function
+priority_queue_stress_test: RuntimeError # receiver._addHashTableEntry$2 is not a function
+typed_array_test: RuntimeError # receiver._collection$_addHashTableEntry$2 is not a function
diff --git a/tests/utils/utils.status b/tests/utils/utils.status
index d690ff9..c438459 100644
--- a/tests/utils/utils.status
+++ b/tests/utils/utils.status
@@ -31,4 +31,4 @@
 [ $compiler == dart2js && $cps_ir ]
 dummy_compiler_test: Crash # The null object does not have a getter '_element'.
 recursive_import_test: Crash # The null object does not have a getter '_element'.
-source_mirrors_test: Crash # (Future<bool> run(Ur...  cannot handle async/sync*/async* functions
+source_mirrors_test: Crash # The null object does not have a getter '_element'.
diff --git a/tools/VERSION b/tools/VERSION
index 3572a33..6cd4df1 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 1
 MINOR 12
 PATCH 0
-PRERELEASE 2
-PRERELEASE_PATCH 2
+PRERELEASE 3
+PRERELEASE_PATCH 0
diff --git a/tools/bots/bot_utils.py b/tools/bots/bot_utils.py
index 3646724..8262462 100644
--- a/tools/bots/bot_utils.py
+++ b/tools/bots/bot_utils.py
@@ -208,8 +208,7 @@
 
   def dartdocs_dirpath(self, revision):
     assert len('%s' % revision) > 0
-    return '%s/channels/%s/gen-dartdocs/%s' % (self.bucket, 
-                                               self.channel, revision)
+    return '%s/gen-dartdocs/%s' % (self.bucket, revision)
 
   def docs_latestpath(self, revision):
     assert len('%s' % revision) > 0
diff --git a/tools/dom/templates/html/dartium/indexed_db_dartium.darttemplate b/tools/dom/templates/html/dartium/indexed_db_dartium.darttemplate
index 0ac7e6f..256a12a 100644
--- a/tools/dom/templates/html/dartium/indexed_db_dartium.darttemplate
+++ b/tools/dom/templates/html/dartium/indexed_db_dartium.darttemplate
@@ -5,6 +5,78 @@
 // DO NOT EDIT
 // Auto-generated dart:indexed_db library.
 
+/**
+ * A client-side key-value store with support for indexes.
+ *
+ * Many browsers support IndexedDB&mdash;a web standard for
+ * an indexed database.
+ * By storing data on the client in an IndexedDB,
+ * a web app gets some advantages, such as faster performance and persistence.
+ * To find out which browsers support IndexedDB,
+ * refer to [Can I Use?](http://caniuse.com/#feat=indexeddb)
+ *
+ * In IndexedDB, each record is identified by a unique index or key,
+ * making data retrieval speedy.
+ * You can store structured data,
+ * such as images, arrays, and maps using IndexedDB.
+ * The standard does not specify size limits for individual data items
+ * or for the database itself, but browsers may impose storage limits.
+ *
+ * ## Using indexed_db
+ *
+ * The classes in this library provide an interface
+ * to the browser's IndexedDB, if it has one.
+ * To use this library in your code:
+ *
+ *     import 'dart:indexed_db';
+ *
+ * A web app can determine if the browser supports
+ * IndexedDB with [IdbFactory.supported]:
+ *
+ *     if (IdbFactory.supported)
+ *       // Use indexeddb.
+ *     else
+ *       // Find an alternative.
+ *
+ * Access to the browser's IndexedDB is provided by the app's top-level
+ * [Window] object, which your code can refer to with `window.indexedDB`.
+ * So, for example,
+ * here's how to use window.indexedDB to open a database:
+ *
+ *     Future open() {
+ *       return window.indexedDB.open('myIndexedDB',
+ *           version: 1,
+ *           onUpgradeNeeded: _initializeDatabase)
+ *         .then(_loadFromDB);
+ *     }
+ *     void _initializeDatabase(VersionChangeEvent e) {
+ *       ...
+ *     }
+ *     Future _loadFromDB(Database db) {
+ *       ...
+ *     }
+ *
+ *
+ * All data in an IndexedDB is stored within an [ObjectStore].
+ * To manipulate the database use [Transaction]s.
+ *
+ * ## Other resources
+ *
+ * Other options for client-side data storage include:
+ *
+ * * [Window.localStorage]&mdash;a
+ * basic mechanism that stores data as a [Map],
+ * and where both the keys and the values are strings.
+ *
+ * * [dart:web_sql]&mdash;a database that can be queried with SQL.
+ * 
+ * For a tutorial about using the indexed_db library with Dart,
+ * check out
+ * [Use IndexedDB](http://www.dartlang.org/docs/tutorials/indexeddb/).
+ *
+ * [IndexedDB reference](http://docs.webplatform.org/wiki/apis/indexeddb)
+ * provides wiki-style docs about indexedDB
+ */
 library dart.dom.indexed_db;
 
 import 'dart:async';