Version 1.18.0-dev.2.0

Merge '9eed0f74d4373d80261e29d09208409ef34b3ae9' into dev
diff --git a/DEPS b/DEPS
index d46d997..626a258 100644
--- a/DEPS
+++ b/DEPS
@@ -42,21 +42,21 @@
   "chrome_rev" : "@19997",
   "cli_util_tag" : "@0.0.1+2",
   "code_transformers_rev": "@bfe9799e88d9c231747435e1c1d2495ef5ecd966",
-  "collection_tag": "@1.6.0",
-  "convert_tag": "@1.0.0",
-  "crypto_tag" : "@1.1.1",
+  "collection_tag": "@1.8.0",
+  "convert_tag": "@2.0.0",
+  "crypto_tag" : "@2.0.1",
   "csslib_tag" : "@0.12.0",
   "dart2js_info_rev" : "@0a221eaf16aec3879c45719de656680ccb80d8a1",
   "dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
   "dart_style_tag": "@0.2.4",
-  "dartdoc_tag" : "@v0.9.0",
+  "dartdoc_tag" : "@v0.9.6",
   "dev_compiler_rev": "@7e9708eb5e9f3fcdc68b9af039d78cf39ce502b7",
   "fixnum_tag": "@0.10.5",
   "func_rev": "@8d4aea75c21be2179cb00dc2b94a71414653094e",
   "glob_rev": "@704cf75e4f26b417505c5c611bdaacd8808467dd",
   "html_tag" : "@0.12.1+1",
   "http_multi_server_tag" : "@2.0.0",
-  "http_parser_tag" : "@1.1.0",
+  "http_parser_tag" : "@3.0.2",
   "http_tag" : "@0.11.3+3",
   "http_throttle_rev" : "@a81f08be942cdd608883c7b67795c12226abc235",
   "idl_parser_rev": "@7fbe68cab90c38147dee4f48c30ad0d496c17915",
@@ -87,8 +87,8 @@
   "resource_rev":"@a49101ba2deb29c728acba6fb86000a8f730f4b1",
   "root_certificates_rev": "@aed07942ce98507d2be28cbd29e879525410c7fc",
   "scheduled_test_tag": "@0.12.5+2",
-  "shelf_static_tag": "@0.2.3+1",
-  "shelf_tag": "@0.6.5",
+  "shelf_static_tag": "@0.2.3+4",
+  "shelf_tag": "@0.6.5+2",
   "shelf_web_socket_tag": "@0.2.0",
   "smoke_rev" : "@f3361191cc2a85ebc1e4d4c33aec672d7915aba9",
   "source_map_stack_trace_tag": "@1.0.4",
@@ -100,13 +100,13 @@
   "string_scanner_tag": "@0.1.4",
   "sunflower_rev": "@879b704933413414679396b129f5dfa96f7a0b1e",
   "test_reflective_loader_tag": "@0.0.3",
-  "test_tag": "@0.12.13+1",
+  "test_tag": "@0.12.13+5",
   "typed_data_tag": "@1.1.2",
   "usage_rev": "@b5080dac0d26a5609b266f8fdb0d053bc4c1c638",
   "utf_rev": "@1f55027068759e2d52f2c12de6a57cce5f3c5ee6",
   "watcher_tag": "@0.9.7+2",
   "web_components_rev": "@6349e09f9118dce7ae1b309af5763745e25a9d61",
-  "web_socket_channel_tag": "@1.0.0",
+  "web_socket_channel_tag": "@1.0.4",
   "WebCore_rev": "@a86fe28efadcfc781f836037a80f27e22a5dad17",
   "when_tag": "@0.2.0+2",
   "which_tag": "@0.1.3+1",
diff --git a/pkg/analysis_server/benchmark/perf/benchmark_local.dart b/pkg/analysis_server/benchmark/perf/benchmark_local.dart
new file mode 100644
index 0000000..7b17591
--- /dev/null
+++ b/pkg/analysis_server/benchmark/perf/benchmark_local.dart
@@ -0,0 +1,195 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library server.performance.local;
+
+import 'package:analysis_server/plugin/protocol/protocol.dart';
+
+import 'benchmark_scenario.dart';
+
+main(List<String> args) async {
+  String pathRepository = args[0];
+  String pathServer = '$pathRepository/pkg/analysis_server';
+  String pathAnalyzer = '$pathRepository/pkg/analyzer';
+  {
+    String now = new DateTime.now().toUtc().toIso8601String();
+    print('Benchmark started: $now');
+    print('');
+    print('');
+  }
+
+  {
+    String id = 'local-initialAnalysis-1';
+    String description = r'''
+1. Start server, set 'analyzer' analysis root.
+2. Measure the time to finish initial analysis.
+3. Shutdown the server.
+4. Go to (1).
+''';
+    List<int> times = await BenchmarkScenario
+        .start_waitInitialAnalysis_shutdown(
+            roots: [pathAnalyzer], numOfRepeats: 3);
+    printBenchmarkResults(id, description, times);
+  }
+
+  {
+    String id = 'local-initialAnalysis-2';
+    String description = r'''
+1. Start server, set 'analyzer' and 'analysis_server' analysis roots.
+2. Measure the time to finish initial analysis.
+3. Shutdown the server.
+4. Go to (1).
+''';
+    List<int> times = await BenchmarkScenario
+        .start_waitInitialAnalysis_shutdown(
+            roots: [pathAnalyzer, pathServer], numOfRepeats: 3);
+    printBenchmarkResults(id, description, times);
+  }
+
+  {
+    String id = 'local-change-1';
+    String description = r'''
+1. Open 'analyzer'.
+2. Change a method body in src/task/dart.dart.
+3. Measure the time to finish analysis.
+4. Rollback changes to the file and wait for analysis.
+5. Go to (2).
+''';
+    List<int> times = await new BenchmarkScenario().waitAnalyze_change_analyze(
+        roots: [pathAnalyzer],
+        file: '$pathAnalyzer/lib/src/task/dart.dart',
+        fileChange: new FileChange(
+            afterStr: 'if (hasDirectiveChange) {', insertStr: 'print(12345);'),
+        numOfRepeats: 10);
+    printBenchmarkResults(id, description, times);
+  }
+
+  {
+    String id = 'local-change-2';
+    String description = r'''
+1. Open 'analyzer'.
+2. Change the name of a public method in src/task/dart.dart.
+3. Measure the time to finish analysis.
+4. Rollback changes to the file and wait for analysis.
+5. Go to (2).
+''';
+    List<int> times = await new BenchmarkScenario().waitAnalyze_change_analyze(
+        roots: [pathAnalyzer],
+        file: '$pathAnalyzer/lib/src/task/dart.dart',
+        fileChange: new FileChange(
+            afterStr: 'resolveDirective(An',
+            afterStrBack: 3,
+            insertStr: 'NewName'),
+        numOfRepeats: 5);
+    printBenchmarkResults(id, description, times);
+  }
+
+  {
+    String id = 'local-completion-1';
+    String description = r'''
+1. Open 'analyzer'.
+2. Change a method body in src/task/dart.dart.
+3. Request code completion in this method and measure time to get results.
+4. Rollback changes to the file and wait for analysis.
+5. Go to (2).
+''';
+    List<int> times = await new BenchmarkScenario()
+        .waitAnalyze_change_getCompletion(
+            roots: [pathAnalyzer],
+            file: '$pathAnalyzer/lib/src/task/dart.dart',
+            fileChange: new FileChange(
+                afterStr: 'if (hasDirectiveChange) {',
+                insertStr: 'print(12345);'),
+            completeAfterStr: 'print(12345);',
+            numOfRepeats: 10);
+    printBenchmarkResults(id, description, times);
+  }
+
+  {
+    String id = 'local-completion-2';
+    String description = r'''
+1. Open 'analyzer'.
+2. Change the name of a public method in src/task/dart.dart.
+3. Request code completion in this method and measure time to get results.
+4. Rollback changes to the file and wait for analysis.
+5. Go to (2).
+''';
+    List<int> times = await new BenchmarkScenario()
+        .waitAnalyze_change_getCompletion(
+            roots: [pathAnalyzer],
+            file: '$pathAnalyzer/lib/src/task/dart.dart',
+            fileChange: new FileChange(
+                afterStr: 'DeltaResult validate(In',
+                afterStrBack: 3,
+                insertStr: 'NewName'),
+            completeAfterStr: 'if (hasDirectiveChange) {',
+            numOfRepeats: 5);
+    printBenchmarkResults(id, description, times);
+  }
+
+  {
+    String id = 'local-completion-3';
+    String description = r'''
+1. Open 'analysis_server' and 'analyzer'.
+2. Change a method body in src/task/dart.dart.
+3. Request code completion in this method and measure time to get results.
+4. Rollback changes to the file and wait for analysis.
+5. Go to (2).
+''';
+    List<int> times = await new BenchmarkScenario()
+        .waitAnalyze_change_getCompletion(
+            roots: [pathServer, pathAnalyzer],
+            file: '$pathAnalyzer/lib/src/task/dart.dart',
+            fileChange: new FileChange(
+                afterStr: 'if (hasDirectiveChange) {',
+                insertStr: 'print(12345);'),
+            completeAfterStr: 'print(12345);',
+            numOfRepeats: 10);
+    printBenchmarkResults(id, description, times);
+  }
+
+  {
+    String id = 'local-completion-4';
+    String description = r'''
+1. Open 'analysis_server' and 'analyzer'.
+2. Change the name of a public method in src/task/dart.dart.
+3. Request code completion in this method and measure time to get results.
+4. Rollback changes to the file and wait for analysis.
+5. Go to (2).
+''';
+    List<int> times = await new BenchmarkScenario()
+        .waitAnalyze_change_getCompletion(
+            roots: [pathServer, pathAnalyzer],
+            file: '$pathAnalyzer/lib/src/task/dart.dart',
+            fileChange: new FileChange(
+                afterStr: 'DeltaResult validate(In',
+                afterStrBack: 3,
+                insertStr: 'NewName'),
+            completeAfterStr: 'if (hasDirectiveChange) {',
+            numOfRepeats: 5);
+    printBenchmarkResults(id, description, times);
+  }
+
+  {
+    String id = 'local-refactoring-1';
+    String description = r'''
+1. Open 'analyzer'.
+2. Change the name of a public method in src/context/cache.dart.
+3. Request rename refactoring for `getSourcesWithFullName` and measure time to get results.
+4. Rollback changes to the file and wait for analysis.
+5. Go to (2).
+''';
+    List<int> times = await new BenchmarkScenario()
+        .waitAnalyze_change_getRefactoring(
+            roots: [pathAnalyzer],
+            file: '$pathAnalyzer/lib/src/context/cache.dart',
+            fileChange: new FileChange(
+                afterStr: 'getState(An', afterStrBack: 3, insertStr: 'NewName'),
+            refactoringAtStr: 'getSourcesWithFullName(String path)',
+            refactoringKind: RefactoringKind.RENAME,
+            refactoringOptions: new RenameOptions('getSourcesWithFullName2'),
+            numOfRepeats: 5);
+    printBenchmarkResults(id, description, times);
+  }
+}
diff --git a/pkg/analysis_server/benchmark/perf/benchmark_scenario.dart b/pkg/analysis_server/benchmark/perf/benchmark_scenario.dart
new file mode 100644
index 0000000..aac844b
--- /dev/null
+++ b/pkg/analysis_server/benchmark/perf/benchmark_scenario.dart
@@ -0,0 +1,287 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library server.performance.scenarios;
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:analysis_server/plugin/protocol/protocol.dart';
+import 'package:unittest/unittest.dart';
+
+import 'performance_tests.dart';
+
+void printBenchmarkResults(String id, String description, List<int> times) {
+  String now = new DateTime.now().toUtc().toIso8601String();
+  print('$now ========== $id');
+  print('times: $times');
+  print(description.trim());
+  print('--------------------');
+  print('');
+  print('');
+}
+
+class BenchmarkScenario extends AbstractTimingTest {
+  /**
+   * Init.
+   *  - Start Analysis Server.
+   *  - Set the analysis [roots].
+   *  - Wait for analysis to complete.
+   *  - Make [file] the priority file.
+   *
+   * Measurement.
+   *  - Change the [file] according to the [fileChange].
+   *  - Record the time to finish analysis.
+   *
+   * Repeat.
+   *  - Undo changes to the [file].
+   *  - Repeat measurement [numOfRepeats] times.
+   */
+  Future<List<int>> waitAnalyze_change_analyze(
+      {List<String> roots,
+      String file,
+      FileChange fileChange,
+      int numOfRepeats}) async {
+    expect(roots, isNotNull, reason: 'roots');
+    expect(file, isNotNull, reason: 'file');
+    expect(fileChange, isNotNull, reason: 'fileChange');
+    expect(numOfRepeats, isNotNull, reason: 'numOfRepeats');
+    // Initialize Analysis Server.
+    await super.setUp();
+    await subscribeToStatusNotifications();
+    // Set roots and analyze.
+    await sendAnalysisSetAnalysisRoots(roots, []);
+    await analysisFinished;
+    // Make the file priority.
+    await sendAnalysisSetPriorityFiles([file]);
+    // Repeat.
+    List<int> times = <int>[];
+    for (int i = 0; i < numOfRepeats; i++) {
+      // Update and wait for analysis.
+      Stopwatch stopwatch = new Stopwatch()..start();
+      await _applyFileChange(file, fileChange);
+      await analysisFinished;
+      times.add(stopwatch.elapsed.inMilliseconds);
+      // Remove the overlay and analyze.
+      await sendAnalysisUpdateContent({file: new RemoveContentOverlay()});
+      await analysisFinished;
+    }
+    // Done.
+    await shutdown();
+    return times;
+  }
+
+  /**
+   * Init.
+   * 1. Start Analysis Server.
+   * 2. Set the analysis [roots].
+   * 3. Wait for analysis to complete.
+   * 4. Make [file] the priority file.
+   *
+   * Measurement.
+   * 5. Change the [file] according to the [fileChange].
+   * 6. Request [completeAfterStr] in the updated file content.
+   * 7. Record the time to get completion results.
+   * 8. Undo changes to the [file] and analyze.
+   * 9. Go to (5).
+   */
+  Future<List<int>> waitAnalyze_change_getCompletion(
+      {List<String> roots,
+      String file,
+      FileChange fileChange,
+      String completeAfterStr,
+      int numOfRepeats}) async {
+    expect(roots, isNotNull, reason: 'roots');
+    expect(file, isNotNull, reason: 'file');
+    expect(fileChange, isNotNull, reason: 'fileChange');
+    expect(completeAfterStr, isNotNull, reason: 'completeAfterStr');
+    expect(numOfRepeats, isNotNull, reason: 'numOfRepeats');
+    // Initialize Analysis Server.
+    await super.setUp();
+    await subscribeToStatusNotifications();
+    // Set roots and analyze.
+    await sendAnalysisSetAnalysisRoots(roots, []);
+    await analysisFinished;
+    // Make the file priority.
+    await sendAnalysisSetPriorityFiles([file]);
+    // Repeat.
+    List<int> times = <int>[];
+    for (int i = 0; i < numOfRepeats; i++) {
+      String updatedContent = await _applyFileChange(file, fileChange);
+      // Measure completion time.
+      int completionOffset =
+          _indexOfEnd(file, updatedContent, completeAfterStr);
+      Duration completionDuration =
+          await _measureCompletionTime(file, completionOffset);
+      times.add(completionDuration.inMilliseconds);
+      // Remove the overlay and analyze.
+      await sendAnalysisUpdateContent({file: new RemoveContentOverlay()});
+      await analysisFinished;
+    }
+    // Done.
+    await shutdown();
+    return times;
+  }
+
+  /**
+   * Init.
+   * 1. Start Analysis Server.
+   * 2. Set the analysis [roots].
+   * 3. Wait for analysis to complete.
+   * 4. Make [file] the priority file.
+   *
+   * Measurement.
+   * 5. Change the [file] according to the [fileChange].
+   * 6. Request [refactoringAtStr] in the updated file content.
+   * 7. Record the time to get refactoring.
+   * 8. Undo changes to the [file] and analyze.
+   * 9. Go to (5).
+   */
+  Future<List<int>> waitAnalyze_change_getRefactoring(
+      {List<String> roots,
+      String file,
+      FileChange fileChange,
+      String refactoringAtStr,
+      RefactoringKind refactoringKind,
+      RefactoringOptions refactoringOptions,
+      int numOfRepeats}) async {
+    expect(roots, isNotNull, reason: 'roots');
+    expect(file, isNotNull, reason: 'file');
+    expect(fileChange, isNotNull, reason: 'fileChange');
+    expect(refactoringAtStr, isNotNull, reason: 'refactoringAtStr');
+    expect(refactoringKind, isNotNull, reason: 'refactoringKind');
+    expect(refactoringOptions, isNotNull, reason: 'refactoringOptions');
+    expect(numOfRepeats, isNotNull, reason: 'numOfRepeats');
+    // Initialize Analysis Server.
+    await super.setUp();
+    await subscribeToStatusNotifications();
+    // Set roots and analyze.
+    await sendAnalysisSetAnalysisRoots(roots, []);
+    await analysisFinished;
+    // Make the file priority.
+    await sendAnalysisSetPriorityFiles([file]);
+    // Repeat.
+    List<int> times = <int>[];
+    for (int i = 0; i < numOfRepeats; i++) {
+      String updatedContent = await _applyFileChange(file, fileChange);
+      // Measure time to get refactoring.
+      int refactoringOffset = _indexOf(file, updatedContent, refactoringAtStr);
+      Duration refactoringDuration = await _measureRefactoringTime(
+          file, refactoringOffset, refactoringKind, refactoringOptions);
+      times.add(refactoringDuration.inMilliseconds);
+      // Remove the overlay and analyze.
+      await sendAnalysisUpdateContent({file: new RemoveContentOverlay()});
+      await analysisFinished;
+    }
+    // Done.
+    await shutdown();
+    return times;
+  }
+
+  /**
+   * Compute updated content of the [file] as described by [desc], add overlay
+   * for the [file], and return the updated content.
+   */
+  Future<String> _applyFileChange(String file, FileChange desc) async {
+    String originalContent = _getFileContent(file);
+    int offset = _indexOfEnd(file, originalContent, desc.afterStr);
+    offset -= desc.afterStrBack;
+    String updatedContent = originalContent.substring(0, offset) +
+        desc.insertStr +
+        originalContent.substring(offset);
+    await sendAnalysisUpdateContent(
+        {file: new AddContentOverlay(updatedContent)});
+    return updatedContent;
+  }
+
+  Future<Duration> _measureCompletionTime(String file, int offset) async {
+    Stopwatch stopwatch = new Stopwatch();
+    stopwatch.start();
+    Completer<Duration> completer = new Completer<Duration>();
+    var completionSubscription = onCompletionResults.listen((_) {
+      completer.complete(stopwatch.elapsed);
+    });
+    try {
+      await sendCompletionGetSuggestions(file, offset);
+      return await completer.future;
+    } finally {
+      completionSubscription.cancel();
+    }
+  }
+
+  Future<Duration> _measureRefactoringTime(
+      String file,
+      int offset,
+      RefactoringKind refactoringKind,
+      RefactoringOptions refactoringOptions) async {
+    Stopwatch stopwatch = new Stopwatch();
+    stopwatch.start();
+    await sendEditGetRefactoring(refactoringKind, file, offset, 0, false,
+        options: refactoringOptions);
+    return stopwatch.elapsed;
+  }
+
+  /**
+   *  1. Start Analysis Server.
+   *  2. Set the analysis [roots].
+   *  3. Wait for analysis to complete.
+   *  4. Record the time to finish analysis.
+   *  5. Shutdown.
+   *  6. Go to (1).
+   */
+  static Future<List<int>> start_waitInitialAnalysis_shutdown(
+      {List<String> roots, int numOfRepeats}) async {
+    expect(roots, isNotNull, reason: 'roots');
+    expect(numOfRepeats, isNotNull, reason: 'numOfRepeats');
+    // Repeat.
+    List<int> times = <int>[];
+    for (int i = 0; i < numOfRepeats; i++) {
+      BenchmarkScenario instance = new BenchmarkScenario();
+      // Initialize Analysis Server.
+      await instance.setUp();
+      await instance.subscribeToStatusNotifications();
+      // Set roots and analyze.
+      Stopwatch stopwatch = new Stopwatch()..start();
+      await instance.sendAnalysisSetAnalysisRoots(roots, []);
+      await instance.analysisFinished;
+      times.add(stopwatch.elapsed.inMilliseconds);
+      // Stop the server.
+      await instance.shutdown();
+    }
+    return times;
+  }
+
+  static String _getFileContent(String path) {
+    File file = new File(path);
+    expect(file.existsSync(), isTrue, reason: 'File $path does not exist.');
+    return file.readAsStringSync();
+  }
+
+  /**
+   * Return the index of [what] in [where] in the [file], fail if not found.
+   */
+  static int _indexOf(String file, String where, String what) {
+    int index = where.indexOf(what);
+    expect(index, isNot(-1), reason: 'Cannot find |$what| in $file.');
+    return index;
+  }
+
+  /**
+   * Return the end index if [what] in [where] in the [file], fail if not found.
+   */
+  static int _indexOfEnd(String file, String where, String what) {
+    return _indexOf(file, where, what) + what.length;
+  }
+}
+
+class FileChange {
+  final String afterStr;
+  final int afterStrBack;
+  final String insertStr;
+
+  FileChange({this.afterStr, this.afterStrBack: 0, this.insertStr}) {
+    expect(afterStr, isNotNull, reason: 'afterStr');
+    expect(insertStr, isNotNull, reason: 'insertStr');
+  }
+}
diff --git a/pkg/analysis_server/benchmark/perf/performance_tests.dart b/pkg/analysis_server/benchmark/perf/performance_tests.dart
index b784c0c..6d301c9 100644
--- a/pkg/analysis_server/benchmark/perf/performance_tests.dart
+++ b/pkg/analysis_server/benchmark/perf/performance_tests.dart
@@ -61,13 +61,11 @@
   Future shutdown() async => await shutdownIfNeeded();
 
   /**
-   * Enable [SERVER_STATUS] notifications so that [analysisFinished]
+   * Enable [ServerService.STATUS] notifications so that [analysisFinished]
    * can be used.
    */
-  Future subscribeToStatusNotifications() {
-    List<Future> futures = <Future>[];
-    futures.add(sendServerSetSubscriptions([ServerService.STATUS]));
-    return Future.wait(futures);
+  Future subscribeToStatusNotifications() async {
+    await sendServerSetSubscriptions([ServerService.STATUS]);
   }
 }
 
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 0c6b2dd..343d50b 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -61,7 +61,7 @@
 </style></head>
   <body>
     <h1>Analysis Server API Specification</h1>
-    <h1 style="color:#999999">Version 1.15.0</h1>
+    <h1 style="color:#999999">Version 1.16.0</h1>
     <p>
       This document contains a specification of the API provided by the
       analysis server.  The API in this document is currently under
@@ -305,6 +305,7 @@
   "event": "server.connected"
   "params": {
     "<b>version</b>": String
+    "<b>pid</b>": int
   }
 }</pre></div>
         <p>
@@ -321,7 +322,10 @@
       <h4>Parameters</h4><dl><dt class="field"><b><i>version ( String )</i></b></dt><dd>
             
             <p>The version number of the analysis server.</p>
-          </dd></dl></dd><dt class="notification"><a name="notification_server.error">server.error</a> (<a href="#notification_server.error">#</a>)</dt><dd><div class="box"><pre>notification: {
+          </dd><dt class="field"><b><i>pid ( int )</i></b></dt><dd>
+           
+           <p>The process id of the analysis server process.</p>
+         </dd></dl></dd><dt class="notification"><a name="notification_server.error">server.error</a> (<a href="#notification_server.error">#</a>)</dt><dd><div class="box"><pre>notification: {
   "event": "server.error"
   "params": {
     "<b>isFatal</b>": bool
diff --git a/pkg/analysis_server/lib/plugin/protocol/generated_protocol.dart b/pkg/analysis_server/lib/plugin/protocol/generated_protocol.dart
index c547af5..4b8fe8b 100644
--- a/pkg/analysis_server/lib/plugin/protocol/generated_protocol.dart
+++ b/pkg/analysis_server/lib/plugin/protocol/generated_protocol.dart
@@ -266,6 +266,7 @@
  *
  * {
  *   "version": String
+ *   "pid": int
  * }
  *
  * Clients may not extend, implement or mix-in this class.
@@ -273,6 +274,8 @@
 class ServerConnectedParams implements HasToJson {
   String _version;
 
+  int _pid;
+
   /**
    * The version number of the analysis server.
    */
@@ -286,8 +289,22 @@
     this._version = value;
   }
 
-  ServerConnectedParams(String version) {
+  /**
+   * The process id of the analysis server process.
+   */
+  int get pid => _pid;
+
+  /**
+   * The process id of the analysis server process.
+   */
+  void set pid(int value) {
+    assert(value != null);
+    this._pid = value;
+  }
+
+  ServerConnectedParams(String version, int pid) {
     this.version = version;
+    this.pid = pid;
   }
 
   factory ServerConnectedParams.fromJson(JsonDecoder jsonDecoder, String jsonPath, Object json) {
@@ -301,7 +318,13 @@
       } else {
         throw jsonDecoder.missingKey(jsonPath, "version");
       }
-      return new ServerConnectedParams(version);
+      int pid;
+      if (json.containsKey("pid")) {
+        pid = jsonDecoder.decodeInt(jsonPath + ".pid", json["pid"]);
+      } else {
+        throw jsonDecoder.missingKey(jsonPath, "pid");
+      }
+      return new ServerConnectedParams(version, pid);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "server.connected params", json);
     }
@@ -315,6 +338,7 @@
   Map<String, dynamic> toJson() {
     Map<String, dynamic> result = {};
     result["version"] = version;
+    result["pid"] = pid;
     return result;
   }
 
@@ -328,7 +352,8 @@
   @override
   bool operator==(other) {
     if (other is ServerConnectedParams) {
-      return version == other.version;
+      return version == other.version &&
+          pid == other.pid;
     }
     return false;
   }
@@ -337,6 +362,7 @@
   int get hashCode {
     int hash = 0;
     hash = JenkinsSmiHash.combine(hash, version.hashCode);
+    hash = JenkinsSmiHash.combine(hash, pid.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 }
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index ed02817..bda82af 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -7,6 +7,7 @@
 import 'dart:async';
 import 'dart:collection';
 import 'dart:core' hide Resource;
+import 'dart:io' as io;
 import 'dart:math' show max;
 
 import 'package:analysis_server/plugin/protocol/protocol.dart'
@@ -27,7 +28,6 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/plugin/embedded_resolver_provider.dart';
 import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:analyzer/source/embedder.dart';
 import 'package:analyzer/source/pub_package_map_provider.dart';
@@ -296,6 +296,12 @@
       new StreamController<ContextsChangedEvent>.broadcast();
 
   /**
+   * The file resolver provider used to override the way file URI's are
+   * resolved in some contexts.
+   */
+  ResolverProvider fileResolverProvider;
+
+  /**
    * Initialize a newly created server to receive requests from and send
    * responses to the given [channel].
    *
@@ -313,7 +319,7 @@
       this.options,
       this.defaultSdkCreator,
       this.instrumentationService,
-      {EmbeddedResolverProvider embeddedResolverProvider: null,
+      {ResolverProvider fileResolverProvider: null,
       ResolverProvider packageResolverProvider: null,
       bool useSingleContextManager: false,
       this.rethrowExceptions: true})
@@ -336,12 +342,12 @@
           resourceProvider,
           sdkManager,
           packageResolverProvider,
-          embeddedResolverProvider,
           packageMapProvider,
           analyzedFilesGlobs,
           instrumentationService,
           defaultContextOptions);
     }
+    this.fileResolverProvider = fileResolverProvider;
     ServerContextManagerCallbacks contextManagerCallbacks =
         new ServerContextManagerCallbacks(this, resourceProvider);
     contextManager.callbacks = contextManagerCallbacks;
@@ -360,7 +366,7 @@
     });
     _setupIndexInvalidation();
     Notification notification =
-        new ServerConnectedParams(VERSION).toNotification();
+        new ServerConnectedParams(VERSION, io.pid).toNotification();
     channel.sendNotification(notification);
     channel.listen(handleRequest, onDone: done, onError: error);
     handlers = serverPlugin.createDomains(this);
@@ -1559,13 +1565,14 @@
         AnalysisEngine.instance.createAnalysisContext();
     context.contentCache = analysisServer.overlayState;
     analysisServer.folderMap[folder] = context;
-    _locateEmbedderYamls(context, disposition);
+    context.fileResolverProvider = analysisServer.fileResolverProvider;
     context.sourceFactory =
         _createSourceFactory(context, options, disposition, folder);
     context.analysisOptions = options;
     analysisServer._onContextsChangedController
         .add(new ContextsChangedEvent(added: [context]));
     analysisServer.schedulePerformAnalysisOperation(context);
+
     return context;
   }
 
@@ -1626,48 +1633,27 @@
     List<UriResolver> packageUriResolvers =
         disposition.createPackageUriResolvers(resourceProvider);
 
-    EmbedderUriResolver embedderUriResolver;
-
-    // First check for a resolver provider.
-    ContextManager contextManager = analysisServer.contextManager;
-    if (contextManager is ContextManagerImpl) {
-      EmbeddedResolverProvider resolverProvider =
-          contextManager.embeddedUriResolverProvider;
-      if (resolverProvider != null) {
-        embedderUriResolver = resolverProvider(folder);
-      }
-    }
-
     // If no embedded URI resolver was provided, defer to a locator-backed one.
-    embedderUriResolver ??= new EmbedderUriResolver(
-        context.embedderYamlLocator.embedderYamls);
-    if (embedderUriResolver.length == 0) {
-      // The embedder uri resolver has no mappings. Use the default Dart SDK
-      // uri resolver.
+    EmbedderYamlLocator locator =
+        disposition.getEmbedderLocator(resourceProvider);
+    EmbedderSdk sdk = new EmbedderSdk(locator.embedderYamls);
+    if (sdk.libraryMap.size() == 0) {
+      // The embedder file has no mappings, so use the default Dart SDK.
       resolvers.add(new DartUriResolver(
           analysisServer.sdkManager.getSdkForOptions(options)));
     } else {
       // The embedder uri resolver has mappings, use it instead of the default
       // Dart SDK uri resolver.
-      resolvers.add(embedderUriResolver);
+      resolvers.add(new DartUriResolver(sdk));
     }
 
     resolvers.addAll(packageUriResolvers);
-    resolvers.add(new ResourceUriResolver(resourceProvider));
-    return new SourceFactory(resolvers, disposition.packages);
-  }
-
-  /// If [disposition] has a package map, attempt to locate `_embedder.yaml`
-  /// files.
-  void _locateEmbedderYamls(
-      InternalAnalysisContext context, FolderDisposition disposition) {
-    Map<String, List<Folder>> packageMap;
-    if (disposition is PackageMapDisposition) {
-      packageMap = disposition.packageMap;
-    } else if (disposition is PackagesFileDisposition) {
-      packageMap = disposition.buildPackageMap(resourceProvider);
+    if (context.fileResolverProvider == null) {
+      resolvers.add(new ResourceUriResolver(resourceProvider));
+    } else {
+      resolvers.add(context.fileResolverProvider(folder));
     }
-    context.embedderYamlLocator.refresh(packageMap);
+    return new SourceFactory(resolvers, disposition.packages);
   }
 }
 
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 44c3595..785ccfe 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -12,7 +12,6 @@
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/plugin/embedded_resolver_provider.dart';
 import 'package:analyzer/plugin/options.dart';
 import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:analyzer/source/analysis_options_provider.dart';
@@ -77,6 +76,11 @@
   String packageDescriptionPath;
 
   /**
+   * The folder disposition for this context.
+   */
+  final FolderDisposition disposition;
+
+  /**
    * Paths to files which determine the folder disposition and package map.
    *
    * TODO(paulberry): if any of these files are outside of [folder], they won't
@@ -97,7 +101,7 @@
   Map<String, Source> sources = new HashMap<String, Source>();
 
   ContextInfo(ContextManagerImpl contextManager, this.parent, Folder folder,
-      File packagespecFile, this.packageRoot)
+      File packagespecFile, this.packageRoot, this.disposition)
       : folder = folder,
         pathFilter = new PathFilter(
             folder.path, null, contextManager.resourceProvider.pathContext) {
@@ -111,7 +115,9 @@
    */
   ContextInfo._root()
       : folder = null,
-        pathFilter = null;
+        pathFilter = null,
+        packageRoot = null,
+        disposition = null;
 
   /**
    * Iterate through all [children] and their children, recursively.
@@ -408,13 +414,6 @@
   pathos.Context pathContext;
 
   /**
-   * A function that will return a [UriResolver] that can be used to resolve
-   * URI's for embedded libraries within a given folder, or `null` if we should
-   * fall back to the standard URI resolver.
-   */
-  final EmbeddedResolverProvider embeddedUriResolverProvider;
-
-  /**
    * The list of excluded paths (folders and files) most recently passed to
    * [setRoots].
    */
@@ -496,7 +495,6 @@
       this.resourceProvider,
       this.sdkManager,
       this.packageResolverProvider,
-      this.embeddedUriResolverProvider,
       this._packageMapProvider,
       this.analyzedFilesGlobs,
       this._instrumentationService,
@@ -592,13 +590,13 @@
       info.context.analysisOptions = new AnalysisOptionsImpl();
 
       // Apply inherited options.
-      options = _toStringMap(_getEmbeddedOptions(info.context));
+      options = _toStringMap(_getEmbeddedOptions(info));
       if (options != null) {
         configureContextOptions(info.context, options);
       }
     } else {
       // Check for embedded options.
-      Map embeddedOptions = _getEmbeddedOptions(info.context);
+      Map embeddedOptions = _getEmbeddedOptions(info);
       if (embeddedOptions != null) {
         options = _toStringMap(new Merger().merge(embeddedOptions, options));
       }
@@ -910,22 +908,19 @@
           // If there is no embedded URI resolver, a new source factory needs to
           // be recreated.
           if (sourceFactory is SourceFactoryImpl) {
-            if (!sourceFactory.resolvers
-                .any((UriResolver r) => r is EmbedderUriResolver)) {
-              // Get all but the dart: Uri resolver.
-              List<UriResolver> resolvers = sourceFactory.resolvers
-                  .where((r) => r is! DartUriResolver)
-                  .toList();
-              // Add an embedded URI resolver in its place.
-              resolvers.add(new EmbedderUriResolver(embedderYamls));
+            // Get all but the dart: Uri resolver.
+            List<UriResolver> resolvers = sourceFactory.resolvers
+                .where((r) => r is! DartUriResolver)
+                .toList();
+            // Add an embedded URI resolver in its place.
+            resolvers.add(new DartUriResolver(new EmbedderSdk(embedderYamls)));
 
-              // Set a new source factory.
-              SourceFactoryImpl newFactory = sourceFactory.clone();
-              newFactory.resolvers.clear();
-              newFactory.resolvers.addAll(resolvers);
-              info.context.sourceFactory = newFactory;
-              return;
-            }
+            // Set a new source factory.
+            SourceFactoryImpl newFactory = sourceFactory.clone();
+            newFactory.resolvers.clear();
+            newFactory.resolvers.addAll(resolvers);
+            info.context.sourceFactory = newFactory;
+            return;
           }
         }
 
@@ -1051,17 +1046,11 @@
    */
   ContextInfo _createContext(
       ContextInfo parent, Folder folder, File packagespecFile) {
-    ContextInfo info = new ContextInfo(this, parent, folder, packagespecFile,
-        normalizedPackageRoots[folder.path]);
-
-    FolderDisposition disposition;
     List<String> dependencies = <String>[];
-
-    // Next resort to a package uri resolver.
-    if (disposition == null) {
-      disposition =
-          _computeFolderDisposition(folder, dependencies.add, packagespecFile);
-    }
+    FolderDisposition disposition =
+        _computeFolderDisposition(folder, dependencies.add, packagespecFile);
+    ContextInfo info = new ContextInfo(this, parent, folder, packagespecFile,
+        normalizedPackageRoots[folder.path], disposition);
 
     Map<String, Object> optionMap = readOptions(info.folder);
     AnalysisOptions options =
@@ -1166,24 +1155,17 @@
     List<UriResolver> packageUriResolvers =
         disposition.createPackageUriResolvers(resourceProvider);
 
-    EmbedderUriResolver embedderUriResolver;
-
-    // First check for a resolver provider.
-    if (embeddedUriResolverProvider != null) {
-      embedderUriResolver = embeddedUriResolverProvider(folder);
-    }
-
-    // If no embedded URI resolver was provided, defer to a locator-backed one.
-    embedderUriResolver ??=
-        new EmbedderUriResolver(context.embedderYamlLocator.embedderYamls);
-    if (embedderUriResolver.length == 0) {
+    EmbedderYamlLocator locator =
+        disposition.getEmbedderLocator(resourceProvider);
+    EmbedderSdk sdk = new EmbedderSdk(locator.embedderYamls);
+    if (sdk.libraryMap.size() == 0) {
       // The embedder uri resolver has no mappings. Use the default Dart SDK
       // uri resolver.
       resolvers.add(new DartUriResolver(sdkManager.getSdkForOptions(options)));
     } else {
       // The embedder uri resolver has mappings, use it instead of the default
       // Dart SDK uri resolver.
-      resolvers.add(embedderUriResolver);
+      resolvers.add(new DartUriResolver(sdk));
     }
 
     resolvers.addAll(packageUriResolvers);
@@ -1263,29 +1245,26 @@
   /// skipped.
   ///
   /// Returns null if there are no embedded/configured options.
-  Map _getEmbeddedOptions(AnalysisContext context) {
-    Map embeddedOptions;
+  Map _getEmbeddedOptions(ContextInfo info) {
+    Map embeddedOptions = null;
+    EmbedderYamlLocator locator =
+        info.disposition.getEmbedderLocator(resourceProvider);
+    Iterable<YamlMap> maps = locator.embedderYamls.values;
+    if (maps.length == 1) {
+      embeddedOptions = maps.first;
+    }
 
-    if (context is InternalAnalysisContext) {
-      EmbedderYamlLocator locator = context.embedderYamlLocator;
-      Iterable<YamlMap> maps = locator.embedderYamls.values;
-      if (maps.length == 1) {
-        embeddedOptions = maps.first;
-      }
-
-      AnalysisConfiguration configuration = getConfiguration(context);
-      if (configuration != null) {
-        Map configMap = configuration.options;
-        if (configMap != null) {
-          if (embeddedOptions != null) {
-            embeddedOptions = new Merger().merge(embeddedOptions, configMap);
-          } else {
-            embeddedOptions = configMap;
-          }
+    AnalysisConfiguration configuration = getConfiguration(info.context);
+    if (configuration != null) {
+      Map configMap = configuration.options;
+      if (configMap != null) {
+        if (embeddedOptions != null) {
+          embeddedOptions = new Merger().merge(embeddedOptions, configMap);
+        } else {
+          embeddedOptions = configMap;
         }
       }
     }
-
     return embeddedOptions;
   }
 
@@ -1717,6 +1696,10 @@
   Iterable<UriResolver> createPackageUriResolvers(
           ResourceProvider resourceProvider) =>
       <UriResolver>[resolver];
+
+  @override
+  EmbedderYamlLocator getEmbedderLocator(ResourceProvider resourceProvider) =>
+      new EmbedderYamlLocator(null);
 }
 
 /**
@@ -1757,6 +1740,13 @@
    */
   Iterable<UriResolver> createPackageUriResolvers(
       ResourceProvider resourceProvider);
+
+  /**
+   * Return the locator used to locate the _embedder.yaml file used to configure
+   * the SDK. The [resourceProvider] is used to access the file system in cases
+   * where that is necessary.
+   */
+  EmbedderYamlLocator getEmbedderLocator(ResourceProvider resourceProvider);
 }
 
 /**
@@ -1776,6 +1766,10 @@
   Iterable<UriResolver> createPackageUriResolvers(
           ResourceProvider resourceProvider) =>
       const <UriResolver>[];
+
+  @override
+  EmbedderYamlLocator getEmbedderLocator(ResourceProvider resourceProvider) =>
+      new EmbedderYamlLocator(null);
 }
 
 /**
@@ -1785,6 +1779,8 @@
 class PackageMapDisposition extends FolderDisposition {
   final Map<String, List<Folder>> packageMap;
 
+  EmbedderYamlLocator _embedderLocator;
+
   @override
   final String packageRoot;
 
@@ -1800,6 +1796,14 @@
         new SdkExtUriResolver(packageMap),
         new PackageMapUriResolver(resourceProvider, packageMap)
       ];
+
+  @override
+  EmbedderYamlLocator getEmbedderLocator(ResourceProvider resourceProvider) {
+    if (_embedderLocator == null) {
+      _embedderLocator = new EmbedderYamlLocator(packageMap);
+    }
+    return _embedderLocator;
+  }
 }
 
 /**
@@ -1810,22 +1814,27 @@
   @override
   final Packages packages;
 
+  Map<String, List<Folder>> packageMap;
+
+  EmbedderYamlLocator _embedderLocator;
+
   PackagesFileDisposition(this.packages);
 
   @override
   String get packageRoot => null;
 
   Map<String, List<Folder>> buildPackageMap(ResourceProvider resourceProvider) {
-    Map<String, List<Folder>> packageMap = <String, List<Folder>>{};
-    if (packages == null) {
-      return packageMap;
-    }
-    packages.asMap().forEach((String name, Uri uri) {
-      if (uri.scheme == 'file' || uri.scheme == '' /* unspecified */) {
-        var path = resourceProvider.pathContext.fromUri(uri);
-        packageMap[name] = <Folder>[resourceProvider.getFolder(path)];
+    if (packageMap == null) {
+      packageMap = <String, List<Folder>>{};
+      if (packages != null) {
+        packages.asMap().forEach((String name, Uri uri) {
+          if (uri.scheme == 'file' || uri.scheme == '' /* unspecified */) {
+            var path = resourceProvider.pathContext.fromUri(uri);
+            packageMap[name] = <Folder>[resourceProvider.getFolder(path)];
+          }
+        });
       }
-    });
+    }
     return packageMap;
   }
 
@@ -1840,4 +1849,13 @@
       return const <UriResolver>[];
     }
   }
+
+  @override
+  EmbedderYamlLocator getEmbedderLocator(ResourceProvider resourceProvider) {
+    if (_embedderLocator == null) {
+      _embedderLocator =
+          new EmbedderYamlLocator(buildPackageMap(resourceProvider));
+    }
+    return _embedderLocator;
+  }
 }
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index d70517b..a70ecb7 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -19,7 +19,6 @@
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/instrumentation/file_instrumentation.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/plugin/embedded_resolver_provider.dart';
 import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/incremental_logger.dart';
@@ -298,10 +297,10 @@
   InstrumentationServer instrumentationServer;
 
   /**
-   * The embedded library URI resolver provider used to override the way
-   * embedded library URI's are resolved in some contexts.
+   * The file resolver provider used to override the way file URI's are
+   * resolved in some contexts.
    */
-  EmbeddedResolverProvider embeddedUriResolverProvider;
+  ResolverProvider fileResolverProvider;
 
   /**
    * The package resolver provider used to override the way package URI's are
@@ -446,7 +445,7 @@
         defaultSdk,
         service,
         serverPlugin,
-        embeddedUriResolverProvider,
+        fileResolverProvider,
         packageResolverProvider,
         useSingleContextManager);
     httpServer = new HttpAnalysisServer(socketServer);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/optype.dart b/pkg/analysis_server/lib/src/services/completion/dart/optype.dart
index 995ec27..917542c 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/optype.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/optype.dart
@@ -556,7 +556,7 @@
         if (node.parent is VariableDeclaration) {
           VariableDeclaration varDeclaration =
               node.parent as VariableDeclaration;
-          localTypeAssertion = varDeclaration.element.type;
+          localTypeAssertion = varDeclaration.element?.type;
         } else if (node.parent is AssignmentExpression) {
           AssignmentExpression assignmentExpression =
               node.parent as AssignmentExpression;
diff --git a/pkg/analysis_server/lib/src/socket_server.dart b/pkg/analysis_server/lib/src/socket_server.dart
index 1da32a1..380f3a8 100644
--- a/pkg/analysis_server/lib/src/socket_server.dart
+++ b/pkg/analysis_server/lib/src/socket_server.dart
@@ -11,7 +11,6 @@
 import 'package:analysis_server/src/services/index/index.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/plugin/embedded_resolver_provider.dart';
 import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:analyzer/source/pub_package_map_provider.dart';
 import 'package:analyzer/src/generated/sdk.dart';
@@ -35,7 +34,7 @@
   final DirectoryBasedDartSdk defaultSdk;
   final InstrumentationService instrumentationService;
   final ServerPlugin serverPlugin;
-  final EmbeddedResolverProvider embeddedResolverProvider;
+  final ResolverProvider fileResolverProvider;
   final ResolverProvider packageResolverProvider;
   final bool useSingleContextManager;
 
@@ -56,7 +55,7 @@
       this.defaultSdk,
       this.instrumentationService,
       this.serverPlugin,
-      this.embeddedResolverProvider,
+      this.fileResolverProvider,
       this.packageResolverProvider,
       this.useSingleContextManager);
 
@@ -100,7 +99,7 @@
         analysisServerOptions,
         defaultSdkCreator,
         instrumentationService,
-        embeddedResolverProvider: embeddedResolverProvider,
+        fileResolverProvider: fileResolverProvider,
         packageResolverProvider: packageResolverProvider,
         useSingleContextManager: useSingleContextManager,
         rethrowExceptions: false);
diff --git a/pkg/analysis_server/lib/starter.dart b/pkg/analysis_server/lib/starter.dart
index bb2f0f6..be8aba7 100644
--- a/pkg/analysis_server/lib/starter.dart
+++ b/pkg/analysis_server/lib/starter.dart
@@ -6,7 +6,6 @@
 
 import 'package:analysis_server/src/server/driver.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/plugin/embedded_resolver_provider.dart';
 import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:plugin/plugin.dart';
 
@@ -23,19 +22,18 @@
   factory ServerStarter() = Driver;
 
   /**
-   * Set the embedded resolver provider used to override the way embedded
-   * library URI's are resolved in some contexts. The provider should return
-   * `null` if the embedded library URI resolution scheme should be used
-   * instead.
-   */
-  void set embeddedUriResolverProvider(EmbeddedResolverProvider provider);
-
-  /**
    * Set the instrumentation [server] that is to be used by the analysis server.
    */
   void set instrumentationServer(InstrumentationServer server);
 
   /**
+   * Set the file resolver provider used to override the way file URI's
+   * are resolved in some contexts. The provider should return `null` if the
+   * default file resolution scheme should be used instead.
+   */
+  void set fileResolverProvider(ResolverProvider provider);
+
+  /**
    * Set the package resolver provider used to override the way package URI's
    * are resolved in some contexts. The provider should return `null` if the
    * default package resolution scheme should be used instead.
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index db85fcd..b6643de 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -9,6 +9,7 @@
 import 'package:analysis_server/src/context_manager.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/source/embedder.dart';
 import 'package:analyzer/source/error_processor.dart';
@@ -1738,8 +1739,6 @@
 
   UriResolver packageResolver = null;
 
-  UriResolver embeddedUriResolver = null;
-
   String projPath = '/my/proj';
 
   AnalysisError missing_required_param = new AnalysisError(
@@ -1815,9 +1814,6 @@
     manager.processPlugins(plugins);
   }
 
-  EmbedderUriResolver provideEmbeddedUriResolver(Folder folder) =>
-      embeddedUriResolver;
-
   UriResolver providePackageResolver(Folder folder) => packageResolver;
 
   void setUp() {
@@ -1831,7 +1827,6 @@
         resourceProvider,
         sdkManager,
         providePackageResolver,
-        provideEmbeddedUriResolver,
         packageMapProvider,
         analysisFilesGlobs,
         InstrumentationService.NULL_SERVICE,
@@ -2653,21 +2648,19 @@
     currentContextFilePaths[path] = <String, int>{};
     currentContextSources[path] = new HashSet<Source>();
     currentContext = AnalysisEngine.instance.createAnalysisContext();
-    _locateEmbedderYamls(currentContext, disposition);
     List<UriResolver> resolvers = [];
     if (currentContext is InternalAnalysisContext) {
       EmbedderYamlLocator embedderYamlLocator =
-          (currentContext as InternalAnalysisContext).embedderYamlLocator;
-      EmbedderUriResolver embedderUriResolver =
-          new EmbedderUriResolver(embedderYamlLocator.embedderYamls);
-      if (embedderUriResolver.length > 0) {
+          disposition.getEmbedderLocator(resourceProvider);
+      EmbedderSdk sdk = new EmbedderSdk(embedderYamlLocator.embedderYamls);
+      if (sdk.libraryMap.size() > 0) {
         // We have some embedder dart: uri mappings, add the resolver
         // to the list.
-        resolvers.add(embedderUriResolver);
+        resolvers.add(new DartUriResolver(sdk));
       }
     }
     resolvers.addAll(disposition.createPackageUriResolvers(resourceProvider));
-    resolvers.add(new FileUriResolver());
+    resolvers.add(new ResourceUriResolver(PhysicalResourceProvider.INSTANCE));
     currentContext.analysisOptions = options;
     currentContext.sourceFactory =
         new SourceFactory(resolvers, disposition.packages);
@@ -2740,19 +2733,6 @@
   void updateContextPackageUriResolver(AnalysisContext context) {
     // Nothing to do.
   }
-
-  /// If [disposition] has a package map, attempt to locate `_embedder.yaml`
-  /// files.
-  void _locateEmbedderYamls(
-      InternalAnalysisContext context, FolderDisposition disposition) {
-    Map<String, List<Folder>> packageMap;
-    if (disposition is PackageMapDisposition) {
-      packageMap = disposition.packageMap;
-    } else if (disposition is PackagesFileDisposition) {
-      packageMap = disposition.buildPackageMap(resourceProvider);
-    }
-    context.embedderYamlLocator.refresh(packageMap);
-  }
 }
 
 /**
diff --git a/pkg/analysis_server/test/integration/integration_test_methods.dart b/pkg/analysis_server/test/integration/integration_test_methods.dart
index 2508d56..1fbdd7e 100644
--- a/pkg/analysis_server/test/integration/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/integration_test_methods.dart
@@ -94,6 +94,10 @@
    * version ( String )
    *
    *   The version number of the analysis server.
+   *
+   * pid ( int )
+   *
+   *   The process id of the analysis server process.
    */
   Stream<ServerConnectedParams> onServerConnected;
 
diff --git a/pkg/analysis_server/test/integration/protocol_matchers.dart b/pkg/analysis_server/test/integration/protocol_matchers.dart
index 487d6a7..1443aa0 100644
--- a/pkg/analysis_server/test/integration/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/protocol_matchers.dart
@@ -65,11 +65,13 @@
  *
  * {
  *   "version": String
+ *   "pid": int
  * }
  */
 final Matcher isServerConnectedParams = new LazyMatcher(() => new MatchesJsonObject(
   "server.connected params", {
-    "version": isString
+    "version": isString,
+    "pid": isInt
   }));
 
 /**
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 644a1a9..7aa782a 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -6,7 +6,7 @@
   </head>
   <body>
     <h1>Analysis Server API Specification</h1>
-    <h1 style="color:#999999">Version <version>1.15.0</version></h1>
+    <h1 style="color:#999999">Version <version>1.16.0</version></h1>
     <p>
       This document contains a specification of the API provided by the
       analysis server.  The API in this document is currently under
@@ -239,6 +239,10 @@
             <ref>String</ref>
             <p>The version number of the analysis server.</p>
           </field>
+         <field name="pid">
+           <ref>int</ref>
+           <p>The process id of the analysis server process.</p>
+         </field>
         </params>
       </notification>
       <notification event="error">
diff --git a/pkg/analyzer/benchmark/errors_in_all_libraries.dart b/pkg/analyzer/benchmark/errors_in_all_libraries.dart
index 0d68c2f..6f02534 100644
--- a/pkg/analyzer/benchmark/errors_in_all_libraries.dart
+++ b/pkg/analyzer/benchmark/errors_in_all_libraries.dart
@@ -15,6 +15,8 @@
 import 'package:analyzer/src/generated/sdk_io.dart' show DirectoryBasedDartSdk;
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:path/path.dart' as p;
 
 void main(List<String> args) {
@@ -36,7 +38,7 @@
     var context = AnalysisEngine.instance.createAnalysisContext();
     context.sourceFactory = new SourceFactory([
       new DartUriResolver(DirectoryBasedDartSdk.defaultSdk),
-      new FileUriResolver(),
+      new ResourceUriResolver(PhysicalResourceProvider.INSTANCE),
       new PackageUriResolver([new JavaFile(packageRoot)])
     ]);
 
diff --git a/pkg/analyzer/example/resolver_driver.dart b/pkg/analyzer/example/resolver_driver.dart
index 3ba20f7..885a5225 100755
--- a/pkg/analyzer/example/resolver_driver.dart
+++ b/pkg/analyzer/example/resolver_driver.dart
@@ -14,6 +14,8 @@
 import 'package:analyzer/src/generated/sdk_io.dart' show DirectoryBasedDartSdk;
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/file_system/file_system.dart' hide File;
+import 'package:analyzer/file_system/physical_file_system.dart';
 
 void main(List<String> args) {
   print('working dir ${new File('.').resolveSymbolicLinksSync()}');
@@ -31,7 +33,10 @@
   JavaSystemIO.setProperty("com.google.dart.sdk", args[0]);
   DartSdk sdk = DirectoryBasedDartSdk.defaultSdk;
 
-  var resolvers = [new DartUriResolver(sdk), new FileUriResolver()];
+  var resolvers = [
+    new DartUriResolver(sdk),
+    new ResourceUriResolver(PhysicalResourceProvider.INSTANCE)
+  ];
 
   if (packageRoot != null) {
     var packageDirectory = new JavaFile(packageRoot);
diff --git a/pkg/analyzer/lib/analyzer.dart b/pkg/analyzer/lib/analyzer.dart
index c4642e8..59fea17 100644
--- a/pkg/analyzer/lib/analyzer.dart
+++ b/pkg/analyzer/lib/analyzer.dart
@@ -14,6 +14,8 @@
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/string_source.dart';
+import 'package:analyzer/file_system/file_system.dart' hide File;
+import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:path/path.dart' as pathos;
 
 export 'package:analyzer/dart/ast/ast.dart';
@@ -50,7 +52,8 @@
 CompilationUnit parseDartFile(String path,
     {bool suppressErrors: false, bool parseFunctionBodies: true}) {
   String contents = new File(path).readAsStringSync();
-  var sourceFactory = new SourceFactory([new FileUriResolver()]);
+  var sourceFactory = new SourceFactory(
+      [new ResourceUriResolver(PhysicalResourceProvider.INSTANCE)]);
 
   var absolutePath = pathos.absolute(path);
   var source = sourceFactory.forUri(pathos.toUri(absolutePath).toString());
diff --git a/pkg/analyzer/lib/file_system/file_system.dart b/pkg/analyzer/lib/file_system/file_system.dart
index 0acbc14..7a12c6f1c 100644
--- a/pkg/analyzer/lib/file_system/file_system.dart
+++ b/pkg/analyzer/lib/file_system/file_system.dart
@@ -219,7 +219,7 @@
   /**
    * The name of the `file` scheme.
    */
-  static String _FILE_SCHEME = "file";
+  static final String FILE_SCHEME = "file";
 
   final ResourceProvider _provider;
 
@@ -227,7 +227,7 @@
 
   @override
   Source resolveAbsolute(Uri uri, [Uri actualUri]) {
-    if (!_isFileUri(uri)) {
+    if (!isFileUri(uri)) {
       return null;
     }
     Resource resource =
@@ -242,8 +242,10 @@
   Uri restoreAbsolute(Source source) =>
       _provider.pathContext.toUri(source.fullName);
 
+  ResourceProvider get provider => _provider;
+
   /**
    * Return `true` if the given [uri] is a `file` URI.
    */
-  static bool _isFileUri(Uri uri) => uri.scheme == _FILE_SCHEME;
+  static bool isFileUri(Uri uri) => uri.scheme == FILE_SCHEME;
 }
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index 789095c..3391433 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -451,7 +451,7 @@
       return UriKind.PACKAGE_URI;
     } else if (scheme == DartUriResolver.DART_SCHEME) {
       return UriKind.DART_URI;
-    } else if (scheme == FileUriResolver.FILE_SCHEME) {
+    } else if (scheme == ResourceUriResolver.FILE_SCHEME) {
       return UriKind.FILE_URI;
     }
     return UriKind.FILE_URI;
diff --git a/pkg/analyzer/lib/plugin/embedded_resolver_provider.dart b/pkg/analyzer/lib/plugin/embedded_resolver_provider.dart
index b248e34..217ab7f 100644
--- a/pkg/analyzer/lib/plugin/embedded_resolver_provider.dart
+++ b/pkg/analyzer/lib/plugin/embedded_resolver_provider.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.
 
+@deprecated
 library analyzer.plugin.embedded_resolver_provider;
 
 import 'package:analyzer/file_system/file_system.dart';
@@ -12,4 +13,5 @@
  * URI's for embedded libraries within a given folder, or `null` if we should
  * fall back to the standard URI resolver.
  */
+@deprecated
 typedef EmbedderUriResolver EmbeddedResolverProvider(Folder folder);
diff --git a/pkg/analyzer/lib/source/embedder.dart b/pkg/analyzer/lib/source/embedder.dart
index 1b43e00..56abc6a 100644
--- a/pkg/analyzer/lib/source/embedder.dart
+++ b/pkg/analyzer/lib/source/embedder.dart
@@ -10,14 +10,13 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/source/package_map_provider.dart'
     show PackageMapProvider;
-import 'package:analyzer/src/context/context.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/java_io.dart' show JavaFile;
 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' show FileBasedSource;
+import 'package:analyzer/src/summary/idl.dart';
 import 'package:yaml/yaml.dart';
 
 const String _DART_COLON_PREFIX = 'dart:';
@@ -27,104 +26,28 @@
 bool definesEmbeddedLibs(Map map) => map[_EMBEDDED_LIB_MAP_KEY] != null;
 
 /// An SDK backed by URI mappings derived from an `_embedder.yaml` file.
-class EmbedderSdk implements DartSdk {
-  /// The resolver associated with this SDK.
-  EmbedderUriResolver _resolver;
-
-  /// The [AnalysisContext] used for this SDK's sources.
-  InternalAnalysisContext _analysisContext;
-
-  final LibraryMap _librariesMap = new LibraryMap();
-
+class EmbedderSdk extends AbstractDartSdk {
   final Map<String, String> _urlMappings = new HashMap<String, String>();
 
-  /// Analysis options for this SDK.
-  AnalysisOptions analysisOptions;
-
   EmbedderSdk([Map<Folder, YamlMap> embedderYamls]) {
     embedderYamls?.forEach(_processEmbedderYaml);
-    _resolver = new EmbedderUriResolver._forSdk(this);
   }
 
-  @override
-  AnalysisContext get context {
-    if (_analysisContext == null) {
-      _analysisContext = new SdkAnalysisContext(analysisOptions);
-      SourceFactory factory = new SourceFactory([_resolver]);
-      _analysisContext.sourceFactory = factory;
-
-      ChangeSet changeSet = new ChangeSet();
-      for (String uri in uris) {
-        changeSet.addedSource(factory.forUri(uri));
-      }
-      _analysisContext.applyChanges(changeSet);
-    }
-    return _analysisContext;
-  }
-
-  @override
-  List<SdkLibrary> get sdkLibraries => _librariesMap.sdkLibraries;
-
   // TODO(danrubel) Determine SDK version
   @override
   String get sdkVersion => '0';
 
-  @override
-  List<String> get uris => _librariesMap.uris;
-
   /// The url mappings for this SDK.
   Map<String, String> get urlMappings => _urlMappings;
 
   @override
-  Source fromFileUri(Uri uri) {
-    JavaFile file = new JavaFile.fromUri(uri);
-    String filePath = file.getAbsolutePath();
-
-    String path;
-    for (SdkLibrary library in _librariesMap.sdkLibraries) {
-      String libraryPath = library.path.replaceAll('/', JavaFile.separator);
-      if (filePath == libraryPath) {
-        path = library.shortName;
-        break;
-      }
-    }
-    if (path == null) {
-      for (SdkLibrary library in _librariesMap.sdkLibraries) {
-        String libraryPath = library.path.replaceAll('/', JavaFile.separator);
-        int index = libraryPath.lastIndexOf(JavaFile.separator);
-        if (index == -1) {
-          continue;
-        }
-        String prefix = libraryPath.substring(0, index + 1);
-        if (!filePath.startsWith(prefix)) {
-          continue;
-        }
-        var relPath = filePath
-            .substring(prefix.length)
-            .replaceAll(JavaFile.separator, '/');
-        path = '${library.shortName}/$relPath';
-        break;
-      }
-    }
-
-    if (path != null) {
-      try {
-        return new FileBasedSource(file, parseUriWithException(path));
-      } on URISyntaxException catch (exception, stackTrace) {
-        AnalysisEngine.instance.logger.logInformation(
-            "Failed to create URI: $path",
-            new CaughtException(exception, stackTrace));
-        return null;
-      }
-    }
-    return null;
-  }
+  String getRelativePathFromFile(JavaFile file) => file.getAbsolutePath();
 
   @override
-  SdkLibrary getSdkLibrary(String dartUri) => _librariesMap.getLibrary(dartUri);
+  PackageBundle getSummarySdkBundle(bool strongMode) => null;
 
   @override
-  Source mapDartUri(String dartUri) {
+  FileBasedSource internalMapDartUri(String dartUri) {
     String libraryName;
     String relativePath;
     int index = dartUri.indexOf('/');
@@ -173,7 +96,7 @@
     _urlMappings[name] = libPath;
     SdkLibraryImpl library = new SdkLibraryImpl(name);
     library.path = libPath;
-    _librariesMap.setLibrary(name, library);
+    libraryMap.setLibrary(name, library);
   }
 
   /// Given the 'embedderYamls' from [EmbedderYamlLocator] check each one for the
@@ -205,14 +128,27 @@
 ///
 /// If a key doesn't begin with `dart:` it is ignored.
 ///
+/// This class is deprecated; use DartUriResolver directly. In particular, if
+/// there used to be an instance creation of the form:
+///
+/// ```
+/// new EmbedderUriResolver(embedderMap)
+/// ```
+///
+/// This should be replaced by
+///
+/// ```
+/// new DartUriResolver(new EmbedderSdk(embedderMap))
+/// ```
+@deprecated
 class EmbedderUriResolver implements DartUriResolver {
   EmbedderSdk _embedderSdk;
   DartUriResolver _dartUriResolver;
 
   /// Construct a [EmbedderUriResolver] from a package map
   /// (see [PackageMapProvider]).
-  EmbedderUriResolver(Map<Folder, YamlMap> embedderMap) :
-      this._forSdk(new EmbedderSdk(embedderMap));
+  EmbedderUriResolver(Map<Folder, YamlMap> embedderMap)
+      : this._forSdk(new EmbedderSdk(embedderMap));
 
   /// (Provisional API.)
   EmbedderUriResolver._forSdk(this._embedderSdk) {
@@ -251,7 +187,7 @@
 
   EmbedderYamlLocator(Map<String, List<Folder>> packageMap) {
     if (packageMap != null) {
-      refresh(packageMap);
+      _processPackageMap(packageMap);
     }
   }
 
@@ -263,10 +199,9 @@
   void refresh(Map<String, List<Folder>> packageMap) {
     // Clear existing.
     embedderYamls.clear();
-    if (packageMap == null) {
-      return;
+    if (packageMap != null) {
+      _processPackageMap(packageMap);
     }
-    packageMap.forEach(_processPackage);
   }
 
   /// Given the yaml for an embedder ([embedderYaml]) and a folder
@@ -295,6 +230,10 @@
     }
   }
 
+  void _processPackageMap(Map<String, List<Folder>> packageMap) {
+    packageMap.forEach(_processPackage);
+  }
+
   /// Read the contents of [libDir]/[EMBEDDER_FILE_NAME] as a string.
   /// Returns null if the file doesn't exist.
   String _readEmbedderYaml(Folder libDir) {
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index 1cc85bc..dd0e0ee 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -11,6 +11,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
+import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:analyzer/plugin/task.dart';
 import 'package:analyzer/source/embedder.dart';
 import 'package:analyzer/src/cancelable_future.dart';
@@ -80,7 +81,10 @@
    */
   AnalysisOptionsImpl _options = new AnalysisOptionsImpl();
 
-  /// The embedder yaml locator for this context.
+  /**
+   * The embedder yaml locator for this context.
+   */
+  @deprecated
   EmbedderYamlLocator _embedderYamlLocator = new EmbedderYamlLocator(null);
 
   /**
@@ -225,6 +229,9 @@
    */
   CompilationUnit incrementalResolutionValidation_lastUnit;
 
+  @override
+  ResolverProvider fileResolverProvider;
+
   /**
    * Initialize a newly created analysis context.
    */
@@ -341,6 +348,7 @@
   @override
   DeclaredVariables get declaredVariables => _declaredVariables;
 
+  @deprecated
   @override
   EmbedderYamlLocator get embedderYamlLocator => _embedderYamlLocator;
 
@@ -1885,6 +1893,9 @@
               dartDelta.hasDirectiveChange = unitDelta.hasDirectiveChange;
               unitDelta.addedDeclarations.forEach(dartDelta.elementAdded);
               unitDelta.removedDeclarations.forEach(dartDelta.elementRemoved);
+              for (ClassElementDelta classDelta in unitDelta.classDeltas) {
+                dartDelta.elementChanged(classDelta.element);
+              }
 //              print(
 //                  'dartDelta: add=${dartDelta.addedNames} remove=${dartDelta.removedNames}');
               delta = dartDelta;
diff --git a/pkg/analyzer/lib/src/dart/ast/token.dart b/pkg/analyzer/lib/src/dart/ast/token.dart
index 9828113..baae1b8 100644
--- a/pkg/analyzer/lib/src/dart/ast/token.dart
+++ b/pkg/analyzer/lib/src/dart/ast/token.dart
@@ -569,5 +569,6 @@
   }
 
   @override
-  Token copy() => new TokenWithComment(type, offset, precedingComments);
+  Token copy() =>
+      new TokenWithComment(type, offset, copyComments(precedingComments));
 }
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index e3e379f..e2867a3 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -994,6 +994,37 @@
   AstNode _other;
 
   /**
+   * Notify that [first] and second have different length.
+   * This implementation returns `false`. Subclasses can override and throw.
+   */
+  bool failDifferentLength(List first, List second) {
+    return false;
+  }
+
+  /**
+   * Check whether [second] is null. Subclasses can override to throw.
+   */
+  bool failIfNotNull(Object first, Object second) {
+    return second == null;
+  }
+
+  /**
+   * Notify that [first] is not `null` while [second] one is `null`.
+   * This implementation returns `false`. Subclasses can override and throw.
+   */
+  bool failIsNull(Object first, Object second) {
+    return false;
+  }
+
+  /**
+   * Notify that [first] and [second] have different types.
+   * This implementation returns `false`. Subclasses can override and throw.
+   */
+  bool failRuntimeType(Object first, Object second) {
+    return false;
+  }
+
+  /**
    * Return `true` if the [first] node and the [second] node have the same
    * structure.
    *
@@ -1002,11 +1033,11 @@
    */
   bool isEqualNodes(AstNode first, AstNode second) {
     if (first == null) {
-      return second == null;
+      return failIfNotNull(first, second);
     } else if (second == null) {
-      return false;
+      return failIsNull(first, second);
     } else if (first.runtimeType != second.runtimeType) {
-      return false;
+      return failRuntimeType(first, second);
     }
     _other = second;
     return first.accept(this);
@@ -1021,17 +1052,24 @@
    */
   bool isEqualTokens(Token first, Token second) {
     if (first == null) {
-      return second == null;
+      return failIfNotNull(first, second);
     } else if (second == null) {
-      return false;
+      return failIsNull(first, second);
     } else if (identical(first, second)) {
       return true;
     }
-    return first.offset == second.offset &&
-        first.length == second.length &&
-        first.lexeme == second.lexeme;
+    return isEqualTokensNotNull(first, second);
   }
 
+  /**
+   * Return `true` if the [first] token and the [second] token have the same
+   * structure.  Both [first] and [second] are not `null`.
+   */
+  bool isEqualTokensNotNull(Token first, Token second) =>
+      first.offset == second.offset &&
+      first.length == second.length &&
+      first.lexeme == second.lexeme;
+
   @override
   bool visitAdjacentStrings(AdjacentStrings node) {
     AdjacentStrings other = _other as AdjacentStrings;
@@ -2016,13 +2054,13 @@
    */
   bool _isEqualNodeLists(NodeList first, NodeList second) {
     if (first == null) {
-      return second == null;
+      return failIfNotNull(first, second);
     } else if (second == null) {
-      return false;
+      return failIsNull(first, second);
     }
     int size = first.length;
     if (second.length != size) {
-      return false;
+      return failDifferentLength(first, second);
     }
     for (int i = 0; i < size; i++) {
       if (!isEqualNodes(first[i], second[i])) {
@@ -2039,7 +2077,7 @@
   bool _isEqualTokenLists(List<Token> first, List<Token> second) {
     int length = first.length;
     if (second.length != length) {
-      return false;
+      return failDifferentLength(first, second);
     }
     for (int i = 0; i < length; i++) {
       if (!isEqualTokens(first[i], second[i])) {
diff --git a/pkg/analyzer/lib/src/generated/bazel.dart b/pkg/analyzer/lib/src/generated/bazel.dart
new file mode 100644
index 0000000..8198f46
--- /dev/null
+++ b/pkg/analyzer/lib/src/generated/bazel.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.src.generated.bazel;
+
+import 'dart:core' hide Resource;
+
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+
+/**
+ * Instances of the class `BazelFileUriResolver` resolve `file` URI's by first
+ * resolving file uri's in the expected way, and then by looking in the
+ * corresponding generated directories.
+ */
+class BazelFileUriResolver extends ResourceUriResolver {
+  /**
+   * The Bazel workspace directory.
+   */
+  final Folder _workspaceDir;
+
+  /**
+   * The build directories that relative `file` URI's should use to resolve
+   * relative URIs.
+   */
+  final List<Folder> _buildDirectories;
+
+  BazelFileUriResolver(
+      ResourceProvider provider, this._workspaceDir, this._buildDirectories)
+      : super(provider);
+
+  @override
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
+    if (!ResourceUriResolver.isFileUri(uri)) {
+      return null;
+    }
+
+    File uriFile = provider.getFile(provider.pathContext.fromUri(uri));
+    if (uriFile.exists) {
+      return uriFile.createSource(actualUri ?? uri);
+    }
+
+    String relativeFromWorkspaceDir = _getPathFromWorkspaceDir(uri);
+    if (_buildDirectories.isEmpty || relativeFromWorkspaceDir.isEmpty) {
+      return null;
+    }
+
+    for (Folder buildDir in _buildDirectories) {
+      File file = buildDir.getChildAssumingFile(relativeFromWorkspaceDir);
+      if (file.exists) {
+        return file.createSource(actualUri ?? uri);
+      }
+    }
+    return null;
+  }
+
+  String _getPathFromWorkspaceDir(Uri uri) {
+    String uriPath = uri.path;
+    String workspacePath = _workspaceDir.path;
+
+    if (uriPath.startsWith(workspacePath) &&
+        workspacePath.length < uriPath.length) {
+      return uriPath.substring(workspacePath.length + 1);
+    }
+    return '';
+  }
+}
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 61816ab..4e67792 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -11,6 +11,7 @@
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
+import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:analyzer/source/embedder.dart';
 import 'package:analyzer/src/cancelable_future.dart';
 import 'package:analyzer/src/context/cache.dart';
@@ -332,6 +333,12 @@
   bool exists(Source source);
 
   /**
+   * The file resolver provider used to override the way file URI's are
+   * resolved in some contexts.
+   */
+  ResolverProvider fileResolverProvider;
+
+  /**
    * Return the element model corresponding to the compilation unit defined by
    * the given [unitSource] in the library defined by the given [librarySource],
    * or `null` if the element model does not currently exist or if the library
@@ -1965,7 +1972,10 @@
    */
   set contentCache(ContentCache value);
 
-  /// Get the [EmbedderYamlLocator] for this context.
+  /**
+   * Get the [EmbedderYamlLocator] for this context.
+   */
+  @deprecated
   EmbedderYamlLocator get embedderYamlLocator;
 
   /**
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolution_validator.dart b/pkg/analyzer/lib/src/generated/incremental_resolution_validator.dart
index 67885d1..518d6f6 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolution_validator.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolution_validator.dart
@@ -5,8 +5,10 @@
 library analyzer.src.generated.incremental_resolution_validator;
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 
@@ -16,9 +18,8 @@
  */
 void assertSameResolution(CompilationUnit actual, CompilationUnit expected,
     {bool validateTypes: false}) {
-  _SameResolutionValidator validator =
-      new _SameResolutionValidator(validateTypes, expected);
-  actual.accept(validator);
+  _SameResolutionValidator validator = new _SameResolutionValidator(validateTypes);
+  validator.isEqualNodes(expected, actual);
 }
 
 /**
@@ -33,808 +34,91 @@
   String toString() => "IncrementalResolutionMismatch: $message";
 }
 
-class _SameResolutionValidator implements AstVisitor {
+/**
+ * An [AstVisitor] that compares the structure of two [AstNode]s and their
+ * resolution to see whether they are equal.
+ */
+class _SameResolutionValidator extends AstComparator {
   final bool validateTypes;
 
-  /// The expected node to compare with the visited node.
-  AstNode other;
-
-  _SameResolutionValidator(this.validateTypes, this.other);
+  _SameResolutionValidator(this.validateTypes);
 
   @override
-  visitAdjacentStrings(AdjacentStrings node) {}
-
-  @override
-  visitAnnotation(Annotation node) {
-    Annotation other = this.other;
-    _visitNode(node.name, other.name);
-    _visitNode(node.constructorName, other.constructorName);
-    _visitNode(node.arguments, other.arguments);
-    _verifyElement(node.element, other.element);
-  }
-
-  @override
-  visitArgumentList(ArgumentList node) {
-    ArgumentList other = this.other;
-    _visitList(node.arguments, other.arguments);
-  }
-
-  @override
-  visitAsExpression(AsExpression node) {
-    AsExpression other = this.other;
-    _visitExpression(node, other);
-    _visitNode(node.expression, other.expression);
-    _visitNode(node.type, other.type);
-  }
-
-  @override
-  visitAssertStatement(AssertStatement node) {
-    AssertStatement other = this.other;
-    _visitNode(node.condition, other.condition);
-    _visitNode(node.message, other.message);
-  }
-
-  @override
-  visitAssignmentExpression(AssignmentExpression node) {
-    AssignmentExpression other = this.other;
-    _visitExpression(node, other);
-    _verifyElement(node.staticElement, other.staticElement);
-    _verifyElement(node.propagatedElement, other.propagatedElement);
-    _visitNode(node.leftHandSide, other.leftHandSide);
-    _visitNode(node.rightHandSide, other.rightHandSide);
-  }
-
-  @override
-  visitAwaitExpression(AwaitExpression node) {
-    AwaitExpression other = this.other;
-    _visitExpression(node, other);
-    _visitNode(node.expression, other.expression);
-  }
-
-  @override
-  visitBinaryExpression(BinaryExpression node) {
-    BinaryExpression other = this.other;
-    _visitExpression(node, other);
-    _verifyElement(node.staticElement, other.staticElement);
-    _verifyElement(node.propagatedElement, other.propagatedElement);
-    _visitNode(node.leftOperand, other.leftOperand);
-    _visitNode(node.rightOperand, other.rightOperand);
-  }
-
-  @override
-  visitBlock(Block node) {
-    Block other = this.other;
-    _visitList(node.statements, other.statements);
-  }
-
-  @override
-  visitBlockFunctionBody(BlockFunctionBody node) {
-    BlockFunctionBody other = this.other;
-    _visitNode(node.block, other.block);
-  }
-
-  @override
-  visitBooleanLiteral(BooleanLiteral node) {
-    BooleanLiteral other = this.other;
-    _visitExpression(node, other);
-  }
-
-  @override
-  visitBreakStatement(BreakStatement node) {
-    BreakStatement other = this.other;
-    _visitNode(node.label, other.label);
-  }
-
-  @override
-  visitCascadeExpression(CascadeExpression node) {
-    CascadeExpression other = this.other;
-    _visitExpression(node, other);
-    _visitNode(node.target, other.target);
-    _visitList(node.cascadeSections, other.cascadeSections);
-  }
-
-  @override
-  visitCatchClause(CatchClause node) {
-    CatchClause other = this.other;
-    _visitNode(node.exceptionType, other.exceptionType);
-    _visitNode(node.exceptionParameter, other.exceptionParameter);
-    _visitNode(node.stackTraceParameter, other.stackTraceParameter);
-    _visitNode(node.body, other.body);
-  }
-
-  @override
-  visitClassDeclaration(ClassDeclaration node) {
-    ClassDeclaration other = this.other;
-    _visitDeclaration(node, other);
-    _visitNode(node.name, other.name);
-    _visitNode(node.typeParameters, other.typeParameters);
-    _visitNode(node.extendsClause, other.extendsClause);
-    _visitNode(node.implementsClause, other.implementsClause);
-    _visitNode(node.withClause, other.withClause);
-    _visitList(node.members, other.members);
-  }
-
-  @override
-  visitClassTypeAlias(ClassTypeAlias node) {
-    ClassTypeAlias other = this.other;
-    _visitDeclaration(node, other);
-    _visitNode(node.name, other.name);
-    _visitNode(node.typeParameters, other.typeParameters);
-    _visitNode(node.superclass, other.superclass);
-    _visitNode(node.withClause, other.withClause);
-  }
-
-  @override
-  visitComment(Comment node) {
-    Comment other = this.other;
-    _visitList(node.references, other.references);
-  }
-
-  @override
-  visitCommentReference(CommentReference node) {
-    CommentReference other = this.other;
-    _visitNode(node.identifier, other.identifier);
-  }
-
-  @override
-  visitCompilationUnit(CompilationUnit node) {
-    CompilationUnit other = this.other;
-    _verifyElement(node.element, other.element);
-    _visitList(node.directives, other.directives);
-    _visitList(node.declarations, other.declarations);
-  }
-
-  @override
-  visitConditionalExpression(ConditionalExpression node) {
-    ConditionalExpression other = this.other;
-    _visitExpression(node, other);
-    _visitNode(node.condition, other.condition);
-    _visitNode(node.thenExpression, other.thenExpression);
-    _visitNode(node.elseExpression, other.elseExpression);
-  }
-
-  @override
-  visitConfiguration(Configuration node) {
-    Configuration other = this.other;
-    _visitNode(node.name, other.name);
-    _visitNode(node.value, other.value);
-    _visitNode(node.libraryUri, other.libraryUri);
-  }
-
-  @override
-  visitConstructorDeclaration(ConstructorDeclaration node) {
-    ConstructorDeclaration other = this.other;
-    _visitDeclaration(node, other);
-    _visitNode(node.returnType, other.returnType);
-    _visitNode(node.name, other.name);
-    _visitNode(node.parameters, other.parameters);
-    _visitNode(node.redirectedConstructor, other.redirectedConstructor);
-    _visitList(node.initializers, other.initializers);
-  }
-
-  @override
-  visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
-    ConstructorFieldInitializer other = this.other;
-    _visitNode(node.fieldName, other.fieldName);
-    _visitNode(node.expression, other.expression);
-  }
-
-  @override
-  visitConstructorName(ConstructorName node) {
-    ConstructorName other = this.other;
-    _verifyElement(node.staticElement, other.staticElement);
-    _visitNode(node.type, other.type);
-    _visitNode(node.name, other.name);
-  }
-
-  @override
-  visitContinueStatement(ContinueStatement node) {
-    ContinueStatement other = this.other;
-    _visitNode(node.label, other.label);
-  }
-
-  @override
-  visitDeclaredIdentifier(DeclaredIdentifier node) {
-    DeclaredIdentifier other = this.other;
-    _visitNode(node.type, other.type);
-    _visitNode(node.identifier, other.identifier);
-  }
-
-  @override
-  visitDefaultFormalParameter(DefaultFormalParameter node) {
-    DefaultFormalParameter other = this.other;
-    _visitNode(node.parameter, other.parameter);
-    _visitNode(node.defaultValue, other.defaultValue);
-  }
-
-  @override
-  visitDoStatement(DoStatement node) {
-    DoStatement other = this.other;
-    _visitNode(node.condition, other.condition);
-    _visitNode(node.body, other.body);
-  }
-
-  @override
-  visitDottedName(DottedName node) {
-    DottedName other = this.other;
-    _visitList(node.components, other.components);
-  }
-
-  @override
-  visitDoubleLiteral(DoubleLiteral node) {
-    DoubleLiteral other = this.other;
-    _visitExpression(node, other);
-  }
-
-  @override
-  visitEmptyFunctionBody(EmptyFunctionBody node) {}
-
-  @override
-  visitEmptyStatement(EmptyStatement node) {}
-
-  @override
-  visitEnumConstantDeclaration(EnumConstantDeclaration node) {
-    EnumConstantDeclaration other = this.other;
-    _visitDeclaration(node, other);
-    _visitNode(node.name, other.name);
-  }
-
-  @override
-  visitEnumDeclaration(EnumDeclaration node) {
-    EnumDeclaration other = this.other;
-    _visitDeclaration(node, other);
-    _visitNode(node.name, other.name);
-    _visitList(node.constants, other.constants);
-  }
-
-  @override
-  visitExportDirective(ExportDirective node) {
-    ExportDirective other = this.other;
-    _visitDirective(node, other);
-  }
-
-  @override
-  visitExpressionFunctionBody(ExpressionFunctionBody node) {
-    ExpressionFunctionBody other = this.other;
-    _visitNode(node.expression, other.expression);
-  }
-
-  @override
-  visitExpressionStatement(ExpressionStatement node) {
-    ExpressionStatement other = this.other;
-    _visitNode(node.expression, other.expression);
-  }
-
-  @override
-  visitExtendsClause(ExtendsClause node) {
-    ExtendsClause other = this.other;
-    _visitNode(node.superclass, other.superclass);
-  }
-
-  @override
-  visitFieldDeclaration(FieldDeclaration node) {
-    FieldDeclaration other = this.other;
-    _visitDeclaration(node, other);
-    _visitNode(node.fields, other.fields);
-  }
-
-  @override
-  visitFieldFormalParameter(FieldFormalParameter node) {
-    FieldFormalParameter other = this.other;
-    _visitNormalFormalParameter(node, other);
-    _visitNode(node.type, other.type);
-    _visitNode(node.parameters, other.parameters);
-  }
-
-  @override
-  visitForEachStatement(ForEachStatement node) {
-    ForEachStatement other = this.other;
-    _visitNode(node.identifier, other.identifier);
-    _visitNode(node.loopVariable, other.loopVariable);
-    _visitNode(node.iterable, other.iterable);
-  }
-
-  @override
-  visitFormalParameterList(FormalParameterList node) {
-    FormalParameterList other = this.other;
-    _visitList(node.parameters, other.parameters);
-  }
-
-  @override
-  visitForStatement(ForStatement node) {
-    ForStatement other = this.other;
-    _visitNode(node.variables, other.variables);
-    _visitNode(node.initialization, other.initialization);
-    _visitNode(node.condition, other.condition);
-    _visitList(node.updaters, other.updaters);
-    _visitNode(node.body, other.body);
-  }
-
-  @override
-  visitFunctionDeclaration(FunctionDeclaration node) {
-    FunctionDeclaration other = this.other;
-    _visitDeclaration(node, other);
-    _visitNode(node.returnType, other.returnType);
-    _visitNode(node.name, other.name);
-    _visitNode(node.functionExpression, other.functionExpression);
-  }
-
-  @override
-  visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
-    FunctionDeclarationStatement other = this.other;
-    _visitNode(node.functionDeclaration, other.functionDeclaration);
-  }
-
-  @override
-  visitFunctionExpression(FunctionExpression node) {
-    FunctionExpression other = this.other;
-    _visitExpression(node, other);
-    _verifyElement(node.element, other.element);
-    _visitNode(node.parameters, other.parameters);
-    _visitNode(node.body, other.body);
-  }
-
-  @override
-  visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
-    FunctionExpressionInvocation other = this.other;
-    _visitExpression(node, other);
-    _verifyElement(node.staticElement, other.staticElement);
-    _verifyElement(node.propagatedElement, other.propagatedElement);
-    _visitNode(node.function, other.function);
-    _visitNode(node.argumentList, other.argumentList);
-  }
-
-  @override
-  visitFunctionTypeAlias(FunctionTypeAlias node) {
-    FunctionTypeAlias other = this.other;
-    _visitDeclaration(node, other);
-    _visitNode(node.returnType, other.returnType);
-    _visitNode(node.name, other.name);
-    _visitNode(node.typeParameters, other.typeParameters);
-    _visitNode(node.parameters, other.parameters);
-  }
-
-  @override
-  visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
-    FunctionTypedFormalParameter other = this.other;
-    _visitNormalFormalParameter(node, other);
-    _visitNode(node.returnType, other.returnType);
-    _visitNode(node.parameters, other.parameters);
-  }
-
-  @override
-  visitHideCombinator(HideCombinator node) {
-    HideCombinator other = this.other;
-    _visitList(node.hiddenNames, other.hiddenNames);
-  }
-
-  @override
-  visitIfStatement(IfStatement node) {
-    IfStatement other = this.other;
-    _visitNode(node.condition, other.condition);
-    _visitNode(node.thenStatement, other.thenStatement);
-    _visitNode(node.elseStatement, other.elseStatement);
-  }
-
-  @override
-  visitImplementsClause(ImplementsClause node) {
-    ImplementsClause other = this.other;
-    _visitList(node.interfaces, other.interfaces);
-  }
-
-  @override
-  visitImportDirective(ImportDirective node) {
-    ImportDirective other = this.other;
-    _visitDirective(node, other);
-    _visitNode(node.prefix, other.prefix);
-    _verifyElement(node.uriElement, other.uriElement);
-  }
-
-  @override
-  visitIndexExpression(IndexExpression node) {
-    IndexExpression other = this.other;
-    _visitExpression(node, other);
-    _verifyElement(node.staticElement, other.staticElement);
-    _verifyElement(node.propagatedElement, other.propagatedElement);
-    _visitNode(node.target, other.target);
-    _visitNode(node.index, other.index);
-  }
-
-  @override
-  visitInstanceCreationExpression(InstanceCreationExpression node) {
-    InstanceCreationExpression other = this.other;
-    _visitExpression(node, other);
-    _verifyElement(node.staticElement, other.staticElement);
-    _visitNode(node.constructorName, other.constructorName);
-    _visitNode(node.argumentList, other.argumentList);
-  }
-
-  @override
-  visitIntegerLiteral(IntegerLiteral node) {
-    IntegerLiteral other = this.other;
-    _visitExpression(node, other);
-  }
-
-  @override
-  visitInterpolationExpression(InterpolationExpression node) {
-    InterpolationExpression other = this.other;
-    _visitNode(node.expression, other.expression);
-  }
-
-  @override
-  visitInterpolationString(InterpolationString node) {}
-
-  @override
-  visitIsExpression(IsExpression node) {
-    IsExpression other = this.other;
-    _visitExpression(node, other);
-    _visitNode(node.expression, other.expression);
-    _visitNode(node.type, other.type);
-  }
-
-  @override
-  visitLabel(Label node) {
-    Label other = this.other;
-    _visitNode(node.label, other.label);
-  }
-
-  @override
-  visitLabeledStatement(LabeledStatement node) {
-    LabeledStatement other = this.other;
-    _visitList(node.labels, other.labels);
-    _visitNode(node.statement, other.statement);
-  }
-
-  @override
-  visitLibraryDirective(LibraryDirective node) {
-    LibraryDirective other = this.other;
-    _visitDirective(node, other);
-    _visitNode(node.name, other.name);
-  }
-
-  @override
-  visitLibraryIdentifier(LibraryIdentifier node) {
-    LibraryIdentifier other = this.other;
-    _visitList(node.components, other.components);
-  }
-
-  @override
-  visitListLiteral(ListLiteral node) {
-    ListLiteral other = this.other;
-    _visitExpression(node, other);
-    _visitList(node.elements, other.elements);
-  }
-
-  @override
-  visitMapLiteral(MapLiteral node) {
-    MapLiteral other = this.other;
-    _visitExpression(node, other);
-    _visitList(node.entries, other.entries);
-  }
-
-  @override
-  visitMapLiteralEntry(MapLiteralEntry node) {
-    MapLiteralEntry other = this.other;
-    _visitNode(node.key, other.key);
-    _visitNode(node.value, other.value);
-  }
-
-  @override
-  visitMethodDeclaration(MethodDeclaration node) {
-    MethodDeclaration other = this.other;
-    _visitDeclaration(node, other);
-    _visitNode(node.name, other.name);
-    _visitNode(node.parameters, other.parameters);
-    _visitNode(node.body, other.body);
-  }
-
-  @override
-  visitMethodInvocation(MethodInvocation node) {
-    MethodInvocation other = this.other;
-    _visitNode(node.target, other.target);
-    _visitNode(node.methodName, other.methodName);
-    _visitNode(node.argumentList, other.argumentList);
-  }
-
-  @override
-  visitNamedExpression(NamedExpression node) {
-    NamedExpression other = this.other;
-    _visitNode(node.name, other.name);
-    _visitNode(node.expression, other.expression);
-  }
-
-  @override
-  visitNativeClause(NativeClause node) {}
-
-  @override
-  visitNativeFunctionBody(NativeFunctionBody node) {}
-
-  @override
-  visitNullLiteral(NullLiteral node) {
-    NullLiteral other = this.other;
-    _visitExpression(node, other);
-  }
-
-  @override
-  visitParenthesizedExpression(ParenthesizedExpression node) {
-    ParenthesizedExpression other = this.other;
-    _visitNode(node.expression, other.expression);
-  }
-
-  @override
-  visitPartDirective(PartDirective node) {
-    PartDirective other = this.other;
-    _visitDirective(node, other);
-  }
-
-  @override
-  visitPartOfDirective(PartOfDirective node) {
-    PartOfDirective other = this.other;
-    _visitDirective(node, other);
-    _visitNode(node.libraryName, other.libraryName);
-  }
-
-  @override
-  visitPostfixExpression(PostfixExpression node) {
-    PostfixExpression other = this.other;
-    _visitExpression(node, other);
-    _verifyElement(node.staticElement, other.staticElement);
-    _verifyElement(node.propagatedElement, other.propagatedElement);
-    _visitNode(node.operand, other.operand);
-  }
-
-  @override
-  visitPrefixedIdentifier(PrefixedIdentifier node) {
-    PrefixedIdentifier other = this.other;
-    _visitExpression(node, other);
-    _visitNode(node.prefix, other.prefix);
-    _visitNode(node.identifier, other.identifier);
-  }
-
-  @override
-  visitPrefixExpression(PrefixExpression node) {
-    PrefixExpression other = this.other;
-    _visitExpression(node, other);
-    _verifyElement(node.staticElement, other.staticElement);
-    _verifyElement(node.propagatedElement, other.propagatedElement);
-    _visitNode(node.operand, other.operand);
-  }
-
-  @override
-  visitPropertyAccess(PropertyAccess node) {
-    PropertyAccess other = this.other;
-    _visitExpression(node, other);
-    _visitNode(node.target, other.target);
-    _visitNode(node.propertyName, other.propertyName);
-  }
-
-  @override
-  visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
-    RedirectingConstructorInvocation other = this.other;
-    _verifyElement(node.staticElement, other.staticElement);
-    _visitNode(node.constructorName, other.constructorName);
-    _visitNode(node.argumentList, other.argumentList);
-  }
-
-  @override
-  visitRethrowExpression(RethrowExpression node) {
-    RethrowExpression other = this.other;
-    _visitExpression(node, other);
-  }
-
-  @override
-  visitReturnStatement(ReturnStatement node) {
-    ReturnStatement other = this.other;
-    _visitNode(node.expression, other.expression);
-  }
-
-  @override
-  visitScriptTag(ScriptTag node) {}
-
-  @override
-  visitShowCombinator(ShowCombinator node) {
-    ShowCombinator other = this.other;
-    _visitList(node.shownNames, other.shownNames);
-  }
-
-  @override
-  visitSimpleFormalParameter(SimpleFormalParameter node) {
-    SimpleFormalParameter other = this.other;
-    _visitNormalFormalParameter(node, other);
-    _visitNode(node.type, other.type);
-  }
-
-  @override
-  visitSimpleIdentifier(SimpleIdentifier node) {
-    SimpleIdentifier other = this.other;
-    _verifyElement(node.staticElement, other.staticElement);
-    _verifyElement(node.propagatedElement, other.propagatedElement);
-    _visitExpression(node, other);
-  }
-
-  @override
-  visitSimpleStringLiteral(SimpleStringLiteral node) {}
-
-  @override
-  visitStringInterpolation(StringInterpolation node) {
-    StringInterpolation other = this.other;
-    _visitList(node.elements, other.elements);
-  }
-
-  @override
-  visitSuperConstructorInvocation(SuperConstructorInvocation node) {
-    SuperConstructorInvocation other = this.other;
-    _verifyElement(node.staticElement, other.staticElement);
-    _visitNode(node.constructorName, other.constructorName);
-    _visitNode(node.argumentList, other.argumentList);
-  }
-
-  @override
-  visitSuperExpression(SuperExpression node) {
-    SuperExpression other = this.other;
-    _visitExpression(node, other);
-  }
-
-  @override
-  visitSwitchCase(SwitchCase node) {
-    SwitchCase other = this.other;
-    _visitList(node.labels, other.labels);
-    _visitNode(node.expression, other.expression);
-    _visitList(node.statements, other.statements);
-  }
-
-  @override
-  visitSwitchDefault(SwitchDefault node) {
-    SwitchDefault other = this.other;
-    _visitList(node.statements, other.statements);
-  }
-
-  @override
-  visitSwitchStatement(SwitchStatement node) {
-    SwitchStatement other = this.other;
-    _visitNode(node.expression, other.expression);
-    _visitList(node.members, other.members);
-  }
-
-  @override
-  visitSymbolLiteral(SymbolLiteral node) {}
-
-  @override
-  visitThisExpression(ThisExpression node) {
-    ThisExpression other = this.other;
-    _visitExpression(node, other);
-  }
-
-  @override
-  visitThrowExpression(ThrowExpression node) {
-    ThrowExpression other = this.other;
-    _visitNode(node.expression, other.expression);
-  }
-
-  @override
-  visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
-    TopLevelVariableDeclaration other = this.other;
-    _visitNode(node.variables, other.variables);
-  }
-
-  @override
-  visitTryStatement(TryStatement node) {
-    TryStatement other = this.other;
-    _visitNode(node.body, other.body);
-    _visitList(node.catchClauses, other.catchClauses);
-    _visitNode(node.finallyBlock, other.finallyBlock);
-  }
-
-  @override
-  visitTypeArgumentList(TypeArgumentList node) {
-    TypeArgumentList other = this.other;
-    _visitList(node.arguments, other.arguments);
-  }
-
-  @override
-  visitTypeName(TypeName node) {
-    TypeName other = this.other;
-    _verifyType(node.type, other.type);
-    _visitNode(node.name, node.name);
-    _visitNode(node.typeArguments, other.typeArguments);
-  }
-
-  @override
-  visitTypeParameter(TypeParameter node) {
-    TypeParameter other = this.other;
-    _visitNode(node.name, other.name);
-    _visitNode(node.bound, other.bound);
-  }
-
-  @override
-  visitTypeParameterList(TypeParameterList node) {
-    TypeParameterList other = this.other;
-    _visitList(node.typeParameters, other.typeParameters);
-  }
-
-  @override
-  visitVariableDeclaration(VariableDeclaration node) {
-    VariableDeclaration other = this.other;
-    _visitDeclaration(node, other);
-    _visitNode(node.name, other.name);
-    _visitNode(node.initializer, other.initializer);
-  }
-
-  @override
-  visitVariableDeclarationList(VariableDeclarationList node) {
-    VariableDeclarationList other = this.other;
-    _visitNode(node.type, other.type);
-    _visitList(node.variables, other.variables);
-  }
-
-  @override
-  visitVariableDeclarationStatement(VariableDeclarationStatement node) {
-    VariableDeclarationStatement other = this.other;
-    _visitNode(node.variables, other.variables);
-  }
-
-  @override
-  visitWhileStatement(WhileStatement node) {
-    WhileStatement other = this.other;
-    _visitNode(node.condition, other.condition);
-    _visitNode(node.body, other.body);
-  }
-
-  @override
-  visitWithClause(WithClause node) {
-    WithClause other = this.other;
-    _visitList(node.mixinTypes, other.mixinTypes);
-  }
-
-  @override
-  visitYieldStatement(YieldStatement node) {
-    YieldStatement other = this.other;
-    _visitNode(node.expression, other.expression);
-  }
-
-  void _assertNode(AstNode a, AstNode b) {
-    _expectEquals(a.offset, b.offset);
-    _expectEquals(a.length, b.length);
-  }
-
-  void _expectEquals(actual, expected) {
-    if (actual != expected) {
-      String message = '';
-      message += 'Expected: $expected\n';
-      message += '  Actual: $actual\n';
-      _fail(message);
-    }
-  }
-
-  void _expectIsNull(obj) {
-    if (obj != null) {
-      String message = '';
-      message += 'Expected: null\n';
-      message += '  Actual: $obj\n';
-      _fail(message);
-    }
-  }
-
-  void _expectLength(List actualList, int expected) {
+  bool failDifferentLength(List expectedList, List actualList) {
+    int expectedLength = expectedList.length;
+    int actualLength = actualList.length;
     String message = '';
-    message += 'Expected length: $expected\n';
-    if (actualList == null) {
-      message += 'but null found.';
-      _fail(message);
+    message += 'Expected length: $expectedLength\n';
+    message += 'but $actualLength found\n';
+    message += 'in $actualList';
+    _fail(message);
+    return false;
+  }
+
+  @override
+  bool failIfNotNull(Object expected, Object actual) {
+    if (actual != null) {
+      _fail('Expected null, but found $actual');
+      return false;
     }
-    int actual = actualList.length;
-    if (actual != expected) {
-      message += 'but $actual found\n';
-      message += 'in $actualList';
-      _fail(message);
+    return true;
+  }
+
+  @override
+  bool failIsNull(Object expected, Object actual) {
+    _fail('Expected not null, but found null');
+    return false;
+  }
+
+  @override
+  bool failRuntimeType(Object expected, Object actual) {
+    _fail('Expected ${expected.runtimeType}, but found ${actual.runtimeType}');
+    return false;
+  }
+
+  @override
+  bool isEqualNodes(AstNode first, AstNode second) {
+    super.isEqualNodes(first, second);
+    if (first is SimpleIdentifier && second is SimpleIdentifier) {
+      int offset = first.offset;
+      _verifyElement(
+          first.staticElement, second.staticElement, 'staticElement[$offset]');
+      _verifyElement(first.propagatedElement, second.propagatedElement,
+          'propagatedElement[$offset]');
+    } else if (first is Declaration && second is Declaration) {
+      int offset = first.offset;
+      _verifyElement(first.element, second.element, 'declaration[$offset]');
+    } else if (first is Directive && second is Directive) {
+      int offset = first.offset;
+      _verifyElement(first.element, second.element, 'directive[$offset]');
+    } else if (first is Expression && second is Expression) {
+      int offset = first.offset;
+      _verifyType(first.staticType, second.staticType, 'staticType[$offset]');
+      _verifyType(first.propagatedType, second.propagatedType,
+          'propagatedType[$offset]');
+      _verifyElement(first.staticParameterElement,
+          second.staticParameterElement, 'staticParameterElement[$offset]');
+      _verifyElement(
+          first.propagatedParameterElement,
+          second.propagatedParameterElement,
+          'propagatedParameterElement[$offset]');
     }
+    return true;
+  }
+
+  @override
+  bool isEqualTokensNotNull(Token expected, Token actual) {
+    _verifyEqual('lexeme', expected.lexeme, actual.lexeme);
+    _verifyEqual('offset', expected.offset, actual.offset);
+    _verifyEqual('offset', expected.length, actual.length);
+    return true;
   }
 
   void _fail(String message) {
     throw new IncrementalResolutionMismatch(message);
   }
 
-  void _verifyElement(Element a, Element b) {
+  void _verifyElement(Element a, Element b, String desc) {
     if (a is Member && b is Member) {
       a = (a as Member).baseElement;
       b = (b as Member).baseElement;
@@ -842,8 +126,7 @@
     String locationA = _getElementLocationWithoutUri(a);
     String locationB = _getElementLocationWithoutUri(b);
     if (locationA != locationB) {
-      int offset = other.offset;
-      _fail('[$offset]\nExpected: $b ($locationB)\n  Actual: $a ($locationA)');
+      _fail('$desc\nExpected: $b ($locationB)\n  Actual: $a ($locationA)');
     }
     if (a == null && b == null) {
       return;
@@ -866,66 +149,15 @@
     }
   }
 
-  void _verifyType(DartType a, DartType b) {
+  void _verifyType(DartType a, DartType b, String desc) {
     if (!validateTypes) {
       return;
     }
     if (a != b) {
-      int offset = other.offset;
-      _fail('[$offset]\nExpected: $b\n  Actual: $a');
+      _fail('$desc\nExpected: $b\n  Actual: $a');
     }
   }
 
-  void _visitAnnotatedNode(AnnotatedNode node, AnnotatedNode other) {
-    _visitNode(node.documentationComment, other.documentationComment);
-    _visitList(node.metadata, other.metadata);
-  }
-
-  _visitDeclaration(Declaration node, Declaration other) {
-    _verifyElement(node.element, other.element);
-    _visitAnnotatedNode(node, other);
-  }
-
-  _visitDirective(Directive node, Directive other) {
-    _verifyElement(node.element, other.element);
-    _visitAnnotatedNode(node, other);
-  }
-
-  void _visitExpression(Expression a, Expression b) {
-//    print('[${a.offset}] |$a| vs. [${b.offset}] |$b|');
-    _verifyType(a.staticType, b.staticType);
-    _verifyType(a.propagatedType, b.propagatedType);
-    _verifyElement(a.staticParameterElement, b.staticParameterElement);
-    _verifyElement(a.propagatedParameterElement, b.propagatedParameterElement);
-    _assertNode(a, b);
-  }
-
-  void _visitList(NodeList nodeList, NodeList expected) {
-    int length = nodeList.length;
-    _expectLength(nodeList, expected.length);
-    for (int i = 0; i < length; i++) {
-      _visitNode(nodeList[i], expected[i]);
-    }
-  }
-
-  void _visitNode(AstNode node, AstNode other) {
-    if (node == null) {
-      _expectIsNull(other);
-    } else {
-      this.other = other;
-      _assertNode(node, other);
-      node.accept(this);
-    }
-  }
-
-  void _visitNormalFormalParameter(
-      NormalFormalParameter node, NormalFormalParameter other) {
-    _verifyElement(node.element, other.element);
-    _visitNode(node.documentationComment, other.documentationComment);
-    _visitList(node.metadata, other.metadata);
-    _visitNode(node.identifier, other.identifier);
-  }
-
   /**
    * Returns an URI scheme independent version of the [element] location.
    */
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 889e156..31ed260 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -697,8 +697,12 @@
       return false;
     }
 
+    bool inCommentReference(SimpleIdentifier identifier) =>
+        identifier.getAncestor((AstNode node) => node is CommentReference) !=
+        null;
+
     Element element = identifier.bestElement;
-    if (isProtected(element)) {
+    if (isProtected(element) && !inCommentReference(identifier)) {
       ClassElement definingClass = element.enclosingElement;
       ClassDeclaration accessingClass =
           identifier.getAncestor((AstNode node) => node is ClassDeclaration);
@@ -2049,8 +2053,8 @@
    *            This allows for a final break, continue, return, or throw statement
    *            at the end of a switch case, that are mandated by the language spec.
    */
-  void _checkForDeadStatementsInNodeList(
-      NodeList<Statement> statements, {bool allowMandated: false}) {
+  void _checkForDeadStatementsInNodeList(NodeList<Statement> statements,
+      {bool allowMandated: false}) {
     bool statementExits(Statement statement) {
       if (statement is BreakStatement) {
         return statement.label == null;
@@ -5954,7 +5958,6 @@
 
   @override
   Object visitAsExpression(AsExpression node) {
-    InferenceContext.setType(node.expression, node.type.type);
     super.visitAsExpression(node);
     // Since an as-statement doesn't actually change the type, we don't
     // let it affect the propagated type when it would result in a loss
diff --git a/pkg/analyzer/lib/src/generated/sdk_io.dart b/pkg/analyzer/lib/src/generated/sdk_io.dart
index 0d053f6b..be7c27a 100644
--- a/pkg/analyzer/lib/src/generated/sdk_io.dart
+++ b/pkg/analyzer/lib/src/generated/sdk_io.dart
@@ -25,6 +25,205 @@
 import 'package:path/path.dart' as pathos;
 
 /**
+ * An abstract implementation of a Dart SDK in which the available libraries are
+ * stored in a library map. Subclasses are responsible for populating the
+ * library map.
+ */
+abstract class AbstractDartSdk implements DartSdk {
+  /**
+   * A mapping from Dart library URI's to the library represented by that URI.
+   */
+  LibraryMap libraryMap = new LibraryMap();
+
+  /**
+   * The [AnalysisOptions] to use to create the [context].
+   */
+  AnalysisOptions _analysisOptions;
+
+  /**
+   * The flag that specifies whether an SDK summary should be used. This is a
+   * temporary flag until summaries are enabled by default.
+   */
+  bool _useSummary = false;
+
+  /**
+   * The [AnalysisContext] which is used for all of the sources in this SDK.
+   */
+  InternalAnalysisContext _analysisContext;
+
+  /**
+   * The mapping from Dart URI's to the corresponding sources.
+   */
+  Map<String, Source> _uriToSourceMap = new HashMap<String, Source>();
+
+  /**
+   * Set the [options] for this SDK analysis context.  Throw [StateError] if the
+   * context has been already created.
+   */
+  void set analysisOptions(AnalysisOptions options) {
+    if (_analysisContext != null) {
+      throw new StateError(
+          'Analysis options cannot be changed after context creation.');
+    }
+    _analysisOptions = options;
+  }
+
+  @override
+  AnalysisContext get context {
+    if (_analysisContext == null) {
+      _analysisContext = new SdkAnalysisContext(_analysisOptions);
+      SourceFactory factory = new SourceFactory([new DartUriResolver(this)]);
+      _analysisContext.sourceFactory = factory;
+      if (_useSummary) {
+        bool strongMode = _analysisOptions?.strongMode ?? false;
+        PackageBundle sdkBundle = getSummarySdkBundle(strongMode);
+        if (sdkBundle != null) {
+          _analysisContext.resultProvider = new SdkSummaryResultProvider(
+              _analysisContext, sdkBundle, strongMode);
+        }
+      }
+    }
+    return _analysisContext;
+  }
+
+  @override
+  List<SdkLibrary> get sdkLibraries => libraryMap.sdkLibraries;
+
+  @override
+  List<String> get uris => libraryMap.uris;
+
+  /**
+   * Return `true` if the SDK summary will be used when available.
+   */
+  bool get useSummary => _useSummary;
+
+  /**
+   * Specify whether SDK summary should be used.
+   */
+  void set useSummary(bool use) {
+    if (_analysisContext != null) {
+      throw new StateError(
+          'The "useSummary" flag cannot be changed after context creation.');
+    }
+    _useSummary = use;
+  }
+
+  @override
+  Source fromFileUri(Uri uri) {
+    JavaFile file = new JavaFile.fromUri(uri);
+
+    String path = _getPath(file);
+    if (path == null) {
+      return null;
+    }
+    try {
+      return new FileBasedSource(file, parseUriWithException(path));
+    } on URISyntaxException catch (exception, stackTrace) {
+      AnalysisEngine.instance.logger.logInformation(
+          "Failed to create URI: $path",
+          new CaughtException(exception, stackTrace));
+    }
+    return null;
+  }
+
+  String getRelativePathFromFile(JavaFile file);
+
+  @override
+  SdkLibrary getSdkLibrary(String dartUri) => libraryMap.getLibrary(dartUri);
+
+  /**
+   * Return the [PackageBundle] for this SDK, if it exists, or `null` otherwise.
+   * This method should not be used outside of `analyzer` and `analyzer_cli`
+   * packages.
+   */
+  PackageBundle getSummarySdkBundle(bool strongMode);
+
+  FileBasedSource internalMapDartUri(String dartUri) {
+    // TODO(brianwilkerson) Figure out how to unify the implementations in the
+    // two subclasses.
+    String libraryName;
+    String relativePath;
+    int index = dartUri.indexOf('/');
+    if (index >= 0) {
+      libraryName = dartUri.substring(0, index);
+      relativePath = dartUri.substring(index + 1);
+    } else {
+      libraryName = dartUri;
+      relativePath = "";
+    }
+    SdkLibrary library = getSdkLibrary(libraryName);
+    if (library == null) {
+      return null;
+    }
+    String srcPath;
+    if (relativePath.isEmpty) {
+      srcPath = library.path;
+    } else {
+      String libraryPath = library.path;
+      int index = libraryPath.lastIndexOf(JavaFile.separator);
+      if (index == -1) {
+        index = libraryPath.lastIndexOf('/');
+        if (index == -1) {
+          return null;
+        }
+      }
+      String prefix = libraryPath.substring(0, index + 1);
+      srcPath = '$prefix$relativePath';
+    }
+    String filePath = srcPath.replaceAll('/', JavaFile.separator);
+    try {
+      JavaFile file = new JavaFile(filePath);
+      return new FileBasedSource(file, parseUriWithException(dartUri));
+    } on URISyntaxException {
+      return null;
+    }
+  }
+
+  @override
+  Source mapDartUri(String dartUri) {
+    Source source = _uriToSourceMap[dartUri];
+    if (source == null) {
+      source = internalMapDartUri(dartUri);
+      _uriToSourceMap[dartUri] = source;
+    }
+    return source;
+  }
+
+  String _getPath(JavaFile file) {
+    List<SdkLibrary> libraries = libraryMap.sdkLibraries;
+    int length = libraries.length;
+    List<String> paths = new List(length);
+    String filePath = getRelativePathFromFile(file);
+    if (filePath == null) {
+      return null;
+    }
+    for (int i = 0; i < length; i++) {
+      SdkLibrary library = libraries[i];
+      String libraryPath = library.path.replaceAll('/', JavaFile.separator);
+      if (filePath == libraryPath) {
+        return library.shortName;
+      }
+      paths[i] = libraryPath;
+    }
+    for (int i = 0; i < length; i++) {
+      SdkLibrary library = libraries[i];
+      String libraryPath = paths[i];
+      int index = libraryPath.lastIndexOf(JavaFile.separator);
+      if (index >= 0) {
+        String prefix = libraryPath.substring(0, index + 1);
+        if (filePath.startsWith(prefix)) {
+          String relPath = filePath
+              .substring(prefix.length)
+              .replaceAll(JavaFile.separator, '/');
+          return '${library.shortName}/$relPath';
+        }
+      }
+    }
+    return null;
+  }
+}
+
+/**
  * A Dart SDK installed in a specified directory. Typical Dart SDK layout is
  * something like...
  *
@@ -40,7 +239,7 @@
  *           ... Dart utilities ...
  *     Chromium/   <-- Dartium typically exists in a sibling directory
  */
-class DirectoryBasedDartSdk implements DartSdk {
+class DirectoryBasedDartSdk extends AbstractDartSdk {
   /**
    * The default SDK, or `null` if the default SDK either has not yet been
    * created or cannot be created for some reason.
@@ -193,11 +392,6 @@
   }
 
   /**
-   * The [AnalysisContext] which is used for all of the sources in this sdk.
-   */
-  InternalAnalysisContext _analysisContext;
-
-  /**
    * The directory containing the SDK.
    */
   JavaFile _sdkDirectory;
@@ -208,11 +402,6 @@
   JavaFile _libraryDirectory;
 
   /**
-   * The flag that specifies whether SDK summary should be used.
-   */
-  bool _useSummary = false;
-
-  /**
    * The revision number of this SDK, or `"0"` if the revision number cannot be
    * discovered.
    */
@@ -239,58 +428,13 @@
   JavaFile _vmExecutable;
 
   /**
-   * A mapping from Dart library URI's to the library represented by that URI.
-   */
-  LibraryMap _libraryMap;
-
-  /**
-   * The mapping from Dart URI's to the corresponding sources.
-   */
-  Map<String, Source> _uriToSourceMap = new HashMap<String, Source>();
-
-  /**
-   * The [AnalysisOptions] to use to create the [context].
-   */
-  AnalysisOptions _analysisOptions;
-
-  /**
    * Initialize a newly created SDK to represent the Dart SDK installed in the
    * [sdkDirectory]. The flag [useDart2jsPaths] is `true` if the dart2js path
    * should be used when it is available
    */
   DirectoryBasedDartSdk(JavaFile sdkDirectory, [bool useDart2jsPaths = false]) {
     this._sdkDirectory = sdkDirectory.getAbsoluteFile();
-    _libraryMap = initialLibraryMap(useDart2jsPaths);
-  }
-
-  /**
-   * Set the [options] for this SDK analysis context.  Throw [StateError] if the
-   * context has been already created.
-   */
-  void set analysisOptions(AnalysisOptions options) {
-    if (_analysisContext != null) {
-      throw new StateError(
-          'Analysis options cannot be changed after context creation.');
-    }
-    _analysisOptions = options;
-  }
-
-  @override
-  AnalysisContext get context {
-    if (_analysisContext == null) {
-      _analysisContext = new SdkAnalysisContext(_analysisOptions);
-      SourceFactory factory = new SourceFactory([new DartUriResolver(this)]);
-      _analysisContext.sourceFactory = factory;
-      if (_useSummary) {
-        PackageBundle sdkBundle = getSummarySdkBundle();
-        if (sdkBundle != null) {
-          bool strongMode = _analysisOptions?.strongMode ?? false;
-          _analysisContext.resultProvider = new SdkSummaryResultProvider(
-              _analysisContext, sdkBundle, strongMode);
-        }
-      }
-    }
-    return _analysisContext;
+    libraryMap = initialLibraryMap(useDart2jsPaths);
   }
 
   /**
@@ -386,9 +530,6 @@
     return _pubExecutable;
   }
 
-  @override
-  List<SdkLibrary> get sdkLibraries => _libraryMap.sdkLibraries;
-
   /**
    * Return the revision number of this SDK, or `"0"` if the revision number
    * cannot be discovered.
@@ -411,25 +552,6 @@
     return _sdkVersion;
   }
 
-  @override
-  List<String> get uris => _libraryMap.uris;
-
-  /**
-   * Whether an SDK summary should be used.
-   */
-  bool get useSummary => _useSummary;
-
-  /**
-   * Specify whether SDK summary should be used.
-   */
-  void set useSummary(bool use) {
-    if (_analysisContext != null) {
-      throw new StateError(
-          'The "useSummary" flag cannot be changed after context creation.');
-    }
-    _useSummary = use;
-  }
-
   /**
    * Return the name of the file containing the VM executable.
    */
@@ -470,45 +592,6 @@
         _LIBRARIES_FILE);
   }
 
-  @override
-  Source fromFileUri(Uri uri) {
-    JavaFile file = new JavaFile.fromUri(uri);
-    String filePath = file.getAbsolutePath();
-    String libPath = libraryDirectory.getAbsolutePath();
-    if (!filePath.startsWith("$libPath${JavaFile.separator}")) {
-      return null;
-    }
-    filePath = filePath.substring(libPath.length + 1);
-    for (SdkLibrary library in _libraryMap.sdkLibraries) {
-      String libraryPath = library.path;
-      if (filePath.replaceAll('\\', '/') == libraryPath) {
-        String path = library.shortName;
-        try {
-          return new FileBasedSource(file, parseUriWithException(path));
-        } on URISyntaxException catch (exception, stackTrace) {
-          AnalysisEngine.instance.logger.logInformation(
-              "Failed to create URI: $path",
-              new CaughtException(exception, stackTrace));
-          return null;
-        }
-      }
-      libraryPath = new JavaFile(library.path).getParent();
-      if (filePath.startsWith("$libraryPath${JavaFile.separator}")) {
-        String path =
-            "${library.shortName}/${filePath.substring(libraryPath.length + 1)}";
-        try {
-          return new FileBasedSource(file, parseUriWithException(path));
-        } on URISyntaxException catch (exception, stackTrace) {
-          AnalysisEngine.instance.logger.logInformation(
-              "Failed to create URI: $path",
-              new CaughtException(exception, stackTrace));
-          return null;
-        }
-      }
-    }
-    return null;
-  }
-
   /**
    * Return the directory where dartium can be found (the directory that will be
    * the working directory if Dartium is invoked without changing the default),
@@ -536,16 +619,22 @@
   }
 
   @override
-  SdkLibrary getSdkLibrary(String dartUri) => _libraryMap.getLibrary(dartUri);
+  String getRelativePathFromFile(JavaFile file) {
+    String filePath = file.getAbsolutePath();
+    String libPath = libraryDirectory.getAbsolutePath();
+    if (!filePath.startsWith("$libPath${JavaFile.separator}")) {
+      return null;
+    }
+    return filePath.substring(libPath.length + 1);
+  }
 
   /**
    * Return the [PackageBundle] for this SDK, if it exists, or `null` otherwise.
    * This method should not be used outside of `analyzer` and `analyzer_cli`
    * packages.
    */
-  PackageBundle getSummarySdkBundle() {
+  PackageBundle getSummarySdkBundle(bool strongMode) {
     String rootPath = directory.getAbsolutePath();
-    bool strongMode = _analysisOptions?.strongMode ?? false;
     String name = strongMode ? 'strong.sum' : 'spec.sum';
     String path = pathos.join(rootPath, 'lib', '_internal', name);
     try {
@@ -589,16 +678,7 @@
   }
 
   @override
-  Source mapDartUri(String dartUri) {
-    Source source = _uriToSourceMap[dartUri];
-    if (source == null) {
-      source = _mapDartUri(dartUri);
-      _uriToSourceMap[dartUri] = source;
-    }
-    return source;
-  }
-
-  FileBasedSource _mapDartUri(String dartUri) {
+  FileBasedSource internalMapDartUri(String dartUri) {
     String libraryName;
     String relativePath;
     int index = dartUri.indexOf('/');
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index 4ba4c51..4492037 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -15,7 +15,7 @@
 import 'package:analyzer/src/generated/java_io.dart' show JavaFile;
 import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
 import 'package:analyzer/src/generated/source_io.dart'
-    show FileBasedSource, FileUriResolver, PackageUriResolver;
+    show FileBasedSource, PackageUriResolver;
 import 'package:analyzer/task/model.dart';
 import 'package:package_config/packages.dart';
 import 'package:path/path.dart' as pathos;
@@ -905,7 +905,7 @@
       return UriKind.PACKAGE_URI;
     } else if (scheme == DartUriResolver.DART_SCHEME) {
       return UriKind.DART_URI;
-    } else if (scheme == FileUriResolver.FILE_SCHEME) {
+    } else if (scheme == ResourceUriResolver.FILE_SCHEME) {
       return UriKind.FILE_URI;
     }
     return UriKind.FILE_URI;
diff --git a/pkg/analyzer/lib/src/generated/source_io.dart b/pkg/analyzer/lib/src/generated/source_io.dart
index b7cb0fd..f7b47ef 100644
--- a/pkg/analyzer/lib/src/generated/source_io.dart
+++ b/pkg/analyzer/lib/src/generated/source_io.dart
@@ -262,7 +262,11 @@
 
 /**
  * Instances of the class `FileUriResolver` resolve `file` URI's.
+ *
+ * This class is now deprecated, 'new FileUriResolver()' is equivalent to
+ * 'new ResourceUriResolver(PhysicalResourceProvider.INSTANCE)'.
  */
+@deprecated
 class FileUriResolver extends UriResolver {
   /**
    * The name of the `file` scheme.
@@ -516,7 +520,12 @@
 
 /**
  * Instances of the class `RelativeFileUriResolver` resolve `file` URI's.
+ *
+ * This class is now deprecated, file URI resolution should be done with
+ * ResourceUriResolver, i.e.
+ * 'new ResourceUriResolver(PhysicalResourceProvider.INSTANCE)'.
  */
+@deprecated
 class RelativeFileUriResolver extends UriResolver {
   /**
    * The name of the `file` scheme.
diff --git a/pkg/analyzer/lib/src/summary/summary_file_builder.dart b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
index 0d340b9..3cd21f1 100644
--- a/pkg/analyzer/lib/src/summary/summary_file_builder.dart
+++ b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
@@ -14,10 +14,16 @@
 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/summary/flat_buffers.dart' as fb;
 import 'package:analyzer/src/summary/index_unit.dart';
 import 'package:analyzer/src/summary/summarize_elements.dart';
 import 'package:path/path.dart';
 
+const int FIELD_SPEC_INDEX = 1;
+const int FIELD_SPEC_SUM = 0;
+const int FIELD_STRONG_INDEX = 3;
+const int FIELD_STRONG_SUM = 2;
+
 class BuilderOutput {
   final List<int> sum;
   final List<int> index;
@@ -40,13 +46,72 @@
   }
 }
 
+/**
+ * Summary build configuration.
+ */
+class SummaryBuildConfig {
+
+  /**
+   * Whether to use exclude informative data from created summaries.
+   */
+  final bool buildSummaryExcludeInformative;
+
+  /**
+   * Whether to output a summary in "fallback mode".
+   */
+  final bool buildSummaryFallback;
+
+  /**
+   * Whether to create summaries directly from ASTs, i.e. don't create a
+   * full element model.
+   */
+  final bool buildSummaryOnlyAst;
+
+  /**
+   * Path to the dart SDK summary file.
+   */
+  final String dartSdkSummaryPath;
+
+  /**
+   * Whether to use strong static checking.
+   */
+  final bool strongMode;
+
+  /**
+   * List of summary input file paths.
+   */
+  final Iterable<String> summaryInputs;
+
+  /**
+   * Create a build configuration with the given set options.
+   */
+  SummaryBuildConfig(
+      {this.strongMode: false,
+      this.summaryInputs,
+      this.dartSdkSummaryPath,
+      this.buildSummaryExcludeInformative: false,
+      this.buildSummaryFallback: false,
+      this.buildSummaryOnlyAst: false});
+}
+
 class SummaryBuilder {
-  final AnalysisContext _context;
-  final Iterable<Source> _librarySources;
+  final AnalysisContext context;
+  final Iterable<Source> librarySources;
+  final SummaryBuildConfig config;
 
-  SummaryBuilder(this._librarySources, this._context);
+  /**
+   * Create a summary builder for these [librarySources] and [context] using the
+   * given [config].
+   */
+  SummaryBuilder(this.librarySources, this.context, this.config);
 
-  factory SummaryBuilder.forSdk(String sdkPath, bool strongMode) {
+  /**
+   * Create an SDK summary builder for the dart SDK at the given [sdkPath],
+   * using this [config].
+   */
+  factory SummaryBuilder.forSdk(String sdkPath, SummaryBuildConfig config) {
+    bool strongMode = config.strongMode;
+
     //
     // Prepare SDK.
     //
@@ -70,10 +135,39 @@
       librarySources.add(sdk.mapDartUri(uri));
     }
 
-    return new SummaryBuilder(librarySources, sdk.context);
+    return new SummaryBuilder(librarySources, sdk.context, config);
   }
 
-  BuilderOutput build() => new _Builder(_context, _librarySources).build();
+  BuilderOutput build() => new _Builder(context, librarySources).build();
+}
+
+/**
+ * Intermediary summary output result.
+ */
+class SummaryOutput {
+  final BuilderOutput spec;
+  final BuilderOutput strong;
+  SummaryOutput(this.spec, this.strong);
+
+  /**
+   * Write this summary output to the given [outputPath] and return the
+   * created file.
+   */
+  File write(String outputPath) {
+    fb.Builder builder = new fb.Builder();
+    fb.Offset specSumOffset = builder.writeListUint8(spec.sum);
+    fb.Offset specIndexOffset = builder.writeListUint8(spec.index);
+    fb.Offset strongSumOffset = builder.writeListUint8(strong.sum);
+    fb.Offset strongIndexOffset = builder.writeListUint8(strong.index);
+    builder.startTable();
+    builder.addOffset(FIELD_SPEC_SUM, specSumOffset);
+    builder.addOffset(FIELD_SPEC_INDEX, specIndexOffset);
+    builder.addOffset(FIELD_STRONG_SUM, strongSumOffset);
+    builder.addOffset(FIELD_STRONG_INDEX, strongIndexOffset);
+    fb.Offset offset = builder.endTable();
+    return new File(outputPath)
+      ..writeAsBytesSync(builder.finish(offset), mode: FileMode.WRITE_ONLY);
+  }
 }
 
 class _Builder {
@@ -88,7 +182,7 @@
   _Builder(this.context, this.librarySources);
 
   /**
-   * Build a strong or spec mode summary for the Dart SDK at [sdkPath].
+   * Build summary output.
    */
   BuilderOutput build() {
     //
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index 148499e..5d3d3b2 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -4610,6 +4610,20 @@
   }
 
   @override
+  visitClassTypeAlias(ClassTypeAlias node) {
+    ReferencedNamesScope outerScope = scope;
+    try {
+      scope = new ReferencedNamesScope.forClassTypeAlias(scope, node);
+      dependsOn = new Set<String>();
+      super.visitClassTypeAlias(node);
+      names.userToDependsOn[node.name.name] = dependsOn;
+    } finally {
+      dependsOn = null;
+      scope = outerScope;
+    }
+  }
+
+  @override
   visitConstructorName(ConstructorName node) {
     if (node.parent is! ConstructorDeclaration) {
       super.visitConstructorName(node);
@@ -4696,6 +4710,23 @@
       dependsOn.add(name);
     }
   }
+
+  @override
+  visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+    VariableDeclarationList variableList = node.variables;
+    // Prepare type dependencies.
+    Set<String> typeDependencies = new Set<String>();
+    dependsOn = typeDependencies;
+    variableList.type?.accept(this);
+    // Combine individual variable dependencies with the type dependencies.
+    for (VariableDeclaration variable in variableList.variables) {
+      dependsOn = new Set<String>();
+      variable.accept(this);
+      dependsOn.addAll(typeDependencies);
+      names.userToDependsOn[variable.name.name] = dependsOn;
+    }
+    dependsOn = null;
+  }
 }
 
 class ReferencedNamesScope {
@@ -4735,6 +4766,13 @@
     return scope;
   }
 
+  factory ReferencedNamesScope.forClassTypeAlias(
+      ReferencedNamesScope enclosing, ClassTypeAlias node) {
+    ReferencedNamesScope scope = new ReferencedNamesScope(enclosing);
+    scope._addTypeParameters(node.typeParameters);
+    return scope;
+  }
+
   factory ReferencedNamesScope.forFunction(
       ReferencedNamesScope enclosing, FunctionDeclaration node) {
     ReferencedNamesScope scope = new ReferencedNamesScope(enclosing);
diff --git a/pkg/analyzer/lib/src/task/incremental_element_builder.dart b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
index 66a5bbe..20c6a76 100644
--- a/pkg/analyzer/lib/src/task/incremental_element_builder.dart
+++ b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
@@ -18,6 +18,26 @@
 import 'package:analyzer/src/generated/source.dart';
 
 /**
+ * The change of a single [ClassElement].
+ */
+class ClassElementDelta {
+  final ClassElement element;
+
+  final List<PropertyAccessorElement> addedAccessors =
+      <PropertyAccessorElement>[];
+  final List<PropertyAccessorElement> removedAccessors =
+      <PropertyAccessorElement>[];
+
+  final List<ConstructorElement> addedConstructors = <ConstructorElement>[];
+  final List<ConstructorElement> removedConstructors = <ConstructorElement>[];
+
+  final List<MethodElement> addedMethods = <MethodElement>[];
+  final List<MethodElement> removedMethods = <MethodElement>[];
+
+  ClassElementDelta(this.element);
+}
+
+/**
  * The change of a single [CompilationUnitElement].
  */
 class CompilationUnitElementDelta {
@@ -35,6 +55,11 @@
    * The list of removed top-level elements.
    */
   final List<Element> removedDeclarations = <Element>[];
+
+  /**
+   * The list of changed class elements.
+   */
+  final List<ClassElementDelta> classDeltas = <ClassElementDelta>[];
 }
 
 /**
@@ -47,7 +72,7 @@
   final CompilationUnit oldUnit;
   final CompilationUnitElementImpl unitElement;
   final CompilationUnit newUnit;
-  final ElementHolder holder = new ElementHolder();
+  final ElementHolder unitElementHolder = new ElementHolder();
 
   /**
    * The change between element models of [oldUnit] and [newUnit].
@@ -78,28 +103,176 @@
         .buildCompilationUnit(unitSource, newUnit, librarySource);
     _processDirectives();
     _processUnitMembers();
-    newUnit.element = unitElement;
     _replaceUnitContents(oldUnit, newUnit);
+    newUnit.element = unitElement;
+    unitElement.setCodeRange(0, newUnit.endToken.end);
   }
 
-  void _addElementToHolder(Element element) {
-    if (element is PropertyAccessorElement) {
-      holder.addAccessor(element);
-    } else if (element is ClassElement) {
+  void _addElementToUnitHolder(Element element) {
+    if (element is ClassElement) {
       if (element.isEnum) {
-        holder.addEnum(element);
+        unitElementHolder.addEnum(element);
       } else {
-        holder.addType(element);
+        unitElementHolder.addType(element);
       }
     } else if (element is FunctionElement) {
-      holder.addFunction(element);
+      unitElementHolder.addFunction(element);
     } else if (element is FunctionTypeAliasElement) {
-      holder.addTypeAlias(element);
+      unitElementHolder.addTypeAlias(element);
+    } else if (element is PropertyAccessorElement) {
+      unitElementHolder.addAccessor(element);
     } else if (element is TopLevelVariableElement) {
-      holder.addTopLevelVariable(element);
+      unitElementHolder.addTopLevelVariable(element);
     }
   }
 
+  ClassElementDelta _processClassMembers(
+      ClassDeclaration oldClass, ClassDeclaration newClass) {
+    // TODO(scheglov) Compare class structure: type parameters, supertype,
+    // mixins and interfaces.
+    Map<String, ClassMember> oldNodeMap = new HashMap<String, ClassMember>();
+    for (ClassMember oldNode in oldClass.members) {
+      String code = TokenUtils.getFullCode(oldNode);
+      oldNodeMap[code] = oldNode;
+    }
+    // Prepare elements.
+    ClassElement newElement = newClass.element;
+    ClassElement oldElement = oldClass.element;
+    // Use the old element for the new node.
+    newClass.name.staticElement = oldElement;
+    if (newElement is ClassElementImpl && oldElement is ClassElementImpl) {
+      oldElement.setCodeRange(newElement.codeOffset, newElement.codeLength);
+    }
+    // Prepare delta.
+    ClassElementImpl classElement = oldClass.element;
+    ElementHolder classElementHolder = new ElementHolder();
+    ClassElementDelta classDelta = new ClassElementDelta(classElement);
+    // Prepare all old member elements.
+    var removedAccessors = new Set<PropertyAccessorElement>();
+    var removedConstructors = new Set<ConstructorElement>();
+    var removedMethods = new Set<MethodElement>();
+    removedAccessors.addAll(classElement.accessors);
+    removedConstructors.addAll(classElement.constructors);
+    removedMethods.addAll(classElement.methods);
+    // Utilities.
+    void processConstructorDeclaration(
+        ConstructorDeclaration node, bool isNew) {
+      ConstructorElement element = node.element;
+      if (element != null) {
+        classElementHolder.addConstructor(element);
+        if (isNew) {
+          classDelta.addedConstructors.add(element);
+        } else {
+          removedConstructors.remove(element);
+        }
+      }
+    }
+    void processFieldDeclaration(FieldDeclaration node, bool isNew) {
+      for (VariableDeclaration field in node.fields.variables) {
+        PropertyInducingElement element = field.element;
+        if (element != null) {
+          PropertyAccessorElement getter = element.getter;
+          PropertyAccessorElement setter = element.setter;
+          if (getter != null) {
+            classElementHolder.addAccessor(getter);
+            if (isNew) {
+              classDelta.addedAccessors.add(getter);
+            } else {
+              removedAccessors.remove(getter);
+            }
+          }
+          if (setter != null) {
+            classElementHolder.addAccessor(setter);
+            if (isNew) {
+              classDelta.addedAccessors.add(setter);
+            } else {
+              removedAccessors.remove(setter);
+            }
+          }
+        }
+      }
+    }
+    void processMethodDeclaration(MethodDeclaration node, bool isNew) {
+      Element element = node.element;
+      if (element is MethodElement) {
+        classElementHolder.addMethod(element);
+        if (isNew) {
+          classDelta.addedMethods.add(element);
+        } else {
+          removedMethods.remove(element);
+        }
+      } else if (element is PropertyAccessorElement) {
+        classElementHolder.addAccessor(element);
+        if (isNew) {
+          classDelta.addedAccessors.add(element);
+        } else {
+          removedAccessors.remove(element);
+        }
+      }
+    }
+    // Replace new nodes with the identical old nodes.
+    bool newHasConstructor = false;
+    for (ClassMember newNode in newClass.members) {
+      String code = TokenUtils.getFullCode(newNode);
+      ClassMember oldNode = oldNodeMap[code];
+      // Add the new element.
+      if (oldNode == null) {
+        if (newNode is ConstructorDeclaration) {
+          newHasConstructor = true;
+          processConstructorDeclaration(newNode, true);
+        }
+        if (newNode is FieldDeclaration) {
+          processFieldDeclaration(newNode, true);
+        }
+        if (newNode is MethodDeclaration) {
+          processMethodDeclaration(newNode, true);
+        }
+        continue;
+      }
+      // Do replacement.
+      _replaceNode(newNode, oldNode);
+      if (oldNode is ConstructorDeclaration) {
+        processConstructorDeclaration(oldNode, false);
+      }
+      if (oldNode is FieldDeclaration) {
+        processFieldDeclaration(oldNode, false);
+      }
+      if (oldNode is MethodDeclaration) {
+        processMethodDeclaration(oldNode, false);
+      }
+    }
+    // If the class had only a default synthetic constructor, and there are
+    // no explicit constructors in the new AST, keep the constructor.
+    if (!newHasConstructor) {
+      List<ConstructorElement> constructors = classElement.constructors;
+      if (constructors.length == 1) {
+        ConstructorElement constructor = constructors[0];
+        if (constructor.isSynthetic && constructor.isDefaultConstructor) {
+          classElementHolder.addConstructor(constructor);
+          removedConstructors.remove(constructor);
+        }
+      }
+    }
+    // Update the delta.
+    classDelta.removedAccessors.addAll(removedAccessors);
+    classDelta.removedConstructors.addAll(removedConstructors);
+    classDelta.removedMethods.addAll(removedMethods);
+    // Update ClassElement.
+    classElement.accessors = classElementHolder.accessors;
+    classElement.constructors = classElementHolder.constructors;
+    classElement.methods = classElementHolder.methods;
+    classElementHolder.validate();
+    // Ensure at least a default synthetic constructor.
+    if (classElement.constructors.isEmpty) {
+      ConstructorElementImpl constructor =
+          new ConstructorElementImpl.forNode(null);
+      constructor.synthetic = true;
+      classElement.constructors = <ConstructorElement>[constructor];
+    }
+    // OK
+    return classDelta;
+  }
+
   void _processDirectives() {
     Map<String, Directive> oldDirectiveMap = new HashMap<String, Directive>();
     for (Directive oldDirective in oldUnit.directives) {
@@ -136,9 +309,14 @@
   void _processUnitMembers() {
     Map<String, CompilationUnitMember> oldNodeMap =
         new HashMap<String, CompilationUnitMember>();
+    Map<String, ClassDeclaration> nameToOldClassMap =
+        new HashMap<String, ClassDeclaration>();
     for (CompilationUnitMember oldNode in oldUnit.declarations) {
       String code = TokenUtils.getFullCode(oldNode);
       oldNodeMap[code] = oldNode;
+      if (oldNode is ClassDeclaration) {
+        nameToOldClassMap[oldNode.name.name] = oldNode;
+      }
     }
     // Prepare all old top-level elements.
     Set<Element> removedElements = new Set<Element>();
@@ -151,29 +329,41 @@
     // Replace new nodes with the identical old nodes.
     for (CompilationUnitMember newNode in newUnit.declarations) {
       String code = TokenUtils.getFullCode(newNode);
-      // Prepare an old node.
       CompilationUnitMember oldNode = oldNodeMap[code];
+      // Add the new element.
       if (oldNode == null) {
+        // Compute a delta for the class.
+        if (newNode is ClassDeclaration) {
+          ClassDeclaration oldClass = nameToOldClassMap[newNode.name.name];
+          if (oldClass != null) {
+            ClassElementDelta delta = _processClassMembers(oldClass, newNode);
+            unitDelta.classDeltas.add(delta);
+            _addElementToUnitHolder(delta.element);
+            removedElements.remove(delta.element);
+            continue;
+          }
+        }
+        // Add the new node elements.
         List<Element> elements = _getElements(newNode);
-        elements.forEach(_addElementToHolder);
+        elements.forEach(_addElementToUnitHolder);
         elements.forEach(unitDelta.addedDeclarations.add);
         continue;
       }
       // Do replacement.
       _replaceNode(newNode, oldNode);
       List<Element> elements = _getElements(oldNode);
-      elements.forEach(_addElementToHolder);
+      elements.forEach(_addElementToUnitHolder);
       elements.forEach(removedElements.remove);
     }
     unitDelta.removedDeclarations.addAll(removedElements);
     // Update CompilationUnitElement.
-    unitElement.accessors = holder.accessors;
-    unitElement.enums = holder.enums;
-    unitElement.functions = holder.functions;
-    unitElement.typeAliases = holder.typeAliases;
-    unitElement.types = holder.types;
-    unitElement.topLevelVariables = holder.topLevelVariables;
-    holder.validate();
+    unitElement.accessors = unitElementHolder.accessors;
+    unitElement.enums = unitElementHolder.enums;
+    unitElement.functions = unitElementHolder.functions;
+    unitElement.typeAliases = unitElementHolder.typeAliases;
+    unitElement.types = unitElementHolder.types;
+    unitElement.topLevelVariables = unitElementHolder.topLevelVariables;
+    unitElementHolder.validate();
   }
 
   /**
@@ -213,23 +403,29 @@
    */
   static List<Element> _getElements(AstNode node) {
     List<Element> elements = <Element>[];
-    if (node is TopLevelVariableDeclaration) {
-      VariableDeclarationList variableList = node.variables;
+    void addPropertyAccessors(VariableDeclarationList variableList) {
       if (variableList != null) {
         for (VariableDeclaration variable in variableList.variables) {
-          TopLevelVariableElement element = variable.element;
-          elements.add(element);
-          if (element.getter != null) {
-            elements.add(element.getter);
-          }
-          if (element.setter != null) {
-            elements.add(element.setter);
+          PropertyInducingElement element = variable.element;
+          if (element != null) {
+            elements.add(element);
+            if (element.getter != null) {
+              elements.add(element.getter);
+            }
+            if (element.setter != null) {
+              elements.add(element.setter);
+            }
           }
         }
       }
-    } else if (node is PartDirective || node is PartOfDirective) {} else if (node
-        is Directive &&
-        node.element != null) {
+    }
+    if (node is FieldDeclaration) {
+      addPropertyAccessors(node.fields);
+    } else if (node is TopLevelVariableDeclaration) {
+      addPropertyAccessors(node.variables);
+    } else if (node is PartDirective || node is PartOfDirective) {
+      // Ignore.
+    } else if (node is Directive && node.element != null) {
       elements.add(node.element);
     } else if (node is Declaration && node.element != null) {
       Element element = node.element;
@@ -273,8 +469,21 @@
         copyTokenOffsets(offsetMap, (oldToken as CommentToken).parent,
             (newToken as CommentToken).parent, oldEndToken, newEndToken);
       }
+      // Update (otherwise unlinked) reference tokens in documentation.
+      if (oldToken is DocumentationCommentToken &&
+          newToken is DocumentationCommentToken) {
+        List<Token> oldReferences = oldToken.references;
+        List<Token> newReferences = newToken.references;
+        assert(oldReferences.length == newReferences.length);
+        for (int i = 0; i < oldReferences.length; i++) {
+          copyTokenOffsets(offsetMap, oldReferences[i], newReferences[i],
+              oldEndToken, newEndToken);
+        }
+      }
+      // Update documentation tokens.
       while (oldToken != null) {
         offsetMap[oldToken.offset] = newToken.offset;
+        offsetMap[oldToken.end] = newToken.end;
         oldToken.offset = newToken.offset;
         oldToken = oldToken.next;
         newToken = newToken.next;
@@ -290,7 +499,12 @@
             newToken.precedingComments, oldEndToken, newEndToken);
       }
       offsetMap[oldToken.offset] = newToken.offset;
+      offsetMap[oldToken.end] = newToken.end;
       oldToken.offset = newToken.offset;
+      if (oldToken.type == TokenType.EOF) {
+        assert(newToken.type == TokenType.EOF);
+        break;
+      }
       if (oldToken == oldEndToken) {
         assert(newToken == newEndToken);
         break;
@@ -355,18 +569,57 @@
   _UpdateElementOffsetsVisitor(this.map);
 
   void visitElement(Element element) {
-    if (element is CompilationUnitElement) {
+    if (element is LibraryElement) {
       return;
     }
     if (element.isSynthetic) {
       return;
     }
-    int oldOffset = element.nameOffset;
-    int newOffset = map[oldOffset];
-    assert(newOffset != null);
-    (element as ElementImpl).nameOffset = newOffset;
-    if (element is! LibraryElement) {
-      super.visitElement(element);
+    if (element is ElementImpl) {
+      // name offset
+      {
+        int oldOffset = element.nameOffset;
+        int newOffset = map[oldOffset];
+        assert(newOffset != null);
+        element.nameOffset = newOffset;
+      }
+      // code range
+      {
+        int oldOffset = element.codeOffset;
+        if (oldOffset != null) {
+          int oldEnd = oldOffset + element.codeLength;
+          int newOffset = map[oldOffset];
+          int newEnd = map[oldEnd];
+          assert(newOffset != null);
+          assert(newEnd != null);
+          int newLength = newEnd - newOffset;
+          element.setCodeRange(newOffset, newLength);
+        }
+      }
+      // visible range
+      if (element is LocalElement) {
+        SourceRange oldVisibleRange = (element as LocalElement).visibleRange;
+        if (oldVisibleRange != null) {
+          int oldOffset = oldVisibleRange.offset;
+          int oldLength = oldVisibleRange.length;
+          int oldEnd = oldOffset + oldLength;
+          int newOffset = map[oldOffset];
+          int newEnd = map[oldEnd];
+          assert(newOffset != null);
+          assert(newEnd != null);
+          int newLength = newEnd - newOffset;
+          if (newOffset != oldOffset || newLength != oldLength) {
+            if (element is FunctionElementImpl) {
+              element.setVisibleRange(newOffset, newLength);
+            } else if (element is LocalVariableElementImpl) {
+              element.setVisibleRange(newOffset, newLength);
+            } else if (element is ParameterElementImpl) {
+              element.setVisibleRange(newOffset, newLength);
+            }
+          }
+        }
+      }
     }
+    super.visitElement(element);
   }
 }
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 36d7e4c..9124fe8 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.27.4-alpha.12
+version: 0.27.4-alpha.13
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
diff --git a/pkg/analyzer/test/file_system/resource_uri_resolver_test.dart b/pkg/analyzer/test/file_system/resource_uri_resolver_test.dart
index 53247c1..6ca5bbe 100644
--- a/pkg/analyzer/test/file_system/resource_uri_resolver_test.dart
+++ b/pkg/analyzer/test/file_system/resource_uri_resolver_test.dart
@@ -29,6 +29,11 @@
     provider.newFolder('/folder');
   }
 
+  void test_creation() {
+    expect(provider, isNotNull);
+    expect(resolver, isNotNull);
+  }
+
   void test_resolveAbsolute_file() {
     var uri = new Uri(scheme: 'file', path: '/test.dart');
     Source source = resolver.resolveAbsolute(uri);
@@ -43,12 +48,18 @@
     expect(source, isNull);
   }
 
-  void test_resolveAbsolute_notFile() {
+  void test_resolveAbsolute_notFile_httpsUri() {
     var uri = new Uri(scheme: 'https', path: '127.0.0.1/test.dart');
     Source source = resolver.resolveAbsolute(uri);
     expect(source, isNull);
   }
 
+  void test_resolveAbsolute_notFile_dartUri() {
+    var uri = new Uri(scheme: 'dart', path: 'core');
+    Source source = resolver.resolveAbsolute(uri);
+    expect(source, isNull);
+  }
+
   void test_restoreAbsolute() {
     var uri = new Uri(scheme: 'file', path: '/test.dart');
     Source source = resolver.resolveAbsolute(uri);
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index ba1ba00..925eb8d 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -8,6 +8,7 @@
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart' hide ConstantEvaluator;
@@ -53,7 +54,6 @@
   runReflectiveTests(ExitDetectorTest);
   runReflectiveTests(ExitDetectorTest2);
   runReflectiveTests(FileBasedSourceTest);
-  runReflectiveTests(FileUriResolverTest);
   runReflectiveTests(ResolveRelativeUriTest);
   runReflectiveTests(SDKLibrariesReaderTest);
   runReflectiveTests(UriKindTest);
@@ -4186,7 +4186,8 @@
   }
 
   void test_getEncoding() {
-    SourceFactory factory = new SourceFactory([new FileUriResolver()]);
+    SourceFactory factory = new SourceFactory(
+        [new ResourceUriResolver(PhysicalResourceProvider.INSTANCE)]);
     String fullPath = "/does/not/exist.dart";
     JavaFile file = FileUtilities2.createFile(fullPath);
     FileBasedSource source = new FileBasedSource(file);
@@ -4305,41 +4306,6 @@
 }
 
 @reflectiveTest
-class FileUriResolverTest {
-  void test_creation() {
-    expect(new FileUriResolver(), isNotNull);
-  }
-
-  void test_resolve_file() {
-    UriResolver resolver = new FileUriResolver();
-    Source result = resolver
-        .resolveAbsolute(parseUriWithException("file:/does/not/exist.dart"));
-    expect(result, isNotNull);
-    expect(result.fullName,
-        FileUtilities2.createFile("/does/not/exist.dart").getAbsolutePath());
-  }
-
-  void test_resolve_nonFile() {
-    UriResolver resolver = new FileUriResolver();
-    Source result =
-        resolver.resolveAbsolute(parseUriWithException("dart:core"));
-    expect(result, isNull);
-  }
-
-  void test_restore() {
-    UriResolver resolver = new FileUriResolver();
-    Uri uri = parseUriWithException('file:///foo/bar.dart');
-    Source source = resolver.resolveAbsolute(uri);
-    expect(source, isNotNull);
-    expect(resolver.restoreAbsolute(source), uri);
-    expect(
-        resolver.restoreAbsolute(
-            new NonExistingSource(source.fullName, null, null)),
-        uri);
-  }
-}
-
-@reflectiveTest
 class ResolveRelativeUriTest {
   void test_resolveRelative_dart_dartUri() {
     Uri uri = parseUriWithException('dart:foo');
diff --git a/pkg/analyzer/test/generated/bazel_test.dart b/pkg/analyzer/test/generated/bazel_test.dart
new file mode 100644
index 0000000..bac7e66
--- /dev/null
+++ b/pkg/analyzer/test/generated/bazel_test.dart
@@ -0,0 +1,104 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.test.generated.bazel_test;
+
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/src/generated/bazel.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:unittest/unittest.dart';
+
+import '../reflective_tests.dart';
+import '../utils.dart';
+
+main() {
+  initializeTestEnvironment();
+  runReflectiveTests(BazelFileUriResolverTest);
+}
+
+@reflectiveTest
+class BazelFileUriResolverTest {
+  MemoryResourceProvider provider;
+  Folder workspace;
+  List<Folder> buildDirs;
+  ResourceUriResolver resolver;
+
+  void setUp() {
+    provider = new MemoryResourceProvider();
+    workspace = provider.newFolder('/workspace');
+    buildDirs = [provider.newFolder('/workspace/one'), provider.newFolder('/workspace/two')];
+    resolver = new BazelFileUriResolver(provider, workspace, buildDirs);
+    provider.newFile('/workspace/test.dart', '');
+    provider.newFile('/workspace/one/gen1.dart', '');
+    provider.newFile('/workspace/two/gen2.dart', '');
+  }
+
+  void test_creation() {
+    expect(provider, isNotNull);
+    expect(workspace, isNotNull);
+    expect(buildDirs, isNotNull);
+    expect(buildDirs.length, 2);
+    expect(resolver, isNotNull);
+  }
+
+  void test_resolveAbsolute_file() {
+    var uri = new Uri(scheme: 'file', path: '/workspace/test.dart');
+    Source source = resolver.resolveAbsolute(uri);
+    expect(source, isNotNull);
+    expect(source.exists(), isTrue);
+    expect(source.fullName, '/workspace/test.dart');
+  }
+
+  void test_resolveAbsolute_folder() {
+    var uri = new Uri(scheme: 'file', path: '/workspace');
+    Source source = resolver.resolveAbsolute(uri);
+    expect(source, isNull);
+  }
+
+  void test_resolveAbsolute_notFile_httpsUri() {
+    var uri = new Uri(scheme: 'https', path: '127.0.0.1/test.dart');
+    Source source = resolver.resolveAbsolute(uri);
+    expect(source, isNull);
+  }
+
+  void test_resolveAbsolute_notFile_dartUri() {
+    var uri = new Uri(scheme: 'dart', path: 'core');
+    Source source = resolver.resolveAbsolute(uri);
+    expect(source, isNull);
+  }
+
+  void test_resolveAbsolute_generated_file_exists_one() {
+    var uri = new Uri(scheme: 'file', path: '/workspace/gen1.dart');
+    Source source = resolver.resolveAbsolute(uri);
+    expect(source, isNotNull);
+    expect(source.exists(), isTrue);
+    expect(source.fullName, '/workspace/one/gen1.dart');
+  }
+
+  void test_resolveAbsolute_generated_file_exists_two() {
+    var uri = new Uri(scheme: 'file', path: '/workspace/gen2.dart');
+    Source source = resolver.resolveAbsolute(uri);
+    expect(source, isNotNull);
+    expect(source.exists(), isTrue);
+    expect(source.fullName, '/workspace/two/gen2.dart');
+  }
+
+  void test_resolveAbsolute_generated_file_does_not_exist_three() {
+    var uri = new Uri(scheme: 'file', path: '/workspace/gen3.dart');
+    Source source = resolver.resolveAbsolute(uri);
+    expect(source, isNull);
+  }
+
+  void test_restoreAbsolute() {
+    var uri = new Uri(scheme: 'file', path: '/workspace/test.dart');
+    Source source = resolver.resolveAbsolute(uri);
+    expect(source, isNotNull);
+    expect(resolver.restoreAbsolute(source), uri);
+    expect(
+        resolver.restoreAbsolute(
+            new NonExistingSource(source.fullName, null, null)),
+        uri);
+  }
+}
diff --git a/pkg/analyzer/test/generated/engine_test.dart b/pkg/analyzer/test/generated/engine_test.dart
index e679466..b3ceaa5 100644
--- a/pkg/analyzer/test/generated/engine_test.dart
+++ b/pkg/analyzer/test/generated/engine_test.dart
@@ -8,6 +8,7 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:analyzer/source/embedder.dart';
 import 'package:analyzer/src/cancelable_future.dart';
 import 'package:analyzer/src/context/cache.dart';
@@ -234,6 +235,7 @@
     return null;
   }
 
+  @deprecated
   @override
   EmbedderYamlLocator get embedderYamlLocator {
     fail("Unexpected invocation of get embedderYamlLocator");
@@ -247,6 +249,17 @@
   }
 
   @override
+  ResolverProvider get fileResolverProvider {
+    fail("Unexpected invocation of fileResolverProvider");
+    return null;
+  }
+
+  @override
+  void set fileResolverProvider(ResolverProvider resolverProvider) {
+    fail("Unexpected invocation of fileResolverProvider");
+  }
+
+  @override
   List<Source> get htmlSources {
     fail("Unexpected invocation of getHtmlSources");
     return null;
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index bd01388..645ebeb 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -377,6 +377,49 @@
     verify([source]);
   }
 
+  void test_deadCode_deadFinalReturnInCase() {
+    Source source = addSource(r'''
+f() {
+  switch (true) {
+  case true:
+    try {
+      int a = 1;
+    } finally {
+      return;
+    }
+    return;
+  default:
+    break;
+  }
+}''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [HintCode.DEAD_CODE]);
+    verify([source]);
+  }
+
+  void test_deadCode_deadFinalStatementInCase() {
+    Source source = addSource(r'''
+f() {
+  switch (true) {
+  case true:
+    try {
+      int a = 1;
+    } finally {
+      return;
+    }
+    int b = 1;
+  default:
+    break;
+  }
+}''');
+    computeLibrarySourceErrors(source);
+    // A single dead statement at the end of a switch case that is not a
+    // terminating statement will yield two errors.
+    assertErrors(source,
+        [HintCode.DEAD_CODE, StaticWarningCode.CASE_BLOCK_NOT_TERMINATED]);
+    verify([source]);
+  }
+
   void test_deadCode_deadOperandLHS_and() {
     Source source = addSource(r'''
 f() {
@@ -473,49 +516,6 @@
     verify([source]);
   }
 
-  void test_deadCode_deadFinalReturnInCase() {
-    Source source = addSource(r'''
-f() {
-  switch (true) {
-  case true:
-    try {
-      int a = 1;
-    } finally {
-      return;
-    }
-    return;
-  default:
-    break;
-  }
-}''');
-    computeLibrarySourceErrors(source);
-    assertErrors(source, [HintCode.DEAD_CODE]);
-    verify([source]);
-  }
-
-  void test_deadCode_deadFinalStatementInCase() {
-    Source source = addSource(r'''
-f() {
-  switch (true) {
-  case true:
-    try {
-      int a = 1;
-    } finally {
-      return;
-    }
-    int b = 1;
-  default:
-    break;
-  }
-}''');
-    computeLibrarySourceErrors(source);
-    // A single dead statement at the end of a switch case that is not a
-    // terminating statement will yield two errors.
-    assertErrors(source,
-        [HintCode.DEAD_CODE, StaticWarningCode.CASE_BLOCK_NOT_TERMINATED]);
-    verify([source]);
-  }
-
   void test_deadCode_statementAfterBreak_inWhileStatement() {
     Source source = addSource(r'''
 f(v) {
@@ -1196,6 +1196,27 @@
     verify([source]);
   }
 
+  void test_invalidUseOfProtectedMember_in_docs_OK() {
+    Source source = addSource(r'''
+import 'package:meta/meta.dart';
+
+class A {
+  @protected
+  int a() => c;
+  @protected
+  int get b => a();
+  @protected
+  int c = 42;
+}
+
+/// OK: [A.a], [A.b], [A.c].
+f() {}
+''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_invalidUseOfProtectedMember_message() {
     Source source = addSource(r'''
 import 'package:meta/meta.dart';
diff --git a/pkg/analyzer/test/generated/incremental_resolver_test.dart b/pkg/analyzer/test/generated/incremental_resolver_test.dart
index 518f8c8a..03309dd 100644
--- a/pkg/analyzer/test/generated/incremental_resolver_test.dart
+++ b/pkg/analyzer/test/generated/incremental_resolver_test.dart
@@ -3556,10 +3556,13 @@
   }
 
   static void _shiftTokens(Token token, int afterOffset, int delta) {
-    while (token.type != TokenType.EOF) {
-      if (token.offset >= afterOffset) {
+    while (true) {
+      if (token.offset > afterOffset) {
         token.applyDelta(delta);
       }
+      if (token.type == TokenType.EOF) {
+        break;
+      }
       token = token.next;
     }
   }
diff --git a/pkg/analyzer/test/generated/source_factory_test.dart b/pkg/analyzer/test/generated/source_factory_test.dart
index 9932cf8..9aa7fc1 100644
--- a/pkg/analyzer/test/generated/source_factory_test.dart
+++ b/pkg/analyzer/test/generated/source_factory_test.dart
@@ -7,6 +7,7 @@
 import 'dart:convert';
 
 import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine, Logger;
@@ -40,7 +41,9 @@
 
 void runPackageMapTests() {
   final Uri baseUri = new Uri.file('test/base');
-  final List<UriResolver> testResolvers = [new FileUriResolver()];
+  final List<UriResolver> testResolvers = [
+    new ResourceUriResolver(PhysicalResourceProvider.INSTANCE)
+  ];
 
   Packages createPackageMap(Uri base, String configFileContents) {
     List<int> bytes = UTF8.encode(configFileContents);
diff --git a/pkg/analyzer/test/generated/test_all.dart b/pkg/analyzer/test/generated/test_all.dart
index 3536c10..96e525e 100644
--- a/pkg/analyzer/test/generated/test_all.dart
+++ b/pkg/analyzer/test/generated/test_all.dart
@@ -8,6 +8,7 @@
 
 import '../utils.dart';
 import 'all_the_rest_test.dart' as all_the_rest;
+import 'bazel_test.dart' as bazel_test;
 import 'checked_mode_compile_time_error_code_test.dart'
     as checked_mode_compile_time_error_code_test;
 import 'compile_time_error_code_test.dart' as compile_time_error_code_test;
@@ -41,6 +42,7 @@
   initializeTestEnvironment();
   group('generated tests', () {
     all_the_rest.main();
+    bazel_test.main();
     checked_mode_compile_time_error_code_test.main();
     compile_time_error_code_test.main();
     constant_test.main();
diff --git a/pkg/analyzer/test/generated/utilities_test.dart b/pkg/analyzer/test/generated/utilities_test.dart
index 344612b..a4de8c0 100644
--- a/pkg/analyzer/test/generated/utilities_test.dart
+++ b/pkg/analyzer/test/generated/utilities_test.dart
@@ -59,6 +59,12 @@
       fail('Failed to copy token: ${first.lexeme} (${first.offset})');
       return false;
     }
+    if (first is TokenWithComment) {
+      CommentToken comment = first.precedingComments;
+      if (comment.parent != first) {
+        fail('Failed to link the comment "$comment" with the token "$first".');
+      }
+    }
     return super.isEqualTokens(first, second);
   }
 }
@@ -77,6 +83,13 @@
     _assertCloneUnitMember('@A.c() main() {}');
   }
 
+  void test_visitAnnotation_withComment() {
+    CompilationUnitMember clazz =
+        _parseUnitMember('/** comment */ @deprecated class A {}');
+    Annotation annotation = clazz.metadata.single;
+    _assertClone(annotation);
+  }
+
   void test_visitArgumentList() {
     _assertCloneExpression('m(a, b)');
   }
diff --git a/pkg/analyzer/test/source/embedder_test.dart b/pkg/analyzer/test/source/embedder_test.dart
index 80072b8..c16e6f9 100644
--- a/pkg/analyzer/test/source/embedder_test.dart
+++ b/pkg/analyzer/test/source/embedder_test.dart
@@ -9,149 +9,59 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/source/embedder.dart';
+import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:path/path.dart' as path;
 import 'package:unittest/unittest.dart';
 
+import '../reflective_tests.dart';
 import '../resource_utils.dart';
 import '../utils.dart';
 
 main() {
-  group('EmbedderUriResolverTest', () {
-    setUp(() {
-      initializeTestEnvironment(path.context);
-      buildResourceProvider();
-    });
-    tearDown(() {
-      initializeTestEnvironment();
-      clearResourceProvider();
-    });
-    test('test_NullEmbedderYamls', () {
-      var resolver = new EmbedderUriResolver(null);
-      expect(resolver.length, 0);
-    });
-    test('test_NoEmbedderYamls', () {
-      var locator = new EmbedderYamlLocator({
-        'fox': [pathTranslator.getResource('/empty')]
-      });
-      expect(locator.embedderYamls.length, 0);
-    });
-    test('test_EmbedderYaml', () {
-      var locator = new EmbedderYamlLocator({
-        'fox': [pathTranslator.getResource('/tmp')]
-      });
-      var resolver = new EmbedderUriResolver(locator.embedderYamls);
-
-      expectResolved(dartUri, posixPath) {
-        Source source = resolver.resolveAbsolute(Uri.parse(dartUri));
-        expect(source, isNotNull, reason: dartUri);
-        expect(source.fullName, posixToOSPath(posixPath));
-      }
-
-      // We have five mappings.
-      expect(resolver.length, 5);
-      // Check that they map to the correct paths.
-      expectResolved('dart:core', '/tmp/core.dart');
-      expectResolved('dart:fox', '/tmp/slippy.dart');
-      expectResolved('dart:bear', '/tmp/grizzly.dart');
-      expectResolved('dart:relative', '/relative.dart');
-      expectResolved('dart:deep', '/tmp/deep/directory/file.dart');
-    });
-    test('test_BadYAML', () {
-      var locator = new EmbedderYamlLocator(null);
-      locator.addEmbedderYaml(null, r'''{{{,{{}}},}}''');
-      expect(locator.embedderYamls.length, 0);
-    });
-    test('test_restoreAbsolute', () {
-      var locator = new EmbedderYamlLocator({
-        'fox': [pathTranslator.getResource('/tmp')]
-      });
-      var resolver = new EmbedderUriResolver(locator.embedderYamls);
-
-      expectRestore(String dartUri, [String expected]) {
-        var parsedUri = Uri.parse(dartUri);
-        var source = resolver.resolveAbsolute(parsedUri);
-        expect(source, isNotNull);
-        // Restore source's uri.
-        var restoreUri = resolver.restoreAbsolute(source);
-        expect(restoreUri, isNotNull, reason: dartUri);
-        // Verify that it is 'dart:fox'.
-        expect(restoreUri.toString(), expected ?? dartUri);
-        List<String> split = (expected ?? dartUri).split(':');
-        expect(restoreUri.scheme, split[0]);
-        expect(restoreUri.path, split[1]);
-      }
-
-      expectRestore('dart:deep');
-      expectRestore('dart:deep/file.dart', 'dart:deep');
-      expectRestore('dart:deep/part.dart');
-      expectRestore('dart:deep/deep/file.dart');
-    });
-
-    test('test_EmbedderSdk_fromFileUri', () {
-      var locator = new EmbedderYamlLocator({
-        'fox': [pathTranslator.getResource('/tmp')]
-      });
-      var resolver = new EmbedderUriResolver(locator.embedderYamls);
-      var sdk = resolver.dartSdk;
-
-      expectSource(String posixPath, String dartUri) {
-        var uri = Uri.parse(posixToOSFileUri(posixPath));
-        var source = sdk.fromFileUri(uri);
-        expect(source, isNotNull, reason: posixPath);
-        expect(source.uri.toString(), dartUri);
-        expect(source.fullName, posixToOSPath(posixPath));
-      }
-
-      expectSource('/tmp/slippy.dart', 'dart:fox');
-      expectSource('/tmp/deep/directory/file.dart', 'dart:deep');
-      expectSource('/tmp/deep/directory/part.dart', 'dart:deep/part.dart');
-    });
-    test('test_EmbedderSdk_getSdkLibrary', () {
-      var locator = new EmbedderYamlLocator({
-        'fox': [pathTranslator.getResource('/tmp')]
-      });
-      var resolver = new EmbedderUriResolver(locator.embedderYamls);
-      var sdk = resolver.dartSdk;
-      var lib = sdk.getSdkLibrary('dart:fox');
-      expect(lib, isNotNull);
-      expect(lib.path, posixToOSPath('/tmp/slippy.dart'));
-      expect(lib.shortName, 'dart:fox');
-    });
-    test('test_EmbedderSdk_mapDartUri', () {
-      var locator = new EmbedderYamlLocator({
-        'fox': [pathTranslator.getResource('/tmp')]
-      });
-      var resolver = new EmbedderUriResolver(locator.embedderYamls);
-      var sdk = resolver.dartSdk;
-
-      expectSource(String dartUri, String posixPath) {
-        var source = sdk.mapDartUri(dartUri);
-        expect(source, isNotNull, reason: posixPath);
-        expect(source.uri.toString(), dartUri);
-        expect(source.fullName, posixToOSPath(posixPath));
-      }
-
-      expectSource('dart:core', '/tmp/core.dart');
-      expectSource('dart:fox', '/tmp/slippy.dart');
-      expectSource('dart:deep', '/tmp/deep/directory/file.dart');
-      expectSource('dart:deep/part.dart', '/tmp/deep/directory/part.dart');
-    });
-  });
+  runReflectiveTests(DartUriResolverTest);
+  runReflectiveTests(EmbedderSdkTest);
+  runReflectiveTests(EmbedderUriResolverTest);
+  runReflectiveTests(EmbedderYamlLocatorTest);
 }
 
-TestPathTranslator pathTranslator;
-ResourceProvider resourceProvider;
+@reflectiveTest
+class DartUriResolverTest extends EmbedderRelatedTest {
+  void test_embedderYaml() {
+    EmbedderYamlLocator locator = new EmbedderYamlLocator({
+      'fox': [pathTranslator.getResource('/tmp')]
+    });
+    EmbedderSdk sdk = new EmbedderSdk(locator.embedderYamls);
+    DartUriResolver resolver = new DartUriResolver(sdk);
 
-buildResourceProvider() {
-  var rawProvider = new MemoryResourceProvider(isWindows: isWindows);
-  resourceProvider = new TestResourceProvider(rawProvider);
-  pathTranslator = new TestPathTranslator(rawProvider)
-    ..newFolder('/empty')
-    ..newFolder('/tmp')
-    ..newFile(
-        '/tmp/_embedder.yaml',
-        r'''
+    void expectResolved(dartUri, posixPath) {
+      Source source = resolver.resolveAbsolute(Uri.parse(dartUri));
+      expect(source, isNotNull, reason: dartUri);
+      expect(source.fullName, posixToOSPath(posixPath));
+    }
+    // Check that they map to the correct paths.
+    expectResolved('dart:core', '/tmp/core.dart');
+    expectResolved('dart:fox', '/tmp/slippy.dart');
+    expectResolved('dart:bear', '/tmp/grizzly.dart');
+    expectResolved('dart:relative', '/relative.dart');
+    expectResolved('dart:deep', '/tmp/deep/directory/file.dart');
+  }
+}
+
+abstract class EmbedderRelatedTest {
+  TestPathTranslator pathTranslator;
+  ResourceProvider resourceProvider;
+
+  buildResourceProvider() {
+    MemoryResourceProvider rawProvider =
+        new MemoryResourceProvider(isWindows: isWindows);
+    resourceProvider = new TestResourceProvider(rawProvider);
+    pathTranslator = new TestPathTranslator(rawProvider)
+      ..newFolder('/empty')
+      ..newFolder('/tmp')
+      ..newFile(
+          '/tmp/_embedder.yaml',
+          r'''
 embedded_libs:
   "dart:core" : "core.dart"
   "dart:fox": "slippy.dart"
@@ -160,9 +70,161 @@
   "dart:deep": "deep/directory/file.dart"
   "fart:loudly": "nomatter.dart"
 ''');
+  }
+
+  clearResourceProvider() {
+    resourceProvider = null;
+    pathTranslator = null;
+  }
+
+  void setUp() {
+    initializeTestEnvironment(path.context);
+    buildResourceProvider();
+  }
+
+  void tearDown() {
+    initializeTestEnvironment();
+    clearResourceProvider();
+  }
 }
 
-clearResourceProvider() {
-  resourceProvider = null;
-  pathTranslator = null;
+@reflectiveTest
+class EmbedderSdkTest extends EmbedderRelatedTest {
+  void test_creation() {
+    EmbedderYamlLocator locator = new EmbedderYamlLocator({
+      'fox': [pathTranslator.getResource('/tmp')]
+    });
+    EmbedderSdk sdk = new EmbedderSdk(locator.embedderYamls);
+
+    expect(sdk.urlMappings, hasLength(5));
+  }
+
+  void test_fromFileUri() {
+    EmbedderYamlLocator locator = new EmbedderYamlLocator({
+      'fox': [pathTranslator.getResource('/tmp')]
+    });
+    EmbedderSdk sdk = new EmbedderSdk(locator.embedderYamls);
+
+    expectSource(String posixPath, String dartUri) {
+      Uri uri = Uri.parse(posixToOSFileUri(posixPath));
+      Source source = sdk.fromFileUri(uri);
+      expect(source, isNotNull, reason: posixPath);
+      expect(source.uri.toString(), dartUri);
+      expect(source.fullName, posixToOSPath(posixPath));
+    }
+
+    expectSource('/tmp/slippy.dart', 'dart:fox');
+    expectSource('/tmp/deep/directory/file.dart', 'dart:deep');
+    expectSource('/tmp/deep/directory/part.dart', 'dart:deep/part.dart');
+  }
+
+  void test_getSdkLibrary() {
+    EmbedderYamlLocator locator = new EmbedderYamlLocator({
+      'fox': [pathTranslator.getResource('/tmp')]
+    });
+    EmbedderSdk sdk = new EmbedderSdk(locator.embedderYamls);
+
+    SdkLibrary lib = sdk.getSdkLibrary('dart:fox');
+    expect(lib, isNotNull);
+    expect(lib.path, posixToOSPath('/tmp/slippy.dart'));
+    expect(lib.shortName, 'dart:fox');
+  }
+
+  void test_mapDartUri() {
+    EmbedderYamlLocator locator = new EmbedderYamlLocator({
+      'fox': [pathTranslator.getResource('/tmp')]
+    });
+    EmbedderSdk sdk = new EmbedderSdk(locator.embedderYamls);
+
+    void expectSource(String dartUri, String posixPath) {
+      Source source = sdk.mapDartUri(dartUri);
+      expect(source, isNotNull, reason: posixPath);
+      expect(source.uri.toString(), dartUri);
+      expect(source.fullName, posixToOSPath(posixPath));
+    }
+
+    expectSource('dart:core', '/tmp/core.dart');
+    expectSource('dart:fox', '/tmp/slippy.dart');
+    expectSource('dart:deep', '/tmp/deep/directory/file.dart');
+    expectSource('dart:deep/part.dart', '/tmp/deep/directory/part.dart');
+  }
+}
+
+@reflectiveTest
+class EmbedderUriResolverTest extends EmbedderRelatedTest {
+  void test_embedderYaml() {
+    var locator = new EmbedderYamlLocator({
+      'fox': [pathTranslator.getResource('/tmp')]
+    });
+    var resolver = new EmbedderUriResolver(locator.embedderYamls);
+
+    expectResolved(dartUri, posixPath) {
+      Source source = resolver.resolveAbsolute(Uri.parse(dartUri));
+      expect(source, isNotNull, reason: dartUri);
+      expect(source.fullName, posixToOSPath(posixPath));
+    }
+
+    // We have five mappings.
+    expect(resolver, hasLength(5));
+    // Check that they map to the correct paths.
+    expectResolved('dart:core', '/tmp/core.dart');
+    expectResolved('dart:fox', '/tmp/slippy.dart');
+    expectResolved('dart:bear', '/tmp/grizzly.dart');
+    expectResolved('dart:relative', '/relative.dart');
+    expectResolved('dart:deep', '/tmp/deep/directory/file.dart');
+  }
+
+  void test_nullEmbedderYamls() {
+    var resolver = new EmbedderUriResolver(null);
+    expect(resolver, hasLength(0));
+  }
+
+  void test_restoreAbsolute() {
+    var locator = new EmbedderYamlLocator({
+      'fox': [pathTranslator.getResource('/tmp')]
+    });
+    var resolver = new EmbedderUriResolver(locator.embedderYamls);
+
+    expectRestore(String dartUri, [String expected]) {
+      var parsedUri = Uri.parse(dartUri);
+      var source = resolver.resolveAbsolute(parsedUri);
+      expect(source, isNotNull);
+      // Restore source's uri.
+      var restoreUri = resolver.restoreAbsolute(source);
+      expect(restoreUri, isNotNull, reason: dartUri);
+      // Verify that it is 'dart:fox'.
+      expect(restoreUri.toString(), expected ?? dartUri);
+      List<String> split = (expected ?? dartUri).split(':');
+      expect(restoreUri.scheme, split[0]);
+      expect(restoreUri.path, split[1]);
+    }
+
+    expectRestore('dart:deep');
+    expectRestore('dart:deep/file.dart', 'dart:deep');
+    expectRestore('dart:deep/part.dart');
+    expectRestore('dart:deep/deep/file.dart');
+  }
+}
+
+@reflectiveTest
+class EmbedderYamlLocatorTest extends EmbedderRelatedTest {
+  void test_empty() {
+    EmbedderYamlLocator locator = new EmbedderYamlLocator({
+      'fox': [pathTranslator.getResource('/empty')]
+    });
+    expect(locator.embedderYamls, hasLength(0));
+  }
+
+  void test_invalid() {
+    EmbedderYamlLocator locator = new EmbedderYamlLocator(null);
+    locator.addEmbedderYaml(null, r'''{{{,{{}}},}}''');
+    expect(locator.embedderYamls, hasLength(0));
+  }
+
+  void test_valid() {
+    EmbedderYamlLocator locator = new EmbedderYamlLocator({
+      'fox': [pathTranslator.getResource('/tmp')]
+    });
+    expect(locator.embedderYamls, hasLength(1));
+  }
 }
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index 89cbfbc..33bd37b 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -4174,6 +4174,43 @@
     expect(info.userToDependsOn['f'], unorderedEquals(['A']));
   }
 
+  test_referencedNames_topLevelVariable() {
+    ReferencedNames info = _computeReferencedNames('''
+A v = new B(c);
+''');
+    expect(info.names, unorderedEquals(['A', 'B', 'c']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['v']));
+    expect(info.userToDependsOn['v'], unorderedEquals(['A', 'B', 'c']));
+  }
+
+  test_referencedNames_topLevelVariable_multiple() {
+    ReferencedNames info = _computeReferencedNames('''
+A v1 = new B(c), v2 = new D<E>(f);
+''');
+    expect(info.names, unorderedEquals(['A', 'B', 'c', 'D', 'E', 'f']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['v1', 'v2']));
+    expect(info.userToDependsOn['v1'], unorderedEquals(['A', 'B', 'c']));
+    expect(info.userToDependsOn['v2'], unorderedEquals(['A', 'D', 'E', 'f']));
+  }
+
+  test_referencedNames_unit_classTypeAlias() {
+    ReferencedNames info = _computeReferencedNames('''
+class U = A with B implements C;
+''');
+    expect(info.names, unorderedEquals(['A', 'B', 'C']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
+    expect(info.userToDependsOn['U'], unorderedEquals(['A', 'B', 'C']));
+  }
+
+  test_referencedNames_unit_classTypeAlias_typeParameters() {
+    ReferencedNames info = _computeReferencedNames('''
+class U<T1, T2 extends D> = A<T1> with B<T2> implements C<T1, T2>;
+''');
+    expect(info.names, unorderedEquals(['A', 'B', 'C', 'D']));
+    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
+    expect(info.userToDependsOn['U'], unorderedEquals(['A', 'B', 'C', 'D']));
+  }
+
   test_referencedNames_unit_function() {
     ReferencedNames info = _computeReferencedNames('''
 A f(B b) {
diff --git a/pkg/analyzer/test/src/task/incremental_element_builder_test.dart b/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
index 8ef225a..975de87 100644
--- a/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
+++ b/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
@@ -6,8 +6,12 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/task/dart.dart';
 import 'package:analyzer/src/task/incremental_element_builder.dart';
+import 'package:analyzer/task/dart.dart';
 import 'package:unittest/unittest.dart';
 
 import '../../reflective_tests.dart';
@@ -36,6 +40,631 @@
     return newCode.substring(node.offset, node.end);
   }
 
+  test_classDelta_constructor_0to1() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {
+}
+''');
+    helper.initOld(oldUnit);
+    ConstructorElement oldConstructorElement =
+        helper.element.unnamedConstructor;
+    _buildNewUnit(r'''
+class A {
+  A.a();
+}
+''');
+    helper.initNew(newUnit, unitDelta);
+    // nodes
+    ClassMember newConstructorNode = helper.newMembers[0];
+    // elements
+    ConstructorElement newConstructorElement = newConstructorNode.element;
+    expect(newConstructorElement, isNotNull);
+    expect(newConstructorElement.name, 'a');
+    // classElement.constructors
+    ClassElement classElement = helper.element;
+    expect(classElement.constructors, unorderedEquals([newConstructorElement]));
+    // verify delta
+    expect(helper.delta.addedConstructors,
+        unorderedEquals([newConstructorElement]));
+    expect(helper.delta.removedConstructors,
+        unorderedEquals([oldConstructorElement]));
+    expect(helper.delta.addedAccessors, isEmpty);
+    expect(helper.delta.removedAccessors, isEmpty);
+    expect(helper.delta.addedMethods, isEmpty);
+    expect(helper.delta.removedMethods, isEmpty);
+  }
+
+  test_classDelta_constructor_1to0() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {
+  A.a();
+}
+''');
+    helper.initOld(oldUnit);
+    ConstructorElement oldElementA = helper.element.getNamedConstructor('a');
+    _buildNewUnit(r'''
+class A {
+}
+''');
+    helper.initNew(newUnit, unitDelta);
+    // classElement.constructors
+    ClassElement classElement = helper.element;
+    {
+      List<ConstructorElement> constructors = classElement.constructors;
+      expect(constructors, hasLength(1));
+      expect(constructors[0].isDefaultConstructor, isTrue);
+      expect(constructors[0].isSynthetic, isTrue);
+    }
+    // verify delta
+    expect(helper.delta.addedConstructors, unorderedEquals([]));
+    expect(helper.delta.removedConstructors, unorderedEquals([oldElementA]));
+    expect(helper.delta.addedAccessors, isEmpty);
+    expect(helper.delta.removedAccessors, isEmpty);
+    expect(helper.delta.addedMethods, isEmpty);
+    expect(helper.delta.removedMethods, isEmpty);
+  }
+
+  test_classDelta_constructor_1to2() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {
+  A.a();
+}
+''');
+    helper.initOld(oldUnit);
+    _buildNewUnit(r'''
+class A {
+  A.a();
+  A.b();
+}
+''');
+    helper.initNew(newUnit, unitDelta);
+    // nodes
+    ClassMember nodeA = helper.newMembers[0];
+    ClassMember nodeB = helper.newMembers[1];
+    expect(nodeA, same(helper.oldMembers[0]));
+    // elements
+    ConstructorElement elementA = nodeA.element;
+    ConstructorElement elementB = nodeB.element;
+    expect(elementA, isNotNull);
+    expect(elementB, isNotNull);
+    expect(elementA.name, 'a');
+    expect(elementB.name, 'b');
+    // classElement.constructors
+    ClassElement classElement = helper.element;
+    expect(classElement.constructors, unorderedEquals([elementA, elementB]));
+    // verify delta
+    expect(helper.delta.addedConstructors, unorderedEquals([elementB]));
+    expect(helper.delta.removedConstructors, unorderedEquals([]));
+    expect(helper.delta.addedAccessors, isEmpty);
+    expect(helper.delta.removedAccessors, isEmpty);
+    expect(helper.delta.addedMethods, isEmpty);
+    expect(helper.delta.removedMethods, isEmpty);
+  }
+
+  test_classDelta_constructor_2to1() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {
+  A.a();
+  A.b();
+}
+''');
+    helper.initOld(oldUnit);
+    ConstructorElement oldElementA = helper.element.getNamedConstructor('a');
+    _buildNewUnit(r'''
+class A {
+  A.b();
+}
+''');
+    helper.initNew(newUnit, unitDelta);
+    // nodes
+    ClassMember nodeB = helper.newMembers[0];
+    expect(nodeB, same(helper.oldMembers[1]));
+    // elements
+    ConstructorElement elementB = nodeB.element;
+    expect(elementB, isNotNull);
+    expect(elementB.name, 'b');
+    // classElement.constructors
+    ClassElement classElement = helper.element;
+    expect(classElement.constructors, unorderedEquals([elementB]));
+    // verify delta
+    expect(helper.delta.addedConstructors, unorderedEquals([]));
+    expect(helper.delta.removedConstructors, unorderedEquals([oldElementA]));
+    expect(helper.delta.addedAccessors, isEmpty);
+    expect(helper.delta.removedAccessors, isEmpty);
+    expect(helper.delta.addedMethods, isEmpty);
+    expect(helper.delta.removedMethods, isEmpty);
+  }
+
+  test_classDelta_constructor_2to2_reorder() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {
+  A.a();
+  A.b();
+}
+''');
+    helper.initOld(oldUnit);
+    _buildNewUnit(r'''
+class A {
+  A.b();
+  A.a();
+}
+''');
+    helper.initNew(newUnit, unitDelta);
+    // nodes
+    ClassMember nodeB = helper.newMembers[0];
+    ClassMember nodeA = helper.newMembers[1];
+    expect(nodeB, same(helper.oldMembers[1]));
+    expect(nodeA, same(helper.oldMembers[0]));
+    // elements
+    ConstructorElement elementB = nodeB.element;
+    ConstructorElement elementA = nodeA.element;
+    expect(elementB, isNotNull);
+    expect(elementA, isNotNull);
+    expect(elementB.name, 'b');
+    expect(elementA.name, 'a');
+    // classElement.constructors
+    ClassElement classElement = helper.element;
+    expect(classElement.constructors, unorderedEquals([elementB, elementA]));
+    // verify delta
+    expect(helper.delta.addedConstructors, isEmpty);
+    expect(helper.delta.removedConstructors, isEmpty);
+    expect(helper.delta.addedAccessors, isEmpty);
+    expect(helper.delta.removedAccessors, isEmpty);
+    expect(helper.delta.addedMethods, isEmpty);
+    expect(helper.delta.removedMethods, isEmpty);
+  }
+
+  test_classDelta_field_add() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {
+  int aaa;
+}
+''');
+    helper.initOld(oldUnit);
+    _buildNewUnit(r'''
+class A {
+  int aaa;
+  int bbb;
+}
+''');
+    helper.initNew(newUnit, unitDelta);
+    // nodes
+    FieldDeclaration nodeA = helper.newMembers[0];
+    FieldDeclaration newNodeB = helper.newMembers[1];
+    List<VariableDeclaration> newFieldsB = newNodeB.fields.variables;
+    expect(nodeA, same(helper.oldMembers[0]));
+    expect(newFieldsB, hasLength(1));
+    // elements
+    FieldElement newFieldElementB = newFieldsB[0].name.staticElement;
+    expect(newFieldElementB.name, 'bbb');
+    // verify delta
+    expect(helper.delta.addedConstructors, isEmpty);
+    expect(helper.delta.removedConstructors, isEmpty);
+    expect(helper.delta.addedAccessors,
+        unorderedEquals([newFieldElementB.getter, newFieldElementB.setter]));
+    expect(helper.delta.removedAccessors, isEmpty);
+    expect(helper.delta.addedMethods, isEmpty);
+    expect(helper.delta.removedMethods, isEmpty);
+  }
+
+  test_classDelta_field_changeName() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {
+  int aaa;
+  int bbb;
+}
+''');
+    helper.initOld(oldUnit);
+    _buildNewUnit(r'''
+class A {
+  int aaa2;
+  int bbb;
+}
+''');
+    helper.initNew(newUnit, unitDelta);
+    // nodes
+    FieldDeclaration oldNodeA = helper.oldMembers[0];
+    FieldDeclaration newNodeA = helper.newMembers[0];
+    List<VariableDeclaration> oldFieldsA = oldNodeA.fields.variables;
+    List<VariableDeclaration> newFieldsA = newNodeA.fields.variables;
+    expect(oldFieldsA, hasLength(1));
+    expect(newFieldsA, hasLength(1));
+    FieldDeclaration nodeB = helper.newMembers[1];
+    expect(nodeB, same(helper.oldMembers[1]));
+    // elements
+    FieldElement oldFieldElementA = oldFieldsA[0].name.staticElement;
+    FieldElement newFieldElementA = newFieldsA[0].name.staticElement;
+    expect(oldFieldElementA.name, 'aaa');
+    expect(newFieldElementA.name, 'aaa2');
+    // verify delta
+    expect(helper.delta.addedConstructors, isEmpty);
+    expect(helper.delta.removedConstructors, isEmpty);
+    expect(helper.delta.addedAccessors,
+        unorderedEquals([newFieldElementA.getter, newFieldElementA.setter]));
+    expect(helper.delta.removedAccessors,
+        unorderedEquals([oldFieldElementA.getter, oldFieldElementA.setter]));
+    expect(helper.delta.addedMethods, isEmpty);
+    expect(helper.delta.removedMethods, isEmpty);
+  }
+
+  test_classDelta_field_remove() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {
+  int aaa;
+  int bbb;
+}
+''');
+    helper.initOld(oldUnit);
+    _buildNewUnit(r'''
+class A {
+  int aaa;
+}
+''');
+    helper.initNew(newUnit, unitDelta);
+    // nodes
+    FieldDeclaration nodeA = helper.newMembers[0];
+    FieldDeclaration oldNodeB = helper.oldMembers[1];
+    List<VariableDeclaration> oldFieldsB = oldNodeB.fields.variables;
+    expect(nodeA, same(helper.oldMembers[0]));
+    // elements
+    FieldElement oldFieldElementB = oldFieldsB[0].name.staticElement;
+    expect(oldFieldElementB.name, 'bbb');
+    // verify delta
+    expect(helper.delta.addedConstructors, isEmpty);
+    expect(helper.delta.removedConstructors, isEmpty);
+    expect(helper.delta.addedAccessors, isEmpty);
+    expect(helper.delta.removedAccessors,
+        unorderedEquals([oldFieldElementB.getter, oldFieldElementB.setter]));
+    expect(helper.delta.addedMethods, isEmpty);
+    expect(helper.delta.removedMethods, isEmpty);
+  }
+
+  test_classDelta_getter_add() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {
+  int get aaa => 1;
+}
+''');
+    helper.initOld(oldUnit);
+    _buildNewUnit(r'''
+class A {
+  int get aaa => 1;
+  int get bbb => 2;
+}
+''');
+    helper.initNew(newUnit, unitDelta);
+    // nodes
+    MethodDeclaration nodeA = helper.oldMembers[0];
+    MethodDeclaration newNodeB = helper.newMembers[1];
+    expect(nodeA, same(helper.oldMembers[0]));
+    // elements
+    PropertyAccessorElement elementA = nodeA.element;
+    PropertyAccessorElement newElementB = newNodeB.element;
+    expect(elementA, isNotNull);
+    expect(elementA.name, 'aaa');
+    expect(newElementB, isNotNull);
+    expect(newElementB.name, 'bbb');
+    // verify delta
+    expect(helper.delta.addedConstructors, isEmpty);
+    expect(helper.delta.removedConstructors, isEmpty);
+    expect(helper.delta.addedAccessors, unorderedEquals([newElementB]));
+    expect(helper.delta.removedAccessors, isEmpty);
+    expect(helper.delta.addedMethods, isEmpty);
+    expect(helper.delta.removedMethods, isEmpty);
+  }
+
+  test_classDelta_getter_remove() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {
+  int get aaa => 1;
+  int get bbb => 2;
+}
+''');
+    helper.initOld(oldUnit);
+    _buildNewUnit(r'''
+class A {
+  int get aaa => 1;
+}
+''');
+    helper.initNew(newUnit, unitDelta);
+    // nodes
+    MethodDeclaration nodeA = helper.oldMembers[0];
+    MethodDeclaration oldNodeB = helper.oldMembers[1];
+    expect(nodeA, same(helper.oldMembers[0]));
+    // elements
+    PropertyAccessorElement elementA = nodeA.element;
+    PropertyAccessorElement oldElementB = oldNodeB.element;
+    expect(elementA, isNotNull);
+    expect(elementA.name, 'aaa');
+    // verify delta
+    expect(helper.delta.addedConstructors, isEmpty);
+    expect(helper.delta.removedConstructors, isEmpty);
+    expect(helper.delta.addedAccessors, isEmpty);
+    expect(helper.delta.removedAccessors, unorderedEquals([oldElementB]));
+    expect(helper.delta.addedMethods, isEmpty);
+    expect(helper.delta.removedMethods, isEmpty);
+  }
+
+  test_classDelta_method_add() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {
+  aaa() {}
+}
+''');
+    helper.initOld(oldUnit);
+    _buildNewUnit(r'''
+class A {
+  aaa() {}
+  bbb() {}
+}
+''');
+    helper.initNew(newUnit, unitDelta);
+    // nodes
+    ClassMember nodeA = helper.oldMembers[0];
+    ClassMember newNodeB = helper.newMembers[1];
+    expect(nodeA, same(helper.oldMembers[0]));
+    // elements
+    MethodElement elementA = nodeA.element;
+    MethodElement newElementB = newNodeB.element;
+    expect(elementA, isNotNull);
+    expect(elementA.name, 'aaa');
+    expect(newElementB, isNotNull);
+    expect(newElementB.name, 'bbb');
+    // verify delta
+    expect(helper.delta.addedConstructors, isEmpty);
+    expect(helper.delta.removedConstructors, isEmpty);
+    expect(helper.delta.addedAccessors, isEmpty);
+    expect(helper.delta.removedAccessors, isEmpty);
+    expect(helper.delta.addedMethods, unorderedEquals([newElementB]));
+    expect(helper.delta.removedMethods, isEmpty);
+  }
+
+  test_classDelta_method_addParameter() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {
+  aaa() {}
+  bbb() {}
+}
+''');
+    helper.initOld(oldUnit);
+    _buildNewUnit(r'''
+class A {
+  aaa(int p) {}
+  bbb() {}
+}
+''');
+    helper.initNew(newUnit, unitDelta);
+    // nodes
+    ClassMember oldNodeA = helper.oldMembers[0];
+    ClassMember newNodeA = helper.newMembers[0];
+    ClassMember nodeB = helper.newMembers[1];
+    expect(newNodeA, isNot(same(oldNodeA)));
+    expect(nodeB, same(helper.oldMembers[1]));
+    // elements
+    MethodElement oldElementA = oldNodeA.element;
+    MethodElement newElementA = newNodeA.element;
+    MethodElement elementB = nodeB.element;
+    expect(newElementA, isNotNull);
+    expect(newElementA.name, 'aaa');
+    expect(oldElementA.parameters, hasLength(0));
+    expect(newElementA.parameters, hasLength(1));
+    expect(elementB, isNotNull);
+    expect(elementB.name, 'bbb');
+    // verify delta
+    expect(helper.delta.addedConstructors, isEmpty);
+    expect(helper.delta.removedConstructors, isEmpty);
+    expect(helper.delta.addedAccessors, isEmpty);
+    expect(helper.delta.removedAccessors, isEmpty);
+    expect(helper.delta.addedMethods, unorderedEquals([newElementA]));
+    expect(helper.delta.removedMethods, unorderedEquals([oldElementA]));
+  }
+
+  test_classDelta_method_changeName() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {
+  aaa(int ap) {
+    int av = 1;
+    af(afp) {}
+  }
+  bbb(int bp) {
+    int bv = 1;
+    bf(bfp) {}
+  }
+}
+''');
+    helper.initOld(oldUnit);
+    ConstructorElement oldConstructor = helper.element.unnamedConstructor;
+    _buildNewUnit(r'''
+class A {
+  aaa2(int ap) {
+    int av = 1;
+    af(afp) {}
+  }
+  bbb(int bp) {
+    int bv = 1;
+    bf(bfp) {}
+  }
+}
+''');
+    helper.initNew(newUnit, unitDelta);
+    expect(helper.element.unnamedConstructor, same(oldConstructor));
+    // nodes
+    ClassMember oldNodeA = helper.oldMembers[0];
+    ClassMember newNodeA = helper.newMembers[0];
+    ClassMember nodeB = helper.newMembers[1];
+    expect(nodeB, same(helper.oldMembers[1]));
+    // elements
+    MethodElement oldElementA = oldNodeA.element;
+    MethodElement newElementA = newNodeA.element;
+    MethodElement elementB = nodeB.element;
+    expect(newElementA, isNotNull);
+    expect(newElementA.name, 'aaa2');
+    expect(elementB, isNotNull);
+    expect(elementB.name, 'bbb');
+    // verify delta
+    expect(helper.delta.addedConstructors, isEmpty);
+    expect(helper.delta.removedConstructors, isEmpty);
+    expect(helper.delta.addedAccessors, isEmpty);
+    expect(helper.delta.removedAccessors, isEmpty);
+    expect(helper.delta.addedMethods, unorderedEquals([newElementA]));
+    expect(helper.delta.removedMethods, unorderedEquals([oldElementA]));
+  }
+
+  test_classDelta_method_remove() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {
+  aaa() {}
+  bbb() {}
+}
+''');
+    helper.initOld(oldUnit);
+    _buildNewUnit(r'''
+class A {
+  aaa() {}
+}
+''');
+    helper.initNew(newUnit, unitDelta);
+    // nodes
+    ClassMember nodeA = helper.oldMembers[0];
+    ClassMember oldNodeB = helper.oldMembers[1];
+    expect(nodeA, same(helper.oldMembers[0]));
+    // elements
+    MethodElement elementA = nodeA.element;
+    MethodElement oldElementB = oldNodeB.element;
+    expect(elementA, isNotNull);
+    expect(elementA.name, 'aaa');
+    // verify delta
+    expect(helper.delta.addedConstructors, isEmpty);
+    expect(helper.delta.removedConstructors, isEmpty);
+    expect(helper.delta.addedAccessors, isEmpty);
+    expect(helper.delta.removedAccessors, isEmpty);
+    expect(helper.delta.addedMethods, isEmpty);
+    expect(helper.delta.removedMethods, unorderedEquals([oldElementB]));
+  }
+
+  test_classDelta_method_removeParameter() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {
+  aaa(int p) {}
+  bbb() {}
+}
+''');
+    helper.initOld(oldUnit);
+    _buildNewUnit(r'''
+class A {
+  aaa() {}
+  bbb() {}
+}
+''');
+    helper.initNew(newUnit, unitDelta);
+    // nodes
+    ClassMember oldNodeA = helper.oldMembers[0];
+    ClassMember newNodeA = helper.newMembers[0];
+    ClassMember nodeB = helper.newMembers[1];
+    expect(newNodeA, isNot(same(oldNodeA)));
+    expect(nodeB, same(helper.oldMembers[1]));
+    // elements
+    MethodElement oldElementA = oldNodeA.element;
+    MethodElement newElementA = newNodeA.element;
+    MethodElement elementB = nodeB.element;
+    expect(newElementA, isNotNull);
+    expect(newElementA.name, 'aaa');
+    expect(oldElementA.parameters, hasLength(1));
+    expect(newElementA.parameters, hasLength(0));
+    expect(elementB, isNotNull);
+    expect(elementB.name, 'bbb');
+    // verify delta
+    expect(helper.delta.addedConstructors, isEmpty);
+    expect(helper.delta.removedConstructors, isEmpty);
+    expect(helper.delta.addedAccessors, isEmpty);
+    expect(helper.delta.removedAccessors, isEmpty);
+    expect(helper.delta.addedMethods, unorderedEquals([newElementA]));
+    expect(helper.delta.removedMethods, unorderedEquals([oldElementA]));
+  }
+
+  test_classDelta_setter_add() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {
+  void set aaa(int pa) {}
+}
+''');
+    helper.initOld(oldUnit);
+    _buildNewUnit(r'''
+class A {
+  void set aaa(int pa) {}
+  void set bbb(int pb) {}
+}
+''');
+    helper.initNew(newUnit, unitDelta);
+    // nodes
+    MethodDeclaration nodeA = helper.oldMembers[0];
+    MethodDeclaration newNodeB = helper.newMembers[1];
+    expect(nodeA, same(helper.oldMembers[0]));
+    // elements
+    PropertyAccessorElement elementA = nodeA.element;
+    PropertyAccessorElement newElementB = newNodeB.element;
+    expect(elementA, isNotNull);
+    expect(elementA.name, 'aaa=');
+    expect(newElementB, isNotNull);
+    expect(newElementB.name, 'bbb=');
+    // verify delta
+    expect(helper.delta.addedConstructors, isEmpty);
+    expect(helper.delta.removedConstructors, isEmpty);
+    expect(helper.delta.addedAccessors, unorderedEquals([newElementB]));
+    expect(helper.delta.removedAccessors, isEmpty);
+    expect(helper.delta.addedMethods, isEmpty);
+    expect(helper.delta.removedMethods, isEmpty);
+  }
+
+  test_classDelta_setter_remove() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {
+  void set aaa(int pa) {}
+  void set bbb(int pb) {}
+}
+''');
+    helper.initOld(oldUnit);
+    _buildNewUnit(r'''
+class A {
+  void set aaa(int pa) {}
+}
+''');
+    helper.initNew(newUnit, unitDelta);
+    // nodes
+    MethodDeclaration nodeA = helper.oldMembers[0];
+    MethodDeclaration oldNodeB = helper.oldMembers[1];
+    expect(nodeA, same(helper.oldMembers[0]));
+    // elements
+    PropertyAccessorElement elementA = nodeA.element;
+    PropertyAccessorElement oldElementB = oldNodeB.element;
+    expect(elementA, isNotNull);
+    expect(elementA.name, 'aaa=');
+    // verify delta
+    expect(helper.delta.addedConstructors, isEmpty);
+    expect(helper.delta.removedConstructors, isEmpty);
+    expect(helper.delta.addedAccessors, isEmpty);
+    expect(helper.delta.removedAccessors, unorderedEquals([oldElementB]));
+    expect(helper.delta.addedMethods, isEmpty);
+    expect(helper.delta.removedMethods, isEmpty);
+  }
+
   test_directives_add() {
     _buildOldUnit(r'''
 library test;
@@ -679,6 +1308,18 @@
     builder.build();
     unitDelta = builder.unitDelta;
     expect(newUnit.element, unitElement);
+    // Flush all tokens, ASTs and elements.
+    context.analysisCache.flush((target, result) {
+      return result == TOKEN_STREAM ||
+          result == PARSED_UNIT ||
+          RESOLVED_UNIT_RESULTS.contains(result) ||
+          LIBRARY_ELEMENT_RESULTS.contains(result);
+    });
+    // Compute a new AST with built elements.
+    CompilationUnit newUnitFull = context.computeResult(
+        new LibrarySpecificUnit(source, source), RESOLVED_UNIT1);
+    expect(newUnitFull, isNot(same(newUnit)));
+    new _BuiltElementsValidator().isEqualNodes(newUnitFull, newUnit);
   }
 
   void _buildOldUnit(String oldCode, [Source libSource]) {
@@ -692,3 +1333,107 @@
     expect(unitElement, isNotNull);
   }
 }
+
+/**
+ * Compares tokens and ASTs, and built elements of declared identifiers.
+ */
+class _BuiltElementsValidator extends AstComparator {
+  @override
+  bool isEqualNodes(AstNode expected, AstNode actual) {
+    // Elements of constructors must be linked to the elements of the
+    // corresponding enclosing classes.
+    if (actual is ConstructorDeclaration) {
+      ConstructorElement actualConstructorElement = actual.element;
+      ClassDeclaration actualClassNode = actual.parent;
+      expect(actualConstructorElement.enclosingElement,
+          same(actualClassNode.element));
+    }
+    // Compare nodes.
+    bool result = super.isEqualNodes(expected, actual);
+    if (!result) {
+      fail('|$actual| != expected |$expected|');
+    }
+    // Verify that declared identifiers have equal elements.
+    if (expected is SimpleIdentifier && actual is SimpleIdentifier) {
+      if (expected.inDeclarationContext()) {
+        expect(actual.inDeclarationContext(), isTrue);
+        Element expectedElement = expected.staticElement;
+        Element actualElement = actual.staticElement;
+        _verifyElement(expectedElement, actualElement, 'staticElement');
+      }
+    }
+    return true;
+  }
+
+  void _verifyElement(Element expected, Element actual, String desc) {
+    if (expected == null && actual == null) {
+      return;
+    }
+    // Prefixes are built later.
+    if (actual is PrefixElement) {
+      return;
+    }
+    // Compare properties.
+    _verifyEqual('$desc name', expected.name, actual.name);
+    _verifyEqual('$desc nameOffset', expected.nameOffset, actual.nameOffset);
+    if (expected is ElementImpl && actual is ElementImpl) {
+      _verifyEqual('$desc codeOffset', expected.codeOffset, actual.codeOffset);
+      _verifyEqual('$desc codeLength', expected.codeLength, actual.codeLength);
+    }
+    if (expected is LocalElement && actual is LocalElement) {
+      _verifyEqual(
+          '$desc visibleRange', expected.visibleRange, actual.visibleRange);
+    }
+    _verifyEqual('$desc documentationComment', expected.documentationComment,
+        actual.documentationComment);
+    {
+      var expectedEnclosing = expected.enclosingElement;
+      var actualEnclosing = actual.enclosingElement;
+      if (expectedEnclosing != null) {
+        expect(actualEnclosing, isNotNull, reason: '$desc enclosingElement');
+        _verifyElement(expectedEnclosing, actualEnclosing,
+            '${expectedEnclosing.name}.$desc');
+      }
+    }
+  }
+
+  void _verifyEqual(String name, expected, actual) {
+    if (actual != expected) {
+      fail('$name\nExpected: $expected\n  Actual: $actual');
+    }
+  }
+}
+
+class _ClassDeltaHelper {
+  final String name;
+
+  ClassElementDelta delta;
+  ClassElement element;
+  List<ClassMember> oldMembers;
+  List<ClassMember> newMembers;
+
+  _ClassDeltaHelper(this.name);
+
+  void initNew(CompilationUnit newUnit, CompilationUnitElementDelta unitDelta) {
+    ClassDeclaration newClass = _findClassNode(newUnit, name);
+    expect(newClass, isNotNull);
+    newMembers = newClass.members.toList();
+    for (ClassElementDelta delta in unitDelta.classDeltas) {
+      if (delta.element.name == name) {
+        this.delta = delta;
+      }
+    }
+    expect(this.delta, isNotNull, reason: 'No delta for class: $name');
+  }
+
+  void initOld(CompilationUnit oldUnit) {
+    ClassDeclaration oldClass = _findClassNode(oldUnit, name);
+    expect(oldClass, isNotNull);
+    element = oldClass.element;
+    oldMembers = oldClass.members.toList();
+  }
+
+  ClassDeclaration _findClassNode(CompilationUnit unit, String name) =>
+      unit.declarations.singleWhere((unitMember) =>
+          unitMember is ClassDeclaration && unitMember.name.name == name);
+}
diff --git a/pkg/analyzer/tool/summary/build_sdk_summaries.dart b/pkg/analyzer/tool/summary/build_sdk_summaries.dart
index fc7ec0e..bf6d8b5 100644
--- a/pkg/analyzer/tool/summary/build_sdk_summaries.dart
+++ b/pkg/analyzer/tool/summary/build_sdk_summaries.dart
@@ -29,7 +29,7 @@
     // Prepare results.
     //
     String sdkPath = args.length > 2 ? args[2] : null;
-    _Output output = _buildMultipleOutputs(sdkPath, includeSpec);
+    SummaryOutput output = _buildMultipleOutputs(sdkPath, includeSpec);
     if (output == null) {
       exitCode = 1;
       return;
@@ -49,43 +49,32 @@
     //
     // Prepare results.
     //
-    _Output output = _buildMultipleOutputs(sdkPath, true);
+    SummaryOutput output = _buildMultipleOutputs(sdkPath, true);
     if (output == null) {
       exitCode = 1;
       return;
     }
+
     //
     // Write results.
     //
-    fb.Builder builder = new fb.Builder();
-    fb.Offset specSumOffset = builder.writeListUint8(output.spec.sum);
-    fb.Offset specIndexOffset = builder.writeListUint8(output.spec.index);
-    fb.Offset strongSumOffset = builder.writeListUint8(output.strong.sum);
-    fb.Offset strongIndexOffset = builder.writeListUint8(output.strong.index);
-    builder.startTable();
-    builder.addOffset(_FIELD_SPEC_SUM, specSumOffset);
-    builder.addOffset(_FIELD_SPEC_INDEX, specIndexOffset);
-    builder.addOffset(_FIELD_STRONG_SUM, strongSumOffset);
-    builder.addOffset(_FIELD_STRONG_INDEX, strongIndexOffset);
-    fb.Offset offset = builder.endTable();
-    new File(outputPath)
-        .writeAsBytesSync(builder.finish(offset), mode: FileMode.WRITE_ONLY);
+    output.write(outputPath);
   } else if (command == 'extract-spec-sum' && args.length == 3) {
     String inputPath = args[1];
     String outputPath = args[2];
-    _extractSingleOutput(inputPath, _FIELD_SPEC_SUM, outputPath);
+    _extractSingleOutput(inputPath, FIELD_SPEC_SUM, outputPath);
   } else if (command == 'extract-spec-index' && args.length == 3) {
     String inputPath = args[1];
     String outputPath = args[2];
-    _extractSingleOutput(inputPath, _FIELD_SPEC_INDEX, outputPath);
+    _extractSingleOutput(inputPath, FIELD_SPEC_INDEX, outputPath);
   } else if (command == 'extract-strong-sum' && args.length == 3) {
     String inputPath = args[1];
     String outputPath = args[2];
-    _extractSingleOutput(inputPath, _FIELD_STRONG_SUM, outputPath);
+    _extractSingleOutput(inputPath, FIELD_STRONG_SUM, outputPath);
   } else if (command == 'extract-strong-index' && args.length == 3) {
     String inputPath = args[1];
     String outputPath = args[2];
-    _extractSingleOutput(inputPath, _FIELD_STRONG_INDEX, outputPath);
+    _extractSingleOutput(inputPath, FIELD_STRONG_INDEX, outputPath);
   } else {
     _printUsage();
     exitCode = 1;
@@ -98,12 +87,7 @@
  */
 const BINARY_NAME = "build_sdk_summaries";
 
-const int _FIELD_SPEC_INDEX = 1;
-const int _FIELD_SPEC_SUM = 0;
-const int _FIELD_STRONG_INDEX = 3;
-const int _FIELD_STRONG_SUM = 2;
-
-_Output _buildMultipleOutputs(String sdkPath, bool includeSpec) {
+SummaryOutput _buildMultipleOutputs(String sdkPath, bool includeSpec) {
   //
   // Validate the SDK path.
   //
@@ -122,14 +106,15 @@
   //
   BuilderOutput spec = includeSpec ? _buildOutput(sdkPath, false) : null;
   BuilderOutput strong = _buildOutput(sdkPath, true);
-  return new _Output(spec, strong);
+  return new SummaryOutput(spec, strong);
 }
 
 BuilderOutput _buildOutput(String sdkPath, bool strongMode) {
   String modeName = strongMode ? 'strong' : 'spec';
   print('Generating $modeName mode summary and index.');
   Stopwatch sw = new Stopwatch()..start();
-  BuilderOutput output = new SummaryBuilder.forSdk(sdkPath, strongMode).build();
+  SummaryBuildConfig config = new SummaryBuildConfig(strongMode: strongMode);
+  BuilderOutput output = new SummaryBuilder.forSdk(sdkPath, config).build();
   print('\tDone in ${sw.elapsedMilliseconds} ms.');
   return output;
 }
@@ -169,10 +154,3 @@
   print('  extract-strong-index input_file output_file');
   print('    Extract the strong-mode index file.');
 }
-
-class _Output {
-  final BuilderOutput spec;
-  final BuilderOutput strong;
-
-  _Output(this.spec, this.strong);
-}
diff --git a/pkg/analyzer/tool/task_dependency_graph/generate.dart b/pkg/analyzer/tool/task_dependency_graph/generate.dart
index 2b904bb..fc88511 100644
--- a/pkg/analyzer/tool/task_dependency_graph/generate.dart
+++ b/pkg/analyzer/tool/task_dependency_graph/generate.dart
@@ -162,7 +162,7 @@
     List<UriResolver> uriResolvers = [
       new DartUriResolver(sdk),
       new PackageUriResolver(<JavaFile>[packagesDir]),
-      new FileUriResolver()
+      new ResourceUriResolver(PhysicalResourceProvider.INSTANCE)
     ];
     context.sourceFactory = new SourceFactory(uriResolvers);
     Source dartDartSource =
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index f6b3ddd..879ec69 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -257,7 +257,7 @@
           Driver.createAnalysisOptionsForCommandLineOptions(options);
       directorySdk.useSummary = !options.buildSummaryOnlyAst;
       sdk = directorySdk;
-      sdkBundle = directorySdk.getSummarySdkBundle();
+      sdkBundle = directorySdk.getSummarySdkBundle(options.strongMode);
     }
 
     // In AST mode include SDK bundle to avoid parsing SDK sources.
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index a116073..44cc1d1 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -10,7 +10,6 @@
 
 import 'package:analyzer/file_system/file_system.dart' as file_system;
 import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/plugin/embedded_resolver_provider.dart';
 import 'package:analyzer/plugin/options.dart';
 import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:analyzer/source/analysis_options_provider.dart';
@@ -90,9 +89,6 @@
   IncrementalAnalysisSession incrementalSession;
 
   @override
-  EmbeddedResolverProvider embeddedUriResolverProvider;
-
-  @override
   ResolverProvider packageResolverProvider;
 
   /// SDK instance.
@@ -346,25 +342,13 @@
           PhysicalResourceProvider.INSTANCE.getResource('.');
       UriResolver resolver = packageResolverProvider(folder);
       if (resolver != null) {
-        UriResolver sdkResolver;
-
-        // Check for a resolver provider.
-        if (embeddedUriResolverProvider != null) {
-          EmbedderUriResolver embedderUriResolver =
-              embeddedUriResolverProvider(folder);
-          if (embedderUriResolver != null && embedderUriResolver.length != 0) {
-            sdkResolver = embedderUriResolver;
-          }
-        }
-
-        // Default to a Dart URI resolver if no embedder is found.
-        sdkResolver ??= new DartUriResolver(sdk);
+        UriResolver sdkResolver = new DartUriResolver(sdk);
 
         // TODO(brianwilkerson) This doesn't handle sdk extensions.
         List<UriResolver> resolvers = <UriResolver>[
           sdkResolver,
           resolver,
-          new FileUriResolver()
+          new file_system.ResourceUriResolver(PhysicalResourceProvider.INSTANCE)
         ];
         return new SourceFactory(resolvers);
       }
@@ -404,16 +388,15 @@
     // 'dart:' URIs come first.
 
     // Setup embedding.
-    EmbedderUriResolver embedderUriResolver =
-        new EmbedderUriResolver(embedderMap);
-    if (embedderUriResolver.length == 0) {
+    EmbedderSdk embedderSdk = new EmbedderSdk(embedderMap);
+    if (embedderSdk.libraryMap.size() == 0) {
       // The embedder uri resolver has no mappings. Use the default Dart SDK
       // uri resolver.
       resolvers.add(new DartUriResolver(sdk));
     } else {
       // The embedder uri resolver has mappings, use it instead of the default
       // Dart SDK uri resolver.
-      resolvers.add(embedderUriResolver);
+      resolvers.add(new DartUriResolver(embedderSdk));
     }
 
     // Next SdkExts.
@@ -427,7 +410,8 @@
     }
 
     // Finally files.
-    resolvers.add(new FileUriResolver());
+    resolvers.add(
+        new file_system.ResourceUriResolver(PhysicalResourceProvider.INSTANCE));
 
     return new SourceFactory(resolvers, packageInfo.packages);
   }
@@ -501,7 +485,7 @@
 
     // Process embedders.
     Map<file_system.Folder, YamlMap> embedderMap =
-        _findEmbedders(packageInfo.packageMap);
+        new EmbedderYamlLocator(packageInfo.packageMap).embedderYamls;
 
     // Scan for SDK extenders.
     bool hasSdkExt = _hasSdkExt(packageInfo.packageMap?.values);
@@ -536,14 +520,6 @@
     return null;
   }
 
-  Map<file_system.Folder, YamlMap> _findEmbedders(
-      Map<String, List<file_system.Folder>> packageMap) {
-    EmbedderYamlLocator locator =
-        (_context as InternalAnalysisContext).embedderYamlLocator;
-    locator.refresh(packageMap);
-    return locator.embedderYamls;
-  }
-
   _PackageInfo _findPackages(CommandLineOptions options) {
     if (packageResolverProvider != null) {
       // The resolver provider will do all the work later.
@@ -627,8 +603,8 @@
   /// Analyze a single source.
   ErrorSeverity _runAnalyzer(Source source, CommandLineOptions options) {
     int startTime = currentTimeMillis();
-    AnalyzerImpl analyzer =
-        new AnalyzerImpl(_context, incrementalSession, source, options, stats, startTime);
+    AnalyzerImpl analyzer = new AnalyzerImpl(
+        _context, incrementalSession, source, options, stats, startTime);
     var errorSeverity = analyzer.analyzeSync();
     if (errorSeverity == ErrorSeverity.ERROR) {
       exitCode = errorSeverity.ordinal;
diff --git a/pkg/analyzer_cli/lib/starter.dart b/pkg/analyzer_cli/lib/starter.dart
index e42d39a..a784a75 100644
--- a/pkg/analyzer_cli/lib/starter.dart
+++ b/pkg/analyzer_cli/lib/starter.dart
@@ -4,7 +4,6 @@
 
 library analyzer_cli.starter;
 
-import 'package:analyzer/plugin/embedded_resolver_provider.dart';
 import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:analyzer_cli/src/driver.dart';
 import 'package:plugin/plugin.dart';
@@ -23,14 +22,6 @@
   factory CommandLineStarter() = Driver;
 
   /**
-   * Set the embedded resolver provider used to override the way embedded
-   * library URI's are resolved in some contexts. The provider should return
-   * `null` if the embedded library URI resolution scheme should be used
-   * instead.
-   */
-  void set embeddedUriResolverProvider(EmbeddedResolverProvider provider);
-
-  /**
    * Set the package resolver provider used to override the way package URI's
    * are resolved in some contexts. The provider should return `null` if the
    * default package resolution scheme should be used instead.
diff --git a/pkg/compiler/lib/src/common/backend_api.dart b/pkg/compiler/lib/src/common/backend_api.dart
index 5bbb2f0..c4c9020 100644
--- a/pkg/compiler/lib/src/common/backend_api.dart
+++ b/pkg/compiler/lib/src/common/backend_api.dart
@@ -131,11 +131,6 @@
   /// Called during codegen when [constant] has been used.
   void registerCompileTimeConstant(ConstantValue constant, Registry registry) {}
 
-  /// Called during resolution when a constant value for [metadata] on
-  /// [annotatedElement] has been evaluated.
-  void registerMetadataConstant(MetadataAnnotation metadata,
-      Element annotatedElement, Registry registry) {}
-
   /// Called to notify to the backend that a class is being instantiated.
   // TODO(johnniwinther): Remove this. It's only called once for each [cls] and
   // only with [Compiler.globalDependencies] as [registry].
@@ -278,23 +273,25 @@
   /// been scanned.
   Future onLibraryScanned(LibraryElement library, LibraryLoader loader) {
     // TODO(johnniwinther): Move this to [JavaScriptBackend].
-    if (canLibraryUseNative(library)) {
+    if (!compiler.serialization.isDeserialized(library)) {
+      if (canLibraryUseNative(library)) {
+        library.forEachLocalMember((Element element) {
+          if (element.isClass) {
+            checkNativeAnnotation(compiler, element);
+          }
+        });
+      }
+      checkJsInteropAnnotation(compiler, library);
       library.forEachLocalMember((Element element) {
-        if (element.isClass) {
-          checkNativeAnnotation(compiler, element);
+        checkJsInteropAnnotation(compiler, element);
+        if (element.isClass && isJsInterop(element)) {
+          ClassElement classElement = element;
+          classElement.forEachMember((_, memberElement) {
+            checkJsInteropAnnotation(compiler, memberElement);
+          });
         }
       });
     }
-    checkJsInteropAnnotation(compiler, library);
-    library.forEachLocalMember((Element element) {
-      checkJsInteropAnnotation(compiler, element);
-      if (element.isClass && isJsInterop(element)) {
-        ClassElement classElement = element;
-        classElement.forEachMember((_, memberElement) {
-          checkJsInteropAnnotation(compiler, memberElement);
-        });
-      }
-    });
     return new Future.value();
   }
 
diff --git a/pkg/compiler/lib/src/compile_time_constants.dart b/pkg/compiler/lib/src/compile_time_constants.dart
index bbabcf9..71962e8 100644
--- a/pkg/compiler/lib/src/compile_time_constants.dart
+++ b/pkg/compiler/lib/src/compile_time_constants.dart
@@ -165,7 +165,9 @@
   @override
   @deprecated
   ConstantValue getConstantValueForVariable(VariableElement element) {
-    return getConstantValue(initialVariableValues[element.declaration]);
+    ConstantExpression constant = initialVariableValues[element.declaration];
+    // TODO(johnniwinther): Support eager evaluation of the constant.
+    return constant != null ? getConstantValue(constant) : null;
   }
 
   ConstantExpression compileConstant(VariableElement element) {
@@ -320,8 +322,27 @@
     return constantValueMap.containsKey(expression);
   }
 
+  @override
   ConstantValue getConstantValue(ConstantExpression expression) {
-    return constantValueMap[expression];
+    assert(invariant(CURRENT_ELEMENT_SPANNABLE, expression != null,
+        message: "ConstantExpression is null in getConstantValue."));
+    // TODO(johnniwinther): ensure expressions have been evaluated at this
+    // point. This can't be enabled today due to dartbug.com/26406.
+    if (compiler.serialization.supportsDeserialization) {
+      evaluate(expression);
+    }
+    ConstantValue value = constantValueMap[expression];
+    if (value == null &&
+        expression != null &&
+        expression.kind == ConstantExpressionKind.ERRONEOUS) {
+      // TODO(johnniwinther): When the Dart constant system sees a constant
+      // expression as erroneous but the JavaScript constant system finds it ok
+      // we have store a constant value for the erroneous constant expression.
+      // Ensure the computed constant expressions are always the same; that only
+      // the constant values may be different.
+      value = new NullConstantValue();
+    }
+    return value;
   }
 
   ConstantExpression compileNode(Node node, TreeElements elements,
@@ -359,7 +380,7 @@
       Node node, TreeElements definitions,
       {bool isConst: true}) {
     ConstantExpression constant = definitions.getConstant(node);
-    if (constant != null && getConstantValue(constant) != null) {
+    if (constant != null && hasConstantValue(constant)) {
       return constant;
     }
     constant =
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 234c7e1..ced831b 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -1064,7 +1064,6 @@
           return const WorldImpact();
         }
         WorldImpact worldImpact = analyzeElement(element);
-        backend.onElementResolved(element);
         world.registerProcessedElement(element);
         return worldImpact;
       });
@@ -1659,7 +1658,12 @@
             Token from = astElement.node.getBeginToken();
             Token to = astElement.node.getEndToken();
             if (astElement.metadata.isNotEmpty) {
-              from = astElement.metadata.first.beginToken;
+              if (!astElement.metadata.first.hasNode) {
+                // We might try to report an error while parsing the metadata
+                // itself.
+                return true;
+              }
+              from = astElement.metadata.first.node.getBeginToken();
             }
             return validateToken(from, to);
           }
@@ -1740,8 +1744,7 @@
     } else if (node is Element) {
       return spanFromElement(node);
     } else if (node is MetadataAnnotation) {
-      Uri uri = node.annotatedElement.compilationUnit.script.resourceUri;
-      return spanFromTokens(node.beginToken, node.endToken, uri);
+      return node.sourcePosition;
     } else if (node is Local) {
       Local local = node;
       return spanFromElement(local.executableContext);
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index 37f5646..434fcfa 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -28,6 +28,7 @@
   R visitInterceptor(InterceptorConstantValue constant, A arg);
   R visitSynthetic(SyntheticConstantValue constant, A arg);
   R visitDeferred(DeferredConstantValue constant, A arg);
+  R visitNonConstant(NonConstantValue constant, A arg);
 }
 
 abstract class ConstantValue {
@@ -657,6 +658,8 @@
 }
 
 class ConstructedConstantValue extends ObjectConstantValue {
+  // TODO(johnniwinther): Make [fields] private to avoid misuse of the map
+  // ordering and mutability.
   final Map<FieldElement, ConstantValue> fields;
   final int hashCode;
 
@@ -751,7 +754,9 @@
 
   String toDartText() => 'deferred(${referenced.toDartText()})';
 
-  String toStructuredText() => 'DeferredConstant($referenced)';
+  String toStructuredText() {
+    return 'DeferredConstant(${referenced.toStructuredText()})';
+  }
 }
 
 /// A constant value resulting from a non constant or erroneous constant
@@ -762,7 +767,7 @@
 
   @override
   accept(ConstantValueVisitor visitor, arg) {
-    // TODO(johnniwinther): Should this be part of the visiting?
+    return visitor.visitNonConstant(this, arg);
   }
 
   @override
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 1402b1d8..d788549 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
@@ -475,6 +475,10 @@
     return '(Null)';
   }
 
+  String visitNonConstant(NonConstantValue constant, _) {
+    return '(NonConstant)';
+  }
+
   String visitInt(IntConstantValue constant, _) {
     return '(Int ${constant.toDartText()})';
   }
diff --git a/pkg/compiler/lib/src/elements/elements.dart b/pkg/compiler/lib/src/elements/elements.dart
index e5338de..06e0d00 100644
--- a/pkg/compiler/lib/src/elements/elements.dart
+++ b/pkg/compiler/lib/src/elements/elements.dart
@@ -1620,9 +1620,7 @@
   /// The front-end constant of this metadata annotation.
   ConstantExpression get constant;
   Element get annotatedElement;
-  int get resolutionState;
-  Token get beginToken;
-  Token get endToken;
+  SourceSpan get sourcePosition;
 
   bool get hasNode;
   Node get node;
diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
index e1fd271..248a9ef 100644
--- a/pkg/compiler/lib/src/elements/modelx.dart
+++ b/pkg/compiler/lib/src/elements/modelx.dart
@@ -3193,6 +3193,8 @@
    */
   Token get beginToken;
 
+  Token get endToken;
+
   MetadataAnnotationX([this.resolutionState = STATE_NOT_STARTED]);
 
   MetadataAnnotation ensureResolved(Resolution resolution) {
@@ -3208,6 +3210,11 @@
 
   Node parseNode(ParsingContext parsing);
 
+  SourceSpan get sourcePosition {
+    Uri uri = annotatedElement.compilationUnit.script.resourceUri;
+    return new SourceSpan.fromTokens(uri, beginToken, endToken);
+  }
+
   String toString() => 'MetadataAnnotation($constant, $resolutionState)';
 }
 
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index bcaec4a..01b258e 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -449,6 +449,7 @@
     bool includeLibrary =
         shouldIncludeElementDueToMirrors(lib, includedEnclosing: false);
     lib.forEachLocalMember((Element member) {
+      if (member.isInjected) return;
       if (member.isClass) {
         enqueueReflectiveElementsInClass(member, recents, includeLibrary);
       } else {
@@ -715,6 +716,7 @@
   /// Registers [element] as processed by the resolution enqueuer.
   void registerProcessedElement(AstElement element) {
     processedElements.add(element);
+    compiler.backend.onElementResolved(element);
   }
 
   /**
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index e04aa6c..7489914 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -40,6 +40,11 @@
   final Map<FunctionElement, int> _cachedDecisions =
       new Map<FunctionElement, int>();
 
+  /// Returns the current cache decision. This should only be used for testing.
+  int getCurrentCacheDecisionForTesting(Element element) {
+    return _cachedDecisions[element];
+  }
+
   // Returns `true`/`false` if we have a cached decision.
   // Returns `null` otherwise.
   bool canInline(FunctionElement element, {bool insideLoop}) {
@@ -449,6 +454,9 @@
   /// these constants must be registered.
   final List<Dependency> metadataConstants = <Dependency>[];
 
+  /// Set of elements for which metadata has been registered as dependencies.
+  final Set<Element> _registeredMetadata = new Set<Element>();
+
   /// List of elements that the user has requested for reflection.
   final Set<Element> targetsUsed = new Set<Element>();
 
@@ -1047,21 +1055,12 @@
         // helper so we register a use of that.
         registry.registerStaticUse(new StaticUse.staticInvoke(
             // TODO(johnniwinther): Find the right [CallStructure].
-
             helpers.createRuntimeType,
             null));
       }
     }
   }
 
-  void registerMetadataConstant(MetadataAnnotation metadata,
-      Element annotatedElement, Registry registry) {
-    assert(registry.isForResolution);
-    ConstantValue constant = constants.getConstantValueForMetadata(metadata);
-    registerCompileTimeConstant(constant, registry);
-    metadataConstants.add(new Dependency(constant, annotatedElement));
-  }
-
   void registerInstantiatedClass(
       ClassElement cls, Enqueuer enqueuer, Registry registry) {
     _processClass(cls, enqueuer, registry);
@@ -1272,6 +1271,7 @@
     super.onResolutionComplete();
     computeMembersNeededForReflection();
     rti.computeClassesNeedingRti();
+    _registeredMetadata.clear();
   }
 
   onTypeInferenceComplete() {
@@ -2304,17 +2304,67 @@
       reporter.log('Retaining metadata.');
 
       compiler.libraryLoader.libraries.forEach(retainMetadataOf);
-      for (Dependency dependency in metadataConstants) {
-        registerCompileTimeConstant(dependency.constant,
-            new EagerRegistry('EagerRegistry for ${dependency}', enqueuer));
-      }
-      if (!enqueuer.isResolutionQueue) {
+
+      if (enqueuer.isResolutionQueue && !enqueuer.queueIsClosed) {
+        /// Register the constant value of [metadata] as live in resolution.
+        void registerMetadataConstant(MetadataAnnotation metadata) {
+          ConstantValue constant =
+              constants.getConstantValueForMetadata(metadata);
+          Dependency dependency =
+              new Dependency(constant, metadata.annotatedElement);
+          metadataConstants.add(dependency);
+          registerCompileTimeConstant(dependency.constant,
+              new EagerRegistry('EagerRegistry for ${dependency}', enqueuer));
+        }
+
+        // TODO(johnniwinther): We should have access to all recently processed
+        // elements and process these instead.
+        processMetadata(compiler.enqueuer.resolution.processedElements,
+            registerMetadataConstant);
+      } else {
+        for (Dependency dependency in metadataConstants) {
+          registerCompileTimeConstant(dependency.constant,
+              new EagerRegistry('EagerRegistry for ${dependency}', enqueuer));
+        }
         metadataConstants.clear();
       }
     }
     return true;
   }
 
+  /// Call [registerMetadataConstant] on all metadata from [elements].
+  void processMetadata(Iterable<Element> elements,
+      void onMetadata(MetadataAnnotation metadata)) {
+    void processLibraryMetadata(LibraryElement library) {
+      if (_registeredMetadata.add(library)) {
+        library.metadata.forEach(onMetadata);
+        library.entryCompilationUnit.metadata.forEach(onMetadata);
+        for (ImportElement import in library.imports) {
+          import.metadata.forEach(onMetadata);
+        }
+      }
+    }
+
+    void processElementMetadata(Element element) {
+      if (_registeredMetadata.add(element)) {
+        element.metadata.forEach(onMetadata);
+        if (element.isFunction) {
+          FunctionElement function = element;
+          for (ParameterElement parameter in function.parameters) {
+            parameter.metadata.forEach(onMetadata);
+          }
+        }
+        if (element.enclosingClass != null) {
+          processElementMetadata(element.enclosingClass);
+        } else {
+          processLibraryMetadata(element.library);
+        }
+      }
+    }
+
+    elements.forEach(processElementMetadata);
+  }
+
   void onQueueClosed() {
     lookupMapAnalysis.onQueueClosed();
     jsInteropAnalysis.onQueueClosed();
@@ -3037,6 +3087,8 @@
   final Element annotatedElement;
 
   const Dependency(this.constant, this.annotatedElement);
+
+  String toString() => '$annotatedElement:${constant.toStructuredText()}';
 }
 
 class JavaScriptImpactStrategy extends ImpactStrategy {
diff --git a/pkg/compiler/lib/src/js_backend/backend_serialization.dart b/pkg/compiler/lib/src/js_backend/backend_serialization.dart
index d0594f4..97da2f5 100644
--- a/pkg/compiler/lib/src/js_backend/backend_serialization.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_serialization.dart
@@ -4,6 +4,7 @@
 
 library js_backend.serialization;
 
+import '../common.dart';
 import '../common/backend_api.dart' show BackendSerialization;
 import '../dart_types.dart';
 import '../elements/elements.dart';
@@ -38,6 +39,9 @@
 const Key JS_INTEROP_NAME = const Key('jsInteropName');
 const Key NATIVE_MEMBER_NAME = const Key('nativeMemberName');
 const Key NATIVE_CLASS_TAG_INFO = const Key('nativeClassTagInfo');
+const Key NATIVE_METHOD_BEHAVIOR = const Key('nativeMethodBehavior');
+const Key NATIVE_FIELD_LOAD_BEHAVIOR = const Key('nativeFieldLoadBehavior');
+const Key NATIVE_FIELD_STORE_BEHAVIOR = const Key('nativeFieldStoreBehavior');
 
 class JavaScriptBackendSerializer implements SerializerPlugin {
   final JavaScriptBackend backend;
@@ -63,41 +67,31 @@
     if (nativeClassTagInfo != null) {
       getEncoder().setString(NATIVE_CLASS_TAG_INFO, nativeClassTagInfo);
     }
-  }
-
-  /// Returns a list of the [DartType]s in [types].
-  static List<DartType> filterDartTypes(List types) {
-    return types.where((type) => type is DartType).toList();
-  }
-
-  /// Returns a list of the names of the [SpecialType]s in [types].
-  static List<String> filterSpecialTypes(List types) {
-    return types
-        .where((type) => type is SpecialType)
-        .map((SpecialType type) => type.name)
-        .toList();
+    NativeBehavior nativeMethodBehavior =
+        backend.nativeData.nativeMethodBehavior[element];
+    if (nativeMethodBehavior != null) {
+      NativeBehaviorSerialization.serializeNativeBehavior(nativeMethodBehavior,
+          getEncoder().createObject(NATIVE_METHOD_BEHAVIOR));
+    }
+    NativeBehavior nativeFieldLoadBehavior =
+        backend.nativeData.nativeFieldLoadBehavior[element];
+    if (nativeFieldLoadBehavior != null) {
+      NativeBehaviorSerialization.serializeNativeBehavior(
+          nativeFieldLoadBehavior,
+          getEncoder().createObject(NATIVE_FIELD_LOAD_BEHAVIOR));
+    }
+    NativeBehavior nativeFieldStoreBehavior =
+        backend.nativeData.nativeFieldStoreBehavior[element];
+    if (nativeFieldStoreBehavior != null) {
+      NativeBehaviorSerialization.serializeNativeBehavior(
+          nativeFieldStoreBehavior,
+          getEncoder().createObject(NATIVE_FIELD_STORE_BEHAVIOR));
+    }
   }
 
   @override
   void onData(NativeBehavior behavior, ObjectEncoder encoder) {
-    encoder.setTypes(
-        DART_TYPES_RETURNED, filterDartTypes(behavior.typesReturned));
-    encoder.setStrings(
-        SPECIAL_TYPES_RETURNED, filterSpecialTypes(behavior.typesReturned));
-
-    encoder.setTypes(
-        DART_TYPES_INSTANTIATED, filterDartTypes(behavior.typesInstantiated));
-    encoder.setStrings(SPECIAL_TYPES_INSTANTIATED,
-        filterSpecialTypes(behavior.typesInstantiated));
-
-    if (behavior.codeTemplateText != null) {
-      encoder.setString(CODE_TEMPLATE, behavior.codeTemplateText);
-    }
-
-    encoder.setInt(SIDE_EFFECTS, behavior.sideEffects.flags);
-    encoder.setEnum(THROW_BEHAVIOR, behavior.throwBehavior);
-    encoder.setBool(IS_ALLOCATION, behavior.isAllocation);
-    encoder.setBool(USE_GVN, behavior.useGvn);
+    NativeBehaviorSerialization.serializeNativeBehavior(behavior, encoder);
   }
 }
 
@@ -125,11 +119,73 @@
       if (nativeClassTagInfo != null) {
         backend.nativeData.nativeClassTagInfo[element] = nativeClassTagInfo;
       }
+      ObjectDecoder nativeMethodBehavior =
+          decoder.getObject(NATIVE_METHOD_BEHAVIOR, isOptional: true);
+      if (nativeMethodBehavior != null) {
+        backend.nativeData.nativeMethodBehavior[element] =
+            NativeBehaviorSerialization
+                .deserializeNativeBehavior(nativeMethodBehavior);
+      }
+      ObjectDecoder nativeFieldLoadBehavior =
+          decoder.getObject(NATIVE_FIELD_LOAD_BEHAVIOR, isOptional: true);
+      if (nativeFieldLoadBehavior != null) {
+        backend.nativeData.nativeFieldLoadBehavior[element] =
+            NativeBehaviorSerialization
+                .deserializeNativeBehavior(nativeFieldLoadBehavior);
+      }
+      ObjectDecoder nativeFieldStoreBehavior =
+          decoder.getObject(NATIVE_FIELD_STORE_BEHAVIOR, isOptional: true);
+      if (nativeFieldStoreBehavior != null) {
+        backend.nativeData.nativeFieldStoreBehavior[element] =
+            NativeBehaviorSerialization
+                .deserializeNativeBehavior(nativeFieldStoreBehavior);
+      }
     }
   }
 
   @override
   NativeBehavior onData(ObjectDecoder decoder) {
+    return NativeBehaviorSerialization.deserializeNativeBehavior(decoder);
+  }
+}
+
+class NativeBehaviorSerialization {
+  /// Returns a list of the [DartType]s in [types].
+  static List<DartType> filterDartTypes(List types) {
+    return types.where((type) => type is DartType).toList();
+  }
+
+  /// Returns a list of the names of the [SpecialType]s in [types].
+  static List<String> filterSpecialTypes(List types) {
+    return types
+        .where((type) => type is SpecialType)
+        .map((SpecialType type) => type.name)
+        .toList();
+  }
+
+  static void serializeNativeBehavior(
+      NativeBehavior behavior, ObjectEncoder encoder) {
+    encoder.setTypes(
+        DART_TYPES_RETURNED, filterDartTypes(behavior.typesReturned));
+    encoder.setStrings(
+        SPECIAL_TYPES_RETURNED, filterSpecialTypes(behavior.typesReturned));
+
+    encoder.setTypes(
+        DART_TYPES_INSTANTIATED, filterDartTypes(behavior.typesInstantiated));
+    encoder.setStrings(SPECIAL_TYPES_INSTANTIATED,
+        filterSpecialTypes(behavior.typesInstantiated));
+
+    if (behavior.codeTemplateText != null) {
+      encoder.setString(CODE_TEMPLATE, behavior.codeTemplateText);
+    }
+
+    encoder.setInt(SIDE_EFFECTS, behavior.sideEffects.flags);
+    encoder.setEnum(THROW_BEHAVIOR, behavior.throwBehavior);
+    encoder.setBool(IS_ALLOCATION, behavior.isAllocation);
+    encoder.setBool(USE_GVN, behavior.useGvn);
+  }
+
+  static NativeBehavior deserializeNativeBehavior(ObjectDecoder decoder) {
     SideEffects sideEffects =
         new SideEffects.fromFlags(decoder.getInt(SIDE_EFFECTS));
     NativeBehavior behavior = new NativeBehavior.internal(sideEffects);
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index fc53cb4..eba60d9 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -64,6 +64,11 @@
     return new jsAst.LiteralNull();
   }
 
+  @override
+  jsAst.Expression visitNonConstant(NonConstantValue constant, [_]) {
+    return new jsAst.LiteralNull();
+  }
+
   static final _exponentialRE = new RegExp('^'
       '\([-+]?\)' // 1: sign
       '\([0-9]+\)' // 2: leading digit(s)
@@ -280,7 +285,7 @@
 
   @override
   jsAst.Expression visitConstructed(ConstructedConstantValue constant, [_]) {
-    Element element = constant.type.element;
+    ClassElement element = constant.type.element;
     if (backend.isForeign(element) && element.name == 'JS_CONST') {
       StringConstantValue str = constant.fields.values.single;
       String value = str.primitiveValue.slowToString();
@@ -288,9 +293,10 @@
     }
     jsAst.Expression constructor =
         backend.emitter.constructorAccess(constant.type.element);
-    List<jsAst.Expression> fields = constant.fields.values
-        .map(constantReferenceGenerator)
-        .toList(growable: false);
+    List<jsAst.Expression> fields = <jsAst.Expression>[];
+    element.forEachInstanceField((_, FieldElement field) {
+      fields.add(constantReferenceGenerator(constant.fields[field]));
+    }, includeSuperAndInjectedMembers: true);
     jsAst.New instantiation = new jsAst.New(constructor, fields);
     return maybeAddTypeArguments(constant.type, instantiation);
   }
diff --git a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
index 6077e6d..8e6de54 100644
--- a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
@@ -116,6 +116,8 @@
       new Map<Node, ConstantExpression>();
 
   // Constants computed for metadata.
+  // TODO(johnniwinther): Remove this when no longer used by
+  // poi/forget_element_test.
   final Map<MetadataAnnotation, ConstantExpression> metadataConstantMap =
       new Map<MetadataAnnotation, ConstantExpression>();
 
@@ -212,9 +214,10 @@
   }
 
   ConstantValue getConstantValueForMetadata(MetadataAnnotation metadata) {
-    return getConstantValue(metadataConstantMap[metadata]);
+    return getConstantValue(metadata.constant);
   }
 
+  @override
   ConstantExpression compileMetadata(
       MetadataAnnotation metadata, Node node, TreeElements elements) {
     ConstantExpression constant =
@@ -230,29 +233,6 @@
       element.node.accept(new ForgetConstantNodeVisitor(this));
     }
   }
-
-  @override
-  ConstantValue getConstantValue(ConstantExpression expression) {
-    assert(invariant(CURRENT_ELEMENT_SPANNABLE, expression != null,
-        message: "ConstantExpression is null in getConstantValue."));
-    // TODO(johhniwinther): ensure expressions have been evaluated at this
-    // point. This can't be enabled today due to dartbug.com/26406.
-    if (compiler.serialization.supportsDeserialization) {
-      evaluate(expression);
-    }
-    ConstantValue value = super.getConstantValue(expression);
-    if (value == null &&
-        expression != null &&
-        expression.kind == ConstantExpressionKind.ERRONEOUS) {
-      // TODO(johnniwinther): When the Dart constant system sees a constant
-      // expression as erroneous but the JavaScript constant system finds it ok
-      // we have store a constant value for the erroneous constant expression.
-      // Ensure the computed constant expressions are always the same; that only
-      // the constant values may be different.
-      value = new NullConstantValue();
-    }
-    return value;
-  }
 }
 
 class ForgetConstantElementVisitor
diff --git a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
index 410d1c8..bfd156e 100644
--- a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
@@ -357,7 +357,7 @@
     symbolClass.forEachInstanceField(
         (ClassElement enclosingClass, FieldElement field) {
       fields[field] = argument;
-    });
+    }, includeSuperAndInjectedMembers: true);
     assert(fields.length == 1);
     return new ConstructedConstantValue(type, fields);
   }
diff --git a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
index 448f979..e2ebe39 100644
--- a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
@@ -5,6 +5,7 @@
 /// Analysis to determine how to generate code for typed JavaScript interop.
 library compiler.src.js_backend.js_interop_analysis;
 
+import '../common.dart';
 import '../constants/values.dart'
     show ConstantValue, ConstructedConstantValue, StringConstantValue;
 import '../diagnostics/messages.dart' show MessageKind;
@@ -54,6 +55,8 @@
 
   void processJsInteropAnnotation(Element e) {
     for (MetadataAnnotation annotation in e.implementation.metadata) {
+      // TODO(johnniwinther): Avoid processing unresolved elements.
+      if (annotation.constant == null) continue;
       ConstantValue constant =
           backend.compiler.constants.getConstantValue(annotation.constant);
       if (constant == null || constant is! ConstructedConstantValue) continue;
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index c0f21c5..c4a86ef 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -331,6 +331,7 @@
   final String callPrefix = 'call';
   final String callCatchAllName = r'call*';
   final String callNameField = r'$callName';
+  final String stubNameField = r'$stubName';
   final String reflectableField = r'$reflectable';
   final String reflectionInfoField = r'$reflectionInfo';
   final String reflectionNameField = r'$reflectionName';
@@ -1672,6 +1673,11 @@
   }
 
   @override
+  void visitNonConstant(NonConstantValue constant, [_]) {
+    add('null');
+  }
+
+  @override
   void visitInt(IntConstantValue constant, [_]) {
     // No `addRoot` since IntConstants are always inlined.
     if (constant.primitiveValue < 0) {
@@ -1730,10 +1736,10 @@
   @override
   void visitConstructed(ConstructedConstantValue constant, [_]) {
     addRoot(constant.type.element.name);
-    for (ConstantValue value in constant.fields.values) {
-      _visit(value);
+    constant.type.element.forEachInstanceField((_, FieldElement field) {
       if (failed) return;
-    }
+      _visit(constant.fields[field]);
+    }, includeSuperAndInjectedMembers: true);
   }
 
   @override
@@ -1816,6 +1822,9 @@
   int visitNull(NullConstantValue constant, [_]) => 1;
 
   @override
+  int visitNonConstant(NonConstantValue constant, [_]) => 1;
+
+  @override
   int visitBool(BoolConstantValue constant, [_]) {
     return constant.isTrue ? 2 : 3;
   }
@@ -1854,9 +1863,9 @@
   @override
   int visitConstructed(ConstructedConstantValue constant, [_]) {
     int hash = _hashString(3, constant.type.element.name);
-    for (ConstantValue value in constant.fields.values) {
-      hash = _combine(hash, _visit(value));
-    }
+    constant.type.element.forEachInstanceField((_, FieldElement field) {
+      hash = _combine(hash, _visit(constant.fields[field]));
+    }, includeSuperAndInjectedMembers: true);
     return hash;
   }
 
diff --git a/pkg/compiler/lib/src/js_backend/native_data.dart b/pkg/compiler/lib/src/js_backend/native_data.dart
index 42712f0..67b473b 100644
--- a/pkg/compiler/lib/src/js_backend/native_data.dart
+++ b/pkg/compiler/lib/src/js_backend/native_data.dart
@@ -23,7 +23,6 @@
   /// [setNativeClassTagInfo].
   Map<ClassElement, String> nativeClassTagInfo = <ClassElement, String>{};
 
-  // TODO(johnniwinther): Serialize these.
   /// Cache for [NativeBehavior]s for calling native methods.
   Map<FunctionElement, NativeBehavior> nativeMethodBehavior =
       <FunctionElement, NativeBehavior>{};
diff --git a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
index a2a0d7d..27651c2 100644
--- a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
+++ b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
@@ -76,6 +76,10 @@
     return 0;
   }
 
+  int visitNonConstant(NonConstantValue a, NonConstantValue b) {
+    return 0;
+  }
+
   int visitInt(IntConstantValue a, IntConstantValue b) {
     return a.primitiveValue.compareTo(b.primitiveValue);
   }
@@ -189,12 +193,14 @@
   static const int INTERCEPTOR = 11;
   static const int SYNTHETIC = 12;
   static const int DEFERRED = 13;
+  static const int NONCONSTANT = 13;
 
   static int kind(ConstantValue constant) =>
       constant.accept(const _KindVisitor(), null);
 
   int visitFunction(FunctionConstantValue a, _) => FUNCTION;
   int visitNull(NullConstantValue a, _) => NULL;
+  int visitNonConstant(NonConstantValue a, _) => NONCONSTANT;
   int visitInt(IntConstantValue a, _) => INT;
   int visitDouble(DoubleConstantValue a, _) => DOUBLE;
   int visitBool(BoolConstantValue a, _) => BOOL;
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index 48ccd6d..846ce8b 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -233,6 +233,7 @@
     reflectionInfo = reflectionInfo + typesOffset;
   }
   var name = funsOrNames[0];
+  fun.#stubName = name;
   var getterFunction =
       tearOff(funs, reflectionInfo, isStatic, name, isIntercepted);
   container[getterName] = getterFunction;
@@ -455,6 +456,7 @@
       'constantHolderReference': buildConstantHolderReference(program),
       'holders': emitHolders(program.holders, fragment),
       'callName': js.string(namer.callNameField),
+      'stubName': js.string(namer.stubNameField),
       'argumentCount': js.string(namer.requiredParameterField),
       'defaultArgumentValues': js.string(namer.defaultValuesField),
       'prototypes': emitPrototypes(fragment),
diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart
index 63b601d..e8f3340 100644
--- a/pkg/compiler/lib/src/native/enqueue.dart
+++ b/pkg/compiler/lib/src/native/enqueue.dart
@@ -318,7 +318,7 @@
       // TODO(sra): Better validation of the constant.
       if (fields.length != 1 || fields.single is! StringConstantValue) {
         reporter.internalError(
-            annotation, 'Annotations needs one string: ${annotation.node}');
+            annotation, 'Annotations needs one string: ${annotation}');
       }
       StringConstantValue specStringConstant = fields.single;
       String specString = specStringConstant.toDartString().slowToString();
@@ -326,7 +326,7 @@
         name = specString;
       } else {
         reporter.internalError(
-            annotation, 'Too many JSName annotations: ${annotation.node}');
+            annotation, 'Too many JSName annotations: ${annotation}');
       }
     }
     return name;
diff --git a/pkg/compiler/lib/src/parser/element_listener.dart b/pkg/compiler/lib/src/parser/element_listener.dart
index 6fe019c..6d9bd82 100644
--- a/pkg/compiler/lib/src/parser/element_listener.dart
+++ b/pkg/compiler/lib/src/parser/element_listener.dart
@@ -17,6 +17,7 @@
         EnumClassElementX,
         FieldElementX,
         LibraryElementX,
+        MetadataAnnotationX,
         NamedMixinApplicationElementX,
         VariableList;
 import '../id_generator.dart';
@@ -233,8 +234,8 @@
 
   void endTopLevelDeclaration(Token token) {
     if (!metadata.isEmpty) {
-      recoverableError(
-          metadata.first.beginToken, 'Metadata not supported here.');
+      MetadataAnnotationX first = metadata.first;
+      recoverableError(first.beginToken, 'Metadata not supported here.');
       metadata.clear();
     }
   }
diff --git a/pkg/compiler/lib/src/patch_parser.dart b/pkg/compiler/lib/src/patch_parser.dart
index a2246c4..9f51036 100644
--- a/pkg/compiler/lib/src/patch_parser.dart
+++ b/pkg/compiler/lib/src/patch_parser.dart
@@ -128,6 +128,7 @@
         ClassElementX,
         GetterElementX,
         LibraryElementX,
+        MetadataAnnotationX,
         SetterElementX;
 import 'id_generator.dart';
 import 'js_backend/js_backend.dart' show JavaScriptBackend;
@@ -403,7 +404,7 @@
 class NativeAnnotationHandler implements EagerAnnotationHandler<String> {
   const NativeAnnotationHandler();
 
-  String getNativeAnnotation(MetadataAnnotation annotation) {
+  String getNativeAnnotation(MetadataAnnotationX annotation) {
     if (annotation.beginToken != null &&
         annotation.beginToken.next.value == 'Native') {
       // Skipping '@', 'Native', and '('.
@@ -443,7 +444,7 @@
 class JsInteropAnnotationHandler implements EagerAnnotationHandler<bool> {
   const JsInteropAnnotationHandler();
 
-  bool hasJsNameAnnotation(MetadataAnnotation annotation) =>
+  bool hasJsNameAnnotation(MetadataAnnotationX annotation) =>
       annotation.beginToken != null && annotation.beginToken.next.value == 'JS';
 
   bool apply(
@@ -474,7 +475,7 @@
 class PatchAnnotationHandler implements EagerAnnotationHandler<PatchVersion> {
   const PatchAnnotationHandler();
 
-  PatchVersion getPatchVersion(MetadataAnnotation annotation) {
+  PatchVersion getPatchVersion(MetadataAnnotationX annotation) {
     if (annotation.beginToken != null) {
       if (annotation.beginToken.next.value == 'patch') {
         return const PatchVersion(null);
diff --git a/pkg/compiler/lib/src/resolution/registry.dart b/pkg/compiler/lib/src/resolution/registry.dart
index 54bd495..e52b185 100644
--- a/pkg/compiler/lib/src/resolution/registry.dart
+++ b/pkg/compiler/lib/src/resolution/registry.dart
@@ -334,10 +334,6 @@
     worldImpact.registerStaticUse(staticUse);
   }
 
-  void registerMetadataConstant(MetadataAnnotation metadata) {
-    backend.registerMetadataConstant(metadata, metadata.annotatedElement, this);
-  }
-
   /// Register the use of a type.
   void registerTypeUse(TypeUse typeUse) {
     worldImpact.registerTypeUse(typeUse);
diff --git a/pkg/compiler/lib/src/resolution/resolution.dart b/pkg/compiler/lib/src/resolution/resolution.dart
index f1ca6d0..2fd4e685 100644
--- a/pkg/compiler/lib/src/resolution/resolution.dart
+++ b/pkg/compiler/lib/src/resolution/resolution.dart
@@ -1088,7 +1088,6 @@
               // and the annotated element instead. This will allow the backend to
               // retrieve the backend constant and only register metadata on the
               // elements for which it is needed. (Issue 17732).
-              registry.registerMetadataConstant(annotation);
               annotation.resolutionState = STATE_DONE;
             }));
   }
diff --git a/pkg/compiler/lib/src/serialization/element_serialization.dart b/pkg/compiler/lib/src/serialization/element_serialization.dart
index b115ae0..b025533 100644
--- a/pkg/compiler/lib/src/serialization/element_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/element_serialization.dart
@@ -120,6 +120,31 @@
     }
   }
 
+  /// Serialize the metadata of [element] into [encoder].
+  static void serializeMetadata(Element element, ObjectEncoder encoder) {
+    ListEncoder list;
+
+    void encodeAnnotation(MetadataAnnotation metadata) {
+      ObjectEncoder object = list.createObject();
+      object.setElement(Key.ELEMENT, metadata.annotatedElement);
+      SourceSpan sourcePosition = metadata.sourcePosition;
+      // TODO(johnniwinther): What is the base URI here?
+      object.setUri(Key.URI, sourcePosition.uri, sourcePosition.uri);
+      object.setInt(Key.OFFSET, sourcePosition.begin);
+      object.setInt(Key.LENGTH, sourcePosition.end - sourcePosition.begin);
+      object.setConstant(Key.CONSTANT, metadata.constant);
+    }
+
+    if (element.metadata.isNotEmpty) {
+      list = encoder.createList(Key.METADATA);
+      element.metadata.forEach(encodeAnnotation);
+    }
+    if (element.isPatched && element.implementation.metadata.isNotEmpty) {
+      list ??= encoder.createList(Key.METADATA);
+      element.implementation.metadata.forEach(encodeAnnotation);
+    }
+  }
+
   /// Serialize the parent relation for [element] into [encoder], i.e library,
   /// enclosing class, and compilation unit references.
   static void serializeParentRelation(Element element, ObjectEncoder encoder) {
@@ -225,6 +250,7 @@
 
   void serialize(LibraryElement element, ObjectEncoder encoder,
       SerializedElementKind kind) {
+    SerializerUtil.serializeMetadata(element, encoder);
     encoder.setUri(
         Key.CANONICAL_URI, element.canonicalUri, element.canonicalUri);
     encoder.setString(Key.LIBRARY_NAME, element.libraryName);
@@ -252,6 +278,7 @@
 
   void serialize(CompilationUnitElement element, ObjectEncoder encoder,
       SerializedElementKind kind) {
+    SerializerUtil.serializeMetadata(element, encoder);
     encoder.setElement(Key.LIBRARY, element.library);
     encoder.setUri(
         Key.URI, element.library.canonicalUri, element.script.resourceUri);
@@ -299,6 +326,7 @@
 
   void serialize(
       ClassElement element, ObjectEncoder encoder, SerializedElementKind kind) {
+    SerializerUtil.serializeMetadata(element, encoder);
     encoder.setElement(Key.LIBRARY, element.library);
     encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
     encoder.setString(Key.NAME, element.name);
@@ -307,6 +335,7 @@
     encoder.setBool(Key.IS_ABSTRACT, element.isAbstract);
     SerializerUtil.serializeMembers(getMembers(element), encoder);
     encoder.setBool(Key.IS_PROXY, element.isProxy);
+    encoder.setBool(Key.IS_INJECTED, element.isInjected);
     if (kind == SerializedElementKind.ENUM) {
       EnumClassElement enumClass = element;
       encoder.setElements(Key.FIELDS, enumClass.enumValues);
@@ -368,12 +397,14 @@
     if (kind == SerializedElementKind.FORWARDING_CONSTRUCTOR) {
       encoder.setElement(Key.ELEMENT, element.definingConstructor);
     } else {
+      SerializerUtil.serializeMetadata(element, encoder);
       encoder.setType(Key.TYPE, element.type);
       encoder.setString(Key.NAME, element.name);
       SerializerUtil.serializePosition(element, encoder);
       SerializerUtil.serializeParameters(element, encoder);
       encoder.setBool(Key.IS_CONST, element.isConst);
       encoder.setBool(Key.IS_EXTERNAL, element.isExternal);
+      encoder.setBool(Key.IS_INJECTED, element.isInjected);
       if (element.isConst && !element.isFromEnvironmentConstructor) {
         ConstantConstructor constantConstructor = element.constantConstructor;
         ObjectEncoder constantEncoder = encoder.createObject(Key.CONSTRUCTOR);
@@ -419,10 +450,12 @@
   void serialize(
       FieldElement element, ObjectEncoder encoder, SerializedElementKind kind) {
     encoder.setString(Key.NAME, element.name);
+    SerializerUtil.serializeMetadata(element, encoder);
     SerializerUtil.serializePosition(element, encoder);
     encoder.setType(Key.TYPE, element.type);
     encoder.setBool(Key.IS_FINAL, element.isFinal);
     encoder.setBool(Key.IS_CONST, element.isConst);
+    encoder.setBool(Key.IS_INJECTED, element.isInjected);
     ConstantExpression constant = element.constant;
     if (constant != null) {
       encoder.setConstant(Key.CONSTANT, constant);
@@ -469,6 +502,7 @@
   void serialize(FunctionElement element, ObjectEncoder encoder,
       SerializedElementKind kind) {
     encoder.setString(Key.NAME, element.name);
+    SerializerUtil.serializeMetadata(element, encoder);
     SerializerUtil.serializePosition(element, encoder);
     SerializerUtil.serializeParameters(element, encoder);
     encoder.setType(Key.TYPE, element.type);
@@ -479,6 +513,7 @@
     SerializerUtil.serializeParentRelation(element, encoder);
     encoder.setBool(Key.IS_EXTERNAL, element.isExternal);
     encoder.setBool(Key.IS_ABSTRACT, element.isAbstract);
+    encoder.setBool(Key.IS_INJECTED, element.isInjected);
     if (element.isLocal) {
       LocalFunctionElement localFunction = element;
       encoder.setElement(
@@ -500,6 +535,7 @@
   void serialize(TypedefElement element, ObjectEncoder encoder,
       SerializedElementKind kind) {
     encoder.setString(Key.NAME, element.name);
+    SerializerUtil.serializeMetadata(element, encoder);
     SerializerUtil.serializePosition(element, encoder);
     encoder.setType(Key.ALIAS, element.alias);
     encoder.setElement(Key.LIBRARY, element.library);
@@ -522,6 +558,7 @@
       SerializedElementKind kind) {
     encoder.setElement(Key.TYPE_DECLARATION, element.typeDeclaration);
     encoder.setString(Key.NAME, element.name);
+    SerializerUtil.serializeMetadata(element, encoder);
     SerializerUtil.serializePosition(element, encoder);
     encoder.setType(Key.TYPE, element.type);
     encoder.setInt(Key.INDEX, element.index);
@@ -545,6 +582,7 @@
       SerializedElementKind kind) {
     encoder.setElement(Key.FUNCTION, element.functionDeclaration);
     encoder.setString(Key.NAME, element.name);
+    SerializerUtil.serializeMetadata(element, encoder);
     SerializerUtil.serializePosition(element, encoder);
     encoder.setType(Key.TYPE, element.type);
     encoder.setBool(Key.IS_OPTIONAL, element.isOptional);
@@ -573,6 +611,7 @@
   void serialize(LocalVariableElement element, ObjectEncoder encoder,
       SerializedElementKind kind) {
     encoder.setString(Key.NAME, element.name);
+    SerializerUtil.serializeMetadata(element, encoder);
     SerializerUtil.serializePosition(element, encoder);
     encoder.setType(Key.TYPE, element.type);
     encoder.setBool(Key.IS_FINAL, element.isFinal);
@@ -597,6 +636,7 @@
 
   void serialize(ImportElement element, ObjectEncoder encoder,
       SerializedElementKind kind) {
+    SerializerUtil.serializeMetadata(element, encoder);
     encoder.setElement(Key.LIBRARY, element.library);
     encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
     encoder.setElement(Key.LIBRARY_DEPENDENCY, element.importedLibrary);
@@ -621,6 +661,7 @@
 
   void serialize(ExportElement element, ObjectEncoder encoder,
       SerializedElementKind kind) {
+    SerializerUtil.serializeMetadata(element, encoder);
     encoder.setElement(Key.LIBRARY, element.library);
     encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
     encoder.setElement(Key.LIBRARY_DEPENDENCY, element.exportedLibrary);
diff --git a/pkg/compiler/lib/src/serialization/equivalence.dart b/pkg/compiler/lib/src/serialization/equivalence.dart
index 563783f..a7c08b5 100644
--- a/pkg/compiler/lib/src/serialization/equivalence.dart
+++ b/pkg/compiler/lib/src/serialization/equivalence.dart
@@ -14,7 +14,7 @@
 import '../elements/elements.dart';
 import '../elements/visitor.dart';
 import '../js_backend/backend_serialization.dart'
-    show JavaScriptBackendSerializer;
+    show NativeBehaviorSerialization;
 import '../native/native.dart' show NativeBehavior;
 import '../resolution/access_semantics.dart';
 import '../resolution/send_structure.dart';
@@ -860,6 +860,43 @@
   return false;
 }
 
+bool testNativeBehavior(NativeBehavior a, NativeBehavior b,
+    [TestStrategy strategy = const TestStrategy()]) {
+  if (identical(a, b)) return true;
+  if (a == null || b == null) return false;
+  return strategy.test(
+          a, b, 'codeTemplateText', a.codeTemplateText, b.codeTemplateText) &&
+      strategy.test(a, b, 'isAllocation', a.isAllocation, b.isAllocation) &&
+      strategy.test(a, b, 'sideEffects', a.sideEffects, b.sideEffects) &&
+      strategy.test(a, b, 'throwBehavior', a.throwBehavior, b.throwBehavior) &&
+      strategy.testTypeLists(
+          a,
+          b,
+          'dartTypesReturned',
+          NativeBehaviorSerialization.filterDartTypes(a.typesReturned),
+          NativeBehaviorSerialization.filterDartTypes(b.typesReturned)) &&
+      strategy.testLists(
+          a,
+          b,
+          'specialTypesReturned',
+          NativeBehaviorSerialization.filterSpecialTypes(a.typesReturned),
+          NativeBehaviorSerialization.filterSpecialTypes(b.typesReturned)) &&
+      strategy.testTypeLists(
+          a,
+          b,
+          'dartTypesInstantiated',
+          NativeBehaviorSerialization.filterDartTypes(a.typesInstantiated),
+          NativeBehaviorSerialization.filterDartTypes(b.typesInstantiated)) &&
+      strategy.testLists(
+          a,
+          b,
+          'specialTypesInstantiated',
+          NativeBehaviorSerialization.filterSpecialTypes(a.typesInstantiated),
+          NativeBehaviorSerialization
+              .filterSpecialTypes(b.typesInstantiated)) &&
+      strategy.test(a, b, 'useGvn', a.useGvn, b.useGvn);
+}
+
 /// Visitor that checks the equivalence of [TreeElements] data.
 class TreeElementsEquivalenceVisitor extends Visitor {
   final TestStrategy strategy;
@@ -911,41 +948,7 @@
     if (identical(a, b)) return true;
     if (a == null || b == null) return false;
     if (a is NativeBehavior && b is NativeBehavior) {
-      return strategy.test(a, b, 'codeTemplateText', a.codeTemplateText,
-              b.codeTemplateText) &&
-          strategy.test(a, b, 'isAllocation', a.isAllocation, b.isAllocation) &&
-          strategy.test(a, b, 'sideEffects', a.sideEffects, b.sideEffects) &&
-          strategy.test(
-              a, b, 'throwBehavior', a.throwBehavior, b.throwBehavior) &&
-          strategy.testTypeLists(
-              a,
-              b,
-              'dartTypesReturned',
-              JavaScriptBackendSerializer.filterDartTypes(a.typesReturned),
-              JavaScriptBackendSerializer.filterDartTypes(b.typesReturned)) &&
-          strategy.testLists(
-              a,
-              b,
-              'specialTypesReturned',
-              JavaScriptBackendSerializer.filterSpecialTypes(a.typesReturned),
-              JavaScriptBackendSerializer
-                  .filterSpecialTypes(b.typesReturned)) &&
-          strategy.testTypeLists(
-              a,
-              b,
-              'dartTypesInstantiated',
-              JavaScriptBackendSerializer.filterDartTypes(a.typesInstantiated),
-              JavaScriptBackendSerializer
-                  .filterDartTypes(b.typesInstantiated)) &&
-          strategy.testLists(
-              a,
-              b,
-              'specialTypesInstantiated',
-              JavaScriptBackendSerializer
-                  .filterSpecialTypes(a.typesInstantiated),
-              JavaScriptBackendSerializer
-                  .filterSpecialTypes(b.typesInstantiated)) &&
-          strategy.test(a, b, 'useGvn', a.useGvn, b.useGvn);
+      return testNativeBehavior(a, b, strategy);
     }
     return true;
   }
@@ -1829,3 +1832,12 @@
     throw new UnsupportedError('Unexpected nodes: $node1 <> $node2');
   }
 }
+
+bool areMetadataAnnotationsEquivalent(
+    MetadataAnnotation metadata1, MetadataAnnotation metadata2) {
+  if (metadata1 == metadata2) return true;
+  if (metadata1 == null || metadata2 == null) return false;
+  return areElementsEquivalent(
+          metadata1.annotatedElement, metadata2.annotatedElement) &&
+      areConstantsEquivalent(metadata1.constant, metadata2.constant);
+}
diff --git a/pkg/compiler/lib/src/serialization/keys.dart b/pkg/compiler/lib/src/serialization/keys.dart
index 179b727..fb5151b 100644
--- a/pkg/compiler/lib/src/serialization/keys.dart
+++ b/pkg/compiler/lib/src/serialization/keys.dart
@@ -59,6 +59,7 @@
   static const Key IS_EMPTY = const Key('isEmpty');
   static const Key IS_EXTERNAL = const Key('isExternal');
   static const Key IS_FINAL = const Key('isFinal');
+  static const Key IS_INJECTED = const Key('isInjected');
   static const Key IS_NAMED = const Key('isNamed');
   static const Key IS_OPERATOR = const Key('isOperator');
   static const Key IS_OPTIONAL = const Key('isOptional');
@@ -83,6 +84,7 @@
   static const Key LISTS = const Key('lists');
   static const Key MAPS = const Key('maps');
   static const Key MEMBERS = const Key('members');
+  static const Key METADATA = const Key('metadata');
   static const Key MIXIN = const Key('mixin');
   static const Key MIXINS = const Key('mixins');
   static const Key NAME = const Key('name');
diff --git a/pkg/compiler/lib/src/serialization/modelz.dart b/pkg/compiler/lib/src/serialization/modelz.dart
index a03ef2f..c909f9a 100644
--- a/pkg/compiler/lib/src/serialization/modelz.dart
+++ b/pkg/compiler/lib/src/serialization/modelz.dart
@@ -112,7 +112,6 @@
   @override
   bool get isTopLevel => false;
 
-  // TODO(johnniwinther): Support metadata.
   @override
   Iterable<MetadataAnnotation> get metadata => const <MetadataAnnotation>[];
 
@@ -122,6 +121,7 @@
 
 abstract class DeserializedElementZ extends ElementZ {
   ObjectDecoder _decoder;
+  List<MetadataAnnotation> _metadata;
 
   DeserializedElementZ(this._decoder);
 
@@ -147,6 +147,27 @@
     }
     return new SourceSpan(uri, offset, offset + length);
   }
+
+  @override
+  Iterable<MetadataAnnotation> get metadata {
+    if (_metadata == null) {
+      _metadata = <MetadataAnnotation>[];
+      ListDecoder list = _decoder.getList(Key.METADATA, isOptional: true);
+      if (list != null) {
+        for (int index = 0; index < list.length; index++) {
+          ObjectDecoder object = list.getObject(index);
+          Element element = object.getElement(Key.ELEMENT);
+          Uri uri = object.getUri(Key.URI);
+          int offset = object.getInt(Key.OFFSET);
+          int length = object.getInt(Key.LENGTH);
+          ConstantExpression constant = object.getConstant(Key.CONSTANT);
+          _metadata.add(new MetadataAnnotationZ(
+              element, new SourceSpan(uri, offset, offset + length), constant));
+        }
+      }
+    }
+    return _metadata;
+  }
 }
 
 /// Deserializer for a collection of member elements serialized as a map from
@@ -946,6 +967,9 @@
   bool get isProxy => _decoder.getBool(Key.IS_PROXY);
 
   @override
+  bool get isInjected => _decoder.getBool(Key.IS_INJECTED);
+
+  @override
   bool get isUnnamedMixinApplication => false;
 
   @override
@@ -1480,6 +1504,9 @@
 
   @override
   List<FunctionElement> get nestedClosures => <FunctionElement>[];
+
+  @override
+  bool get isInjected => _decoder.getBool(Key.IS_INJECTED);
 }
 
 abstract class FieldElementZ extends DeserializedElementZ
@@ -2263,3 +2290,25 @@
     return _unsupported('lookupLocalMember');
   }
 }
+
+class MetadataAnnotationZ implements MetadataAnnotation {
+  final Element annotatedElement;
+  final SourceSpan sourcePosition;
+  final ConstantExpression constant;
+
+  MetadataAnnotationZ(
+      this.annotatedElement, this.sourcePosition, this.constant);
+
+  @override
+  MetadataAnnotation ensureResolved(Resolution resolution) {
+    // Do nothing.
+  }
+
+  @override
+  Node get node => throw new UnsupportedError('${this}.node');
+
+  @override
+  bool get hasNode => false;
+
+  String toString() => 'MetadataAnnotationZ(${constant.toDartText()})';
+}
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 0ff32f2..9637549 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -1496,8 +1496,25 @@
     js.Statement elsePart =
         unwrapStatement(generateStatementsInNewBlock(elseGraph));
 
-    pushStatement(new js.If(test, thenPart, elsePart)
-        .withSourceInformation(node.sourceInformation));
+    js.Statement code;
+    // Peephole rewrites:
+    //
+    //     if (e); else S;   -->   if(!e) S;
+    //
+    //     if (e);   -->   e;
+    //
+    // TODO(sra): This peephole optimization would be better done as an SSA
+    // optimization.
+    if (thenPart is js.EmptyStatement) {
+      if (elsePart is js.EmptyStatement) {
+        code = new js.ExpressionStatement(test);
+      } else {
+        code = new js.If.noElse(new js.Prefix('!', test), elsePart);
+      }
+    } else {
+      code = new js.If(test, thenPart, elsePart);
+    }
+    pushStatement(code.withSourceInformation(node.sourceInformation));
   }
 
   visitIf(HIf node) {
diff --git a/pkg/compiler/lib/src/types/constants.dart b/pkg/compiler/lib/src/types/constants.dart
index a3b2faa..d66a31c 100644
--- a/pkg/compiler/lib/src/types/constants.dart
+++ b/pkg/compiler/lib/src/types/constants.dart
@@ -105,6 +105,11 @@
   }
 
   @override
+  TypeMask visitNonConstant(NonConstantValue constant, Compiler compiler) {
+    return compiler.typesTask.nullType;
+  }
+
+  @override
   TypeMask visitString(StringConstantValue constant, Compiler compiler) {
     return compiler.typesTask.stringType;
   }
diff --git a/pkg/meta/CHANGELOG.md b/pkg/meta/CHANGELOG.md
index 6e1655ae..bf761f1 100644
--- a/pkg/meta/CHANGELOG.md
+++ b/pkg/meta/CHANGELOG.md
@@ -1,3 +1,6 @@
+## 1.0.1
+* Updated `@factory` to allow statics and methods returning `null`.
+
 ## 1.0.0
 * First stable API release.
 
diff --git a/pkg/meta/lib/meta.dart b/pkg/meta/lib/meta.dart
index 17f7f1f..99a3924 100644
--- a/pkg/meta/lib/meta.dart
+++ b/pkg/meta/lib/meta.dart
@@ -18,17 +18,16 @@
 /// in the language tour.
 library meta;
 
-/// Used to annotate an instance method `m`. Indicates that `m` must either be
-/// abstract or must return a newly allocated object. In addition, every method
-/// that either implements or overrides `m` is implicitly annotated with this
-/// same annotation.
+/// Used to annotate an instance or static method `m`. Indicates that `m` must
+/// either be abstract or must return a newly allocated object or `null`. In
+/// addition, every method that either implements or overrides `m` is implicitly
+/// annotated with this same annotation.
 ///
 /// Tools, such as the analyzer, can provide feedback if
 ///
-/// * the annotation is associated with anything other than an instance method,
-///   or
-/// * a method that has this annotation that can return anything other than a
-///   newly allocated object.
+/// * the annotation is associated with anything other than a method, or
+/// * the annotation is associated with a method that has this annotation that
+///   can return anything other than a newly allocated object or `null`.
 const _Factory factory = const _Factory();
 
 /// Used to annotate a const constructor `c`. Indicates that any invocation of
diff --git a/pkg/meta/pubspec.yaml b/pkg/meta/pubspec.yaml
index a629570..acab306 100644
--- a/pkg/meta/pubspec.yaml
+++ b/pkg/meta/pubspec.yaml
@@ -1,5 +1,5 @@
 name: meta
-version: 1.0.0
+version: 1.0.1
 author: Dart Team <misc@dartlang.org>
 homepage: http://www.dartlang.org
 description: >
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 4ddace9..a8fadfb 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -84,6 +84,7 @@
 analyzer/test/generated/strong_mode_test: Pass, Slow # Issue 21628
 analyzer/test/generated/type_system_test: Pass, Slow # Issue 21628
 analyzer/test/generated/utilities_test: Pass, Slow # Issue 21628
+analyzer/test/source/embedder_test: Skip # Issue 21628
 analyzer/test/source/package_map_provider_test: Skip # Issue 21628
 analyzer/test/src/context/cache_test: Pass, Slow # Issue 21628
 analyzer/test/src/context/context_test: Pass, Timeout # dartbug.com/23658
@@ -117,6 +118,7 @@
 analyzer/test/src/task/options_work_manager_test: Pass, Slow # Issue 21628
 analyzer/test/src/task/strong/checker_test: Pass, Slow # Issue 21628
 analyzer/test/src/task/strong/inferred_type_test: Pass, Slow # Issue 21628
+analyzer/test/src/task/strong_mode_test: Pass, Slow # Issue 21628
 analyzer/test/src/task/yaml_test: Pass, Slow # Issue 21628
 analyzer/tool/task_dependency_graph/check_test: Skip # Issue 21628
 collection/test/equality_test/01: Fail # Issue 1533
@@ -165,8 +167,6 @@
 
 [ $compiler == dart2analyzer ]
 compiler/samples/compile_loop/compile_loop: CompileTimeError  # Issue 16524
-lookup_map/test/version_check_test: StaticWarning # https://github.com/dart-lang/http_parser/issues/6
-lookup_map/test/lookup_map_test: StaticWarning # https://github.com/dart-lang/http_parser/issues/6
 
 [ $compiler == dart2js && $csp ]
 # This test cannot run under CSP because it is injecting a JavaScript polyfill
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index a57ef87..1b1f42f 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -32,6 +32,7 @@
 namespace bin {
 
 const char* DartUtils::original_working_directory = NULL;
+CommandLineOptions* DartUtils::url_mapping = NULL;
 const char* const DartUtils::kDartScheme = "dart:";
 const char* const DartUtils::kDartExtensionScheme = "dart-ext:";
 const char* const DartUtils::kAsyncLibURL = "dart:async";
@@ -47,6 +48,7 @@
 
 const uint8_t DartUtils::magic_number[] = { 0xf5, 0xf5, 0xdc, 0xdc };
 
+
 static bool IsWindowsHost() {
 #if defined(TARGET_OS_WINDOWS)
   return true;
@@ -56,8 +58,7 @@
 }
 
 
-const char* DartUtils::MapLibraryUrl(CommandLineOptions* url_mapping,
-                                     const char* url_string) {
+const char* DartUtils::MapLibraryUrl(const char* url_string) {
   ASSERT(url_mapping != NULL);
   // We need to check if the passed in url is found in the url_mapping array,
   // in that case use the mapped entry.
@@ -345,17 +346,6 @@
 }
 
 
-Dart_Handle DartUtils::FilePathFromUri(Dart_Handle script_uri) {
-  const int kNumArgs = 1;
-  Dart_Handle dart_args[kNumArgs];
-  dart_args[0] = script_uri;
-  return Dart_Invoke(DartUtils::BuiltinLib(),
-                     NewString("_filePathFromUri"),
-                     kNumArgs,
-                     dart_args);
-}
-
-
 Dart_Handle DartUtils::LibraryFilePath(Dart_Handle library_uri) {
   const int kNumArgs = 1;
   Dart_Handle dart_args[kNumArgs];
@@ -367,18 +357,6 @@
 }
 
 
-Dart_Handle DartUtils::ResolveUri(Dart_Handle library_url, Dart_Handle url) {
-  const int kNumArgs = 2;
-  Dart_Handle dart_args[kNumArgs];
-  dart_args[0] = library_url;
-  dart_args[1] = url;
-  return Dart_Invoke(DartUtils::BuiltinLib(),
-                     NewString("_resolveUri"),
-                     kNumArgs,
-                     dart_args);
-}
-
-
 Dart_Handle DartUtils::ResolveScript(Dart_Handle url) {
   const int kNumArgs = 1;
   Dart_Handle dart_args[kNumArgs];
@@ -966,6 +944,18 @@
 }
 
 
+Dart_Handle DartUtils::GetCanonicalizableWorkingDirectory() {
+  const char* str = DartUtils::original_working_directory;
+  intptr_t len = strlen(str);
+  if ((str[len] == '/') || (IsWindowsHost() && str[len] == '\\')) {
+    return Dart_NewStringFromCString(str);
+  }
+  char* new_str = reinterpret_cast<char*>(Dart_ScopeAllocate(len + 2));
+  snprintf(new_str, (len + 2), "%s%s", str, File::PathSeparator());
+  return Dart_NewStringFromCString(new_str);
+}
+
+
 // Statically allocated Dart_CObject instances for immutable
 // objects. As these will be used by different threads the use of
 // these depends on the fact that the marking internally in the
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index 9c3bc72..b9fe476 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -193,13 +193,11 @@
   }
 
   static bool SetOriginalWorkingDirectory();
+  static Dart_Handle GetCanonicalizableWorkingDirectory();
 
-  static const char* MapLibraryUrl(CommandLineOptions* url_mapping,
-                                   const char* url_string);
+  static const char* MapLibraryUrl(const char* url_string);
 
   static Dart_Handle ResolveUriInWorkingDirectory(Dart_Handle script_uri);
-  static Dart_Handle FilePathFromUri(Dart_Handle script_uri);
-  static Dart_Handle ResolveUri(Dart_Handle library_url, Dart_Handle url);
   static Dart_Handle ResolveScript(Dart_Handle url);
 
   // Sniffs the specified text_buffer to see if it contains the magic number
@@ -217,6 +215,9 @@
   // Global state that stores the original working directory..
   static const char* original_working_directory;
 
+  // Global state that captures the URL mappings specified on the command line.
+  static CommandLineOptions* url_mapping;
+
   static const char* const kDartScheme;
   static const char* const kDartExtensionScheme;
   static const char* const kAsyncLibURL;
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 5d70175..cc8bb06 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -15,6 +15,7 @@
 #include "bin/dartutils.h"
 #include "bin/eventhandler.h"
 #include "bin/file.h"
+#include "bin/loader.h"
 #include "bin/log.h"
 #include "bin/thread.h"
 #include "bin/utils.h"
@@ -81,10 +82,6 @@
 // of a generic snapshot that contains only the corelibs).
 static char* app_script_name = NULL;
 
-
-// Global state that captures the URL mappings specified on the command line.
-static CommandLineOptions* url_mapping = NULL;
-
 // Global state that captures the entry point manifest files specified on the
 // command line.
 static CommandLineOptions* entry_points_files = NULL;
@@ -282,7 +279,7 @@
     mapping = ProcessOption(option, "--url-mapping=");
   }
   if (mapping != NULL) {
-    url_mapping->AddArgument(mapping);
+    DartUtils::url_mapping->AddArgument(mapping);
     return true;
   }
   return false;
@@ -418,9 +415,42 @@
   DISALLOW_COPY_AND_ASSIGN(UriResolverIsolateScope);
 };
 
+
 Dart_Isolate UriResolverIsolateScope::isolate = NULL;
 
 
+static Dart_Handle LoadUrlContents(const char* uri_string) {
+  bool failed = false;
+  char* result_string = NULL;
+  uint8_t* payload = NULL;
+  intptr_t payload_length = 0;
+  // Switch to the UriResolver Isolate and load the script.
+  {
+    UriResolverIsolateScope scope;
+
+    Dart_Handle resolved_uri = Dart_NewStringFromCString(uri_string);
+    Dart_Handle result =  Loader::LoadUrlContents(resolved_uri,
+                                                  &payload,
+                                                  &payload_length);
+    if (Dart_IsError(result)) {
+      failed = true;
+      result_string = strdup(Dart_GetError(result));
+    }
+  }
+  // Switch back to the isolate from which we generate the snapshot and
+  // create the source string for the specified uri.
+  Dart_Handle result;
+  if (!failed) {
+    result = Dart_NewStringFromUTF8(payload, payload_length);
+    free(payload);
+  } else {
+    result = DartUtils::NewString(result_string);
+    free(result_string);
+  }
+  return result;
+}
+
+
 static Dart_Handle ResolveUriInWorkingDirectory(const char* script_uri) {
   bool failed = false;
   char* result_string = NULL;
@@ -447,57 +477,27 @@
 }
 
 
-static Dart_Handle FilePathFromUri(const char* script_uri) {
-  bool failed = false;
-  char* result_string = NULL;
-
-  {
-    UriResolverIsolateScope scope;
-
-    // Run DartUtils::FilePathFromUri in context of uri resolver isolate.
-    Dart_Handle result = DartUtils::FilePathFromUri(
-        DartUtils::NewString(script_uri));
-    if (Dart_IsError(result)) {
-      failed = true;
-      result_string = strdup(Dart_GetError(result));
-    } else {
-      result_string = strdup(DartUtils::GetStringValue(result));
-    }
+static Dart_Handle LoadSnapshotCreationScript(const char* script_name) {
+  // First resolve the specified script uri with respect to the original
+  // working directory.
+  Dart_Handle resolved_uri = ResolveUriInWorkingDirectory(script_name);
+  if (Dart_IsError(resolved_uri)) {
+    return resolved_uri;
   }
-
-  Dart_Handle result = failed ? Dart_NewApiError(result_string) :
-                                DartUtils::NewString(result_string);
-  free(result_string);
-  return result;
-}
-
-
-static Dart_Handle ResolveUri(const char* library_uri, const char* uri) {
-  bool failed = false;
-  char* result_string = NULL;
-
-  {
-    UriResolverIsolateScope scope;
-
-    // Run DartUtils::ResolveUri in context of uri resolver isolate.
-    Dart_Handle result = DartUtils::ResolveUri(
-      DartUtils::NewString(library_uri), DartUtils::NewString(uri));
-    if (Dart_IsError(result)) {
-      failed = true;
-      result_string = strdup(Dart_GetError(result));
-    } else {
-      result_string = strdup(DartUtils::GetStringValue(result));
-    }
+  // Now load the contents of the specified uri.
+  const char* resolved_uri_string = DartUtils::GetStringValue(resolved_uri);
+  Dart_Handle source =  LoadUrlContents(resolved_uri_string);
+  if (Dart_IsError(source)) {
+    return source;
   }
-
-  Dart_Handle result = failed ? Dart_NewApiError(result_string) :
-                                DartUtils::NewString(result_string);
-  free(result_string);
-  return result;
+  if (IsSnapshottingForPrecompilation()) {
+    return Dart_LoadScript(resolved_uri, source, 0, 0);
+  } else {
+    return Dart_LoadLibrary(resolved_uri, source, 0, 0);
+  }
 }
 
 
-
 static Builtin::BuiltinLibraryId BuiltinId(const char* url) {
   if (DartUtils::IsDartBuiltinLibURL(url)) {
     return Builtin::kBuiltinLibrary;
@@ -521,7 +521,7 @@
   }
   const char* library_url_string = DartUtils::GetStringValue(library_url);
   const char* mapped_library_url_string = DartUtils::MapLibraryUrl(
-      url_mapping, library_url_string);
+      library_url_string);
   if (mapped_library_url_string != NULL) {
     library_url = ResolveUriInWorkingDirectory(mapped_library_url_string);
     library_url_string = DartUtils::GetStringValue(library_url);
@@ -531,8 +531,7 @@
     return Dart_NewApiError("url is not a string");
   }
   const char* url_string = DartUtils::GetStringValue(url);
-  const char* mapped_url_string = DartUtils::MapLibraryUrl(url_mapping,
-                                                           url_string);
+  const char* mapped_url_string = DartUtils::MapLibraryUrl(url_string);
 
   Builtin::BuiltinLibraryId libraryBuiltinId = BuiltinId(library_url_string);
   if (tag == Dart_kCanonicalizeUrl) {
@@ -543,7 +542,7 @@
     if (libraryBuiltinId != Builtin::kInvalidLibrary) {
       return url;
     }
-    return ResolveUri(library_url_string, url_string);
+    return Dart_DefaultCanonicalizeUrl(library_url, url);
   }
 
   Builtin::BuiltinLibraryId builtinId = BuiltinId(url_string);
@@ -574,15 +573,8 @@
       return resolved_url;
     }
   }
-
-  // Get the file path out of the url.
-  Dart_Handle file_path = FilePathFromUri(
-      DartUtils::GetStringValue(resolved_url));
-  if (Dart_IsError(file_path)) {
-    return file_path;
-  }
-  const char* raw_path = DartUtils::GetStringValue(file_path);
-  Dart_Handle source = DartUtils::ReadStringFromFile(raw_path);
+  const char* resolved_uri_string = DartUtils::GetStringValue(resolved_url);
+  Dart_Handle source =  LoadUrlContents(resolved_uri_string);
   if (Dart_IsError(source)) {
     return source;
   }
@@ -595,29 +587,6 @@
 }
 
 
-static Dart_Handle LoadSnapshotCreationScript(const char* script_name) {
-  Dart_Handle resolved_script_uri = ResolveUriInWorkingDirectory(script_name);
-  if (Dart_IsError(resolved_script_uri)) {
-    return resolved_script_uri;
-  }
-  Dart_Handle script_path = FilePathFromUri(
-      DartUtils::GetStringValue(resolved_script_uri));
-  if (Dart_IsError(script_path)) {
-    return script_path;
-  }
-  Dart_Handle source = DartUtils::ReadStringFromFile(
-      DartUtils::GetStringValue(script_path));
-  if (Dart_IsError(source)) {
-    return source;
-  }
-  if (IsSnapshottingForPrecompilation()) {
-    return Dart_LoadScript(resolved_script_uri, source, 0, 0);
-  } else {
-    return Dart_LoadLibrary(resolved_script_uri, source, 0, 0);
-  }
-}
-
-
 static Dart_Handle LoadGenericSnapshotCreationScript(
     Builtin::BuiltinLibraryId id) {
   Dart_Handle source = Builtin::Source(id);
@@ -1131,7 +1100,7 @@
 
 static void SetupForUriResolution() {
   // Set up the library tag handler for this isolate.
-  Dart_Handle result = Dart_SetLibraryTagHandler(DartUtils::LibraryTagHandler);
+  Dart_Handle result = Dart_SetLibraryTagHandler(Loader::LibraryTagHandler);
   if (Dart_IsError(result)) {
     Log::PrintErr("%s", Dart_GetError(result));
     Dart_ExitScope();
@@ -1189,7 +1158,7 @@
     Log::PrintErr("Error: We only expect to create the service isolate");
     return NULL;
   }
-  Dart_Handle result = Dart_SetLibraryTagHandler(DartUtils::LibraryTagHandler);
+  Dart_Handle result = Dart_SetLibraryTagHandler(Loader::LibraryTagHandler);
   // Setup the native resolver.
   Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
   Builtin::LoadAndCheckLibrary(Builtin::kIOLibrary);
@@ -1215,8 +1184,8 @@
   CommandLineOptions vm_options(argc + EXTRA_VM_ARGUMENTS);
 
   // Initialize the URL mapping array.
-  CommandLineOptions url_mapping_array(argc);
-  url_mapping = &url_mapping_array;
+  CommandLineOptions cmdline_url_mapping(argc);
+  DartUtils::url_mapping = &cmdline_url_mapping;
 
   // Initialize the entrypoints array.
   CommandLineOptions entry_points_files_array(argc);
@@ -1278,7 +1247,9 @@
     return 255;
   }
 
-  IsolateData* isolate_data = new IsolateData(NULL, NULL, NULL);
+  IsolateData* isolate_data = new IsolateData(NULL,
+                                              commandline_package_root,
+                                              commandline_packages_file);
   Dart_Isolate isolate = Dart_CreateIsolate(
       NULL, NULL, NULL, NULL, isolate_data, &error);
   if (isolate == NULL) {
@@ -1302,7 +1273,6 @@
     // create a full snapshot. The current isolate is set up so that we can
     // invoke the dart uri resolution code like _resolveURI. App script is
     // loaded into a separate isolate.
-
     SetupForUriResolution();
 
     // Prepare builtin and its dependent libraries for use to resolve URIs.
@@ -1321,11 +1291,10 @@
                                          commandline_packages_file);
     CHECK_RESULT(result);
 
+    UriResolverIsolateScope::isolate = isolate;
     Dart_ExitScope();
     Dart_ExitIsolate();
 
-    UriResolverIsolateScope::isolate = isolate;
-
     // Now we create an isolate into which we load all the code that needs to
     // be in the snapshot.
     isolate_data = new IsolateData(NULL, NULL, NULL);
diff --git a/runtime/bin/loader.cc b/runtime/bin/loader.cc
index 4b887ad..8e24f67 100644
--- a/runtime/bin/loader.cc
+++ b/runtime/bin/loader.cc
@@ -25,7 +25,9 @@
       pending_operations_(0),
       results_(NULL),
       results_length_(0),
-      results_capacity_(0) {
+      results_capacity_(0),
+      payload_(NULL),
+      payload_length_(0) {
   monitor_ = new Monitor();
   ASSERT(isolate_data_ != NULL);
   port_ = Dart_NewNativePort("Loader",
@@ -54,6 +56,8 @@
   }
   free(results_);
   results_ = NULL;
+  payload_ = NULL;
+  payload_length_ = 0;
 }
 
 
@@ -191,13 +195,13 @@
 }
 
 
-void Loader::BlockUntilComplete() {
+void Loader::BlockUntilComplete(ProcessResult process_result) {
   MonitorLocker ml(monitor_);
 
   while (true) {
     // If |ProcessQueueLocked| returns false, we've hit an error and should
     // stop loading.
-    if (!ProcessQueueLocked()) {
+    if (!ProcessQueueLocked(process_result)) {
       break;
     }
 
@@ -225,7 +229,7 @@
 }
 
 
-bool Loader::ProcessResultLocked(Loader::IOResult* result) {
+bool Loader::ProcessResultLocked(Loader* loader, Loader::IOResult* result) {
   // We have to copy everything we care about out of |result| because after
   // dropping the lock below |result| may no longer valid.
   Dart_Handle uri =
@@ -249,7 +253,7 @@
       return true;
     }
     // Fall through
-    error_ = Dart_NewUnhandledExceptionError(error);
+    loader->error_ = Dart_NewUnhandledExceptionError(error);
     return false;
   }
 
@@ -267,8 +271,9 @@
     source = Dart_NewStringFromUTF8(result->payload,
                                     result->payload_length);
     if (Dart_IsError(source)) {
-      error_  = DartUtils::NewError("%s is not a valid UTF-8 script",
-                                    reinterpret_cast<char*>(result->uri));
+      loader->error_ = DartUtils::NewError(
+          "%s is not a valid UTF-8 script",
+          reinterpret_cast<char*>(result->uri));
       return false;
     }
   }
@@ -279,7 +284,7 @@
 
   // We must drop the lock here because the tag handler may be recursively
   // invoked and it will attempt to acquire the lock to queue more work.
-  monitor_->Exit();
+  loader->monitor_->Exit();
 
   Dart_Handle dart_result = Dart_Null();
 
@@ -306,10 +311,10 @@
   }
 
   // Re-acquire the lock before exiting the function (it was held before entry),
-  monitor_->Enter();
+  loader->monitor_->Enter();
   if (Dart_IsError(dart_result)) {
     // Remember the error if we encountered one.
-    error_ = dart_result;
+    loader->error_ = dart_result;
     return false;
   }
 
@@ -317,11 +322,29 @@
 }
 
 
-bool Loader::ProcessQueueLocked() {
+bool Loader::ProcessUrlLoadResultLocked(Loader* loader,
+                                        Loader::IOResult* result) {
+  // A negative result tag indicates a loading error occurred in the service
+  // isolate. The payload is a C string of the error message.
+  if (result->tag < 0) {
+    Dart_Handle error = Dart_NewStringFromUTF8(result->payload,
+                                               result->payload_length);
+    loader->error_ = Dart_NewUnhandledExceptionError(error);
+    return false;
+  }
+  loader->payload_length_ = result->payload_length;
+  loader->payload_ =
+      reinterpret_cast<uint8_t*>(::malloc(loader->payload_length_));
+  memmove(loader->payload_, result->payload, loader->payload_length_);
+  return true;
+}
+
+
+bool Loader::ProcessQueueLocked(ProcessResult process_result) {
   bool hit_error = false;
   for (intptr_t i = 0; i < results_length(); i++) {
     if (!hit_error) {
-      hit_error = !ProcessResultLocked(&results_[i]);
+      hit_error = !(*process_result)(this, &results_[i]);
     }
     pending_operations_--;
     ASSERT(hit_error || (pending_operations_ >= 0));
@@ -358,6 +381,48 @@
 }
 
 
+Dart_Handle Loader::LoadUrlContents(Dart_Handle url,
+                                    uint8_t** payload,
+                                    intptr_t* payload_length) {
+  IsolateData* isolate_data =
+      reinterpret_cast<IsolateData*>(Dart_CurrentIsolateData());
+  ASSERT(isolate_data != NULL);
+  ASSERT(!isolate_data->HasLoader());
+  Loader* loader = NULL;
+
+  // Setup the loader. The constructor does a bunch of leg work.
+  loader = new Loader(isolate_data);
+  loader->Init(isolate_data->package_root,
+               isolate_data->packages_file,
+               DartUtils::original_working_directory,
+               NULL);
+  ASSERT(loader != NULL);
+  ASSERT(isolate_data->HasLoader());
+
+  // Now send a load request to the service isolate.
+  loader->SendRequest(Dart_kScriptTag, url, Dart_Null());
+
+  // Wait for a reply to the load request.
+  loader->BlockUntilComplete(ProcessUrlLoadResultLocked);
+
+  // Copy fields from the loader before deleting it.
+  // The payload array itself which was malloced above is freed by
+  // the caller of LoadUrlContents.
+  Dart_Handle error = loader->error();
+  *payload = loader->payload_;
+  *payload_length = loader->payload_length_;
+
+  // Destroy the loader. The destructor does a bunch of leg work.
+  delete loader;
+
+  // An error occurred during loading.
+  if (!Dart_IsNull(error)) {
+    return error;
+  }
+  return Dart_Null();
+}
+
+
 Dart_Handle Loader::LibraryTagHandler(Dart_LibraryTag tag,
                                       Dart_Handle library,
                                       Dart_Handle url) {
@@ -466,7 +531,7 @@
   if (blocking_call) {
     // The outer invocation of the tag handler will block here until all nested
     // invocations complete.
-    loader->BlockUntilComplete();
+    loader->BlockUntilComplete(ProcessResultLocked);
 
     // Remember the error (if any).
     Dart_Handle error = loader->error();
diff --git a/runtime/bin/loader.h b/runtime/bin/loader.h
index 792ea45..088ce2e 100644
--- a/runtime/bin/loader.h
+++ b/runtime/bin/loader.h
@@ -22,6 +22,12 @@
 
   static void InitForSnapshot(const char* snapshot_uri);
 
+  // Loads contents of the specified url.
+  static Dart_Handle LoadUrlContents(Dart_Handle url,
+                                     uint8_t** payload,
+                                     intptr_t* payload_length);
+
+
   // A static tag handler that hides all usage of a loader for an isolate.
   static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag,
                                        Dart_Handle library,
@@ -62,6 +68,9 @@
   IOResult* results_;
   intptr_t results_length_;
   intptr_t results_capacity_;
+  uint8_t* payload_;
+  intptr_t payload_length_;
+  typedef bool (*ProcessResult)(Loader* loader, IOResult* result);
 
   intptr_t results_length() {
     return *static_cast<volatile intptr_t*>(&results_length_);
@@ -82,13 +91,16 @@
   void QueueMessage(Dart_CObject* message);
 
   /// Blocks the caller until the loader is finished.
-  void BlockUntilComplete();
+  void BlockUntilComplete(ProcessResult process_result);
 
   /// Returns false if |result| is an error and the loader should quit.
-  bool ProcessResultLocked(IOResult* result);
+  static bool ProcessResultLocked(Loader* loader, IOResult* result);
+
+  /// Returns false if |result| is an error and the loader should quit.
+  static bool ProcessUrlLoadResultLocked(Loader* loader, IOResult* result);
 
   /// Returns false if an error occurred and the loader should quit.
-  bool ProcessQueueLocked();
+  bool ProcessQueueLocked(ProcessResult process_result);
 
   // Special inner tag handler for dart: uris.
   static Dart_Handle DartColonLibraryTagHandler(Dart_LibraryTag tag,
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 6c8ca4b..d7bfb3b 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -207,7 +207,7 @@
 static bool ProcessPackageRootOption(const char* arg,
                                      CommandLineOptions* vm_options) {
   ASSERT(arg != NULL);
-  if (*arg == '\0' || *arg == '-') {
+  if (*arg == '-') {
     return false;
   }
   commandline_package_root = arg;
@@ -216,9 +216,9 @@
 
 
 static bool ProcessPackagesOption(const char* arg,
-                                     CommandLineOptions* vm_options) {
+                                  CommandLineOptions* vm_options) {
   ASSERT(arg != NULL);
-  if ((*arg == '\0') || (*arg == '-')) {
+  if (*arg == '-') {
     return false;
   }
   commandline_packages_file = arg;
@@ -592,6 +592,16 @@
                   "file is invalid.\n");
     return -1;
   }
+  if ((commandline_package_root != NULL) &&
+      (strlen(commandline_package_root) == 0)) {
+    Log::PrintErr("Empty package root specified.\n");
+    return -1;
+  }
+  if ((commandline_packages_file != NULL) &&
+      (strlen(commandline_packages_file) == 0)) {
+    Log::PrintErr("Empty package file name specified.\n");
+    return -1;
+  }
   if (is_noopt && gen_snapshot_kind != kNone) {
     Log::PrintErr("Generating a snapshot with dart_noopt is invalid.\n");
     return -1;
diff --git a/runtime/bin/vmservice/loader.dart b/runtime/bin/vmservice/loader.dart
index 82fbe5e..cb6792b 100644
--- a/runtime/bin/vmservice/loader.dart
+++ b/runtime/bin/vmservice/loader.dart
@@ -480,7 +480,7 @@
                        Uri uri,
                        Uri resolvedUri,
                        String libraryUrl) {
-  if (resolvedUri.scheme == 'file') {
+  if (resolvedUri.scheme == '' || resolvedUri.scheme == 'file') {
     _loadFile(sp, tag, uri, resolvedUri, libraryUrl);
   } else if ((resolvedUri.scheme == 'http') ||
              (resolvedUri.scheme == 'https')) {
@@ -805,7 +805,7 @@
                        Uri resource) async {
   try {
     if (tag == -1) {
-      if (resource.scheme == 'file') {
+      if (resource.scheme == '' || resource.scheme == 'file') {
         _findPackagesFile(sp, traceLoading, resource);
       } else if ((resource.scheme == 'http') || (resource.scheme == 'https')) {
         // Try to load the .packages file next to the resource.
@@ -825,7 +825,7 @@
       if (traceLoading) {
         _log("Handling load of packages map: '$resource'.");
       }
-      if (resource.scheme == 'file') {
+      if (resource.scheme == '' || resource.scheme == 'file') {
         var exists = await new File.fromUri(resource).exists();
         if (exists) {
           _loadPackagesFile(sp, traceLoading, resource);
diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc
index 2736408..b7f4df4 100644
--- a/runtime/bin/vmservice_impl.cc
+++ b/runtime/bin/vmservice_impl.cc
@@ -342,8 +342,8 @@
     return result;
   }
   if (tag == Dart_kImportTag) {
-    // Embedder handles all requests for external libraries.
-    return DartUtils::LibraryTagHandler(tag, library, url);
+    UNREACHABLE();
+    return Dart_Null();
   }
   ASSERT((tag == Dart_kSourceTag) || (tag == Dart_kCanonicalizeUrl));
   if (tag == Dart_kCanonicalizeUrl) {
diff --git a/runtime/lib/errors.cc b/runtime/lib/errors.cc
index 0387f80..28d4ef4 100644
--- a/runtime/lib/errors.cc
+++ b/runtime/lib/errors.cc
@@ -26,6 +26,7 @@
 
   DartFrameIterator iterator;
   iterator.NextFrame();  // Skip native call.
+  iterator.NextFrame();  // Skip _AssertionError._checkAssertion frame
   const Script& script = Script::Handle(Exceptions::GetCallerScript(&iterator));
 
   // Initialize argument 'failed_assertion' with source snippet.
diff --git a/runtime/lib/errors_patch.dart b/runtime/lib/errors_patch.dart
index 8c995a4..faf342b 100644
--- a/runtime/lib/errors_patch.dart
+++ b/runtime/lib/errors_patch.dart
@@ -26,9 +26,13 @@
   static _throwNew(int assertionStart, int assertionEnd)
       native "AssertionError_throwNew";
 
-  static _handleCondition(condition) {
-    if (condition is Function) return condition();
-    return condition;
+  static void _checkAssertion(condition, int start, int end) {
+    if (condition is Function) {
+      condition = condition();
+    }
+    if (!condition) {
+      _throwNew(start, end);
+    }
   }
 
   String toString() {
diff --git a/runtime/lib/integers.cc b/runtime/lib/integers.cc
index 351cbbf..5680037 100644
--- a/runtime/lib/integers.cc
+++ b/runtime/lib/integers.cc
@@ -146,7 +146,7 @@
   const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1));
   ASSERT(CheckInteger(right_int));
-  ASSERT(CheckInteger(right_int));
+  ASSERT(CheckInteger(left_int));
   if (FLAG_trace_intrinsified_natives) {
     OS::Print("Integer_moduloFromInteger %s mod %s\n",
         left_int.ToCString(), right_int.ToCString());
diff --git a/runtime/lib/isolate_patch.dart b/runtime/lib/isolate_patch.dart
index 09ae531..4dd89c0 100644
--- a/runtime/lib/isolate_patch.dart
+++ b/runtime/lib/isolate_patch.dart
@@ -312,13 +312,12 @@
     try {
       // The VM will invoke [_startIsolate] with entryPoint as argument.
       readyPort = new RawReceivePort();
-      var packageRoot = null;
-      var packageConfig = null;
-      if (Isolate._packageSupported()) {
-        packageRoot = (await Isolate.packageRoot)?.toString();
-        packageConfig = (await Isolate.packageConfig)?.toString();
-      }
 
+      // We do not inherit the package root or package config settings
+      // from the parent isolate, instead we use the values that were
+      // set on the command line.
+      var packageRoot = VMLibraryHooks.packageRootString;
+      var packageConfig = VMLibraryHooks.packageConfigString;
       var script = VMLibraryHooks.platformScript;
       if (script == null) {
         // We do not have enough information to support spawning the new
diff --git a/runtime/observatory/.analysis_options b/runtime/observatory/.analysis_options
index fd7cfbf..fc9ab29 100644
--- a/runtime/observatory/.analysis_options
+++ b/runtime/observatory/.analysis_options
@@ -1,9 +1,6 @@
 analyzer:
   exclude:
-# Remove once Dart 1.13-dev is released
+    - tests/service/get_isolate_after_language_error_test.dart
     - tests/service/developer_extension_test.dart
-# Remove once Dart 1.13-dev is released
-    - tests/service/logging_test.dart
-    - tests/ui/log.dart
-# Remove once Dart 1.13-dev is released
-    - tests/service/get_stack_rpc_test.dart
+    - tests/service/address_mapper_test.dart
+    - tests/service/pause_on_unhandled_exceptions_test.dart
diff --git a/runtime/observatory/lib/src/debugger/debugger_location.dart b/runtime/observatory/lib/src/debugger/debugger_location.dart
index 7688712..ac3a9bf 100644
--- a/runtime/observatory/lib/src/debugger/debugger_location.dart
+++ b/runtime/observatory/lib/src/debugger/debugger_location.dart
@@ -256,7 +256,6 @@
         return new DebuggerLocation.error(
             "Function '${match.group(0)}' is ambiguous");
       }
-      return new DebuggerLocation.error('foo');
     });
   }
 
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index a839728..18d29bf 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -46,6 +46,7 @@
   static const kFileSystemAlreadyExists = 1001;
   static const kFileSystemDoesNotExist  = 1002;
   static const kFileDoesNotExist        = 1003;
+  static const kIsolateReloadFailed     = 1004;
 
   int code;
   Map data;
@@ -1640,7 +1641,7 @@
   }
 
   Future<ObjectStore> getObjectStore() {
-    return invokeRpc('_getObjectStore', {}).then((map) {
+    return invokeRpcNoUpgrade('_getObjectStore', {}).then((map) {
       ObjectStore objectStore = new ObjectStore._empty(this);
       objectStore._update(map, false);
       return objectStore;
diff --git a/runtime/observatory/tests/service/dev_fs_test.dart b/runtime/observatory/tests/service/dev_fs_test.dart
index 9f23396..8855e13 100644
--- a/runtime/observatory/tests/service/dev_fs_test.dart
+++ b/runtime/observatory/tests/service/dev_fs_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 // VMOptions=--error_on_bad_type --error_on_bad_override
 
-import 'dart:async';
 import 'dart:convert';
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/evaluate_activation_in_method_class_other.dart b/runtime/observatory/tests/service/evaluate_activation_in_method_class_other.dart
index 6cc5879..bf070a1 100644
--- a/runtime/observatory/tests/service/evaluate_activation_in_method_class_other.dart
+++ b/runtime/observatory/tests/service/evaluate_activation_in_method_class_other.dart
@@ -11,6 +11,7 @@
   var instVar = 'Superclass';
   method() => 'Superclass';
   static staticMethod() => 'Superclass';
+  suppress_warning() => _instVar;
 }
 
 class Klass extends Superclass {
@@ -22,5 +23,7 @@
   test() {
     var _local = 'Klass';
     debugger();
+    // Suppress unused variable warning.
+    print(_local);
   }
 }
diff --git a/runtime/observatory/tests/service/evaluate_activation_in_method_class_test.dart b/runtime/observatory/tests/service/evaluate_activation_in_method_class_test.dart
index cfe4315..d07b832 100644
--- a/runtime/observatory/tests/service/evaluate_activation_in_method_class_test.dart
+++ b/runtime/observatory/tests/service/evaluate_activation_in_method_class_test.dart
@@ -20,6 +20,7 @@
   var instVar = 'Subclass';
   method() => 'Subclass';
   static staticMethod() => 'Subclass';
+  suppress_warning() => _instVar;
 }
 
 testeeDo() {
@@ -70,7 +71,7 @@
   result = await isolate.evalFrame(topFrame, 'staticMethod()');
   print(result);
   expect(result.valueAsString, equals('Klass'));
-  
+
   // function.Owner verus function.Origin
   // The mixin of Superclass is in _other.dart and the mixin
   // application is in _test.dart.
diff --git a/runtime/observatory/tests/service/get_isolate_after_language_error_test.dart b/runtime/observatory/tests/service/get_isolate_after_language_error_test.dart
index dc763a0..ccb00fe 100644
--- a/runtime/observatory/tests/service/get_isolate_after_language_error_test.dart
+++ b/runtime/observatory/tests/service/get_isolate_after_language_error_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 // VMOptions=--error_on_bad_type --error_on_bad_override
 
-import 'dart:async';
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
 import 'test_helper.dart';
@@ -29,4 +28,4 @@
 main(args) => runIsolateTestsSynchronous(args,
                                          tests,
                                          pause_on_exit: true,
-                                         testeeConcurrent: doThrow);
\ No newline at end of file
+                                         testeeConcurrent: doThrow);
diff --git a/runtime/observatory/tests/service/get_isolate_after_stack_overflow_error_test.dart b/runtime/observatory/tests/service/get_isolate_after_stack_overflow_error_test.dart
new file mode 100644
index 0000000..0223218
--- /dev/null
+++ b/runtime/observatory/tests/service/get_isolate_after_stack_overflow_error_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--error_on_bad_type --error_on_bad_override
+
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+// Non tailable recursive function that should trigger a Stack Overflow.
+num factorialGrowth([num n = 1]) {
+  return factorialGrowth(n + 1) * n;
+}
+
+void nonTailableRecursion() {
+  factorialGrowth();
+}
+
+var tests = [
+  hasStoppedAtExit,
+
+  (Isolate isolate) async {
+    await isolate.reload();
+    expect(isolate.error, isNotNull);
+    expect(isolate.error.message.contains('Stack Overflow'), isTrue);
+  }
+];
+
+main(args) async => runIsolateTests(args,
+                              tests,
+                              pause_on_exit: true,
+                              testeeConcurrent: nonTailableRecursion);
diff --git a/runtime/observatory/tests/service/get_object_store_rpc_test.dart b/runtime/observatory/tests/service/get_object_store_rpc_test.dart
new file mode 100644
index 0000000..fb7f7f6
--- /dev/null
+++ b/runtime/observatory/tests/service/get_object_store_rpc_test.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--error_on_bad_type --error_on_bad_override
+
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+import 'dart:developer' as developer;
+
+void doDebugger() {
+  developer.debugger(message: "foo", when: true);
+}
+
+bool isClosureFunctionsList(NamedField field) {
+  return field.name == 'closure_functions_';
+}
+
+var tests = [
+
+// Initial data fetch and verify we've hit the breakpoint.
+(Isolate isolate) async {
+  await isolate.rootLibrary.load();
+  var script = isolate.rootLibrary.scripts[0];
+  await script.load();
+  await hasStoppedAtBreakpoint(isolate);
+  // Sanity check.
+  expect(isolate.pauseEvent.kind, equals(ServiceEvent.kPauseBreakpoint));
+},
+
+// Get object_store.
+(Isolate isolate) async {
+  var object_store = await isolate.getObjectStore();
+  expect(object_store.runtimeType, equals(ObjectStore));
+  // Sanity check.
+  expect(object_store.fields.length, greaterThanOrEqualTo(1));
+  // Checking Closures.
+  expect(object_store.fields.singleWhere(isClosureFunctionsList), isNotNull);
+  expect(object_store.fields.singleWhere(isClosureFunctionsList).value.isList, isTrue);
+}
+
+];
+
+main(args) => runIsolateTestsSynchronous(args, tests,
+                                          testeeConcurrent: doDebugger);
diff --git a/runtime/observatory/tests/service/instance_field_order_rpc_test.dart b/runtime/observatory/tests/service/instance_field_order_rpc_test.dart
index 0323f8c..f39d324 100644
--- a/runtime/observatory/tests/service/instance_field_order_rpc_test.dart
+++ b/runtime/observatory/tests/service/instance_field_order_rpc_test.dart
@@ -5,7 +5,6 @@
 
 library get_object_rpc_test;
 
-import 'dart:typed_data';
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
 import 'test_helper.dart';
diff --git a/runtime/observatory/tests/service/pause_idle_isolate_test.dart b/runtime/observatory/tests/service/pause_idle_isolate_test.dart
index a75dcd1..859291f 100644
--- a/runtime/observatory/tests/service/pause_idle_isolate_test.dart
+++ b/runtime/observatory/tests/service/pause_idle_isolate_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 // VMOptions=--error_on_bad_type --error_on_bad_override
 
-import 'dart:async';
 import 'dart:developer';
 import 'dart:io';
 import 'dart:isolate' show ReceivePort;
diff --git a/runtime/observatory/tests/service/pause_on_exceptions_test.dart b/runtime/observatory/tests/service/pause_on_exceptions_test.dart
index 03d4731..da2e250 100644
--- a/runtime/observatory/tests/service/pause_on_exceptions_test.dart
+++ b/runtime/observatory/tests/service/pause_on_exceptions_test.dart
@@ -10,7 +10,6 @@
 
 doThrow() {
   throw "TheException"; // Line 13.
-  return "end of doThrow";
 }
 
 doCaught() {
diff --git a/runtime/observatory/tests/service/set_name_rpc_test.dart b/runtime/observatory/tests/service/set_name_rpc_test.dart
new file mode 100644
index 0000000..bb3d8c8
--- /dev/null
+++ b/runtime/observatory/tests/service/set_name_rpc_test.dart
@@ -0,0 +1,36 @@
+// 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=--error_on_bad_type --error_on_bad_override --vm-name=Walter
+
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+import 'dart:async';
+
+var tests = [
+  (Isolate isolate) async {
+    expect(isolate.name, equals('set_name_rpc_test.dart\$main'));
+
+    Completer completer = new Completer();
+    var stream = await isolate.vm.getEventStream(VM.kIsolateStream);
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kIsolateUpdate) {
+        expect(event.owner.type, equals('Isolate'));
+        expect(event.owner.name, equals('Barbara'));
+        subscription.cancel();
+        completer.complete();
+      }
+    });
+
+    var result = await isolate.setName('Barbara');
+    expect(result.type, equals('Success'));
+
+    await completer.future;
+    expect(isolate.name, equals('Barbara'));
+
+  }
+];
+
+main(args) async => runIsolateTests(args, tests);
diff --git a/runtime/observatory/tests/service/string_escaping_test.dart b/runtime/observatory/tests/service/string_escaping_test.dart
index fd99cee..0f5dee4 100644
--- a/runtime/observatory/tests/service/string_escaping_test.dart
+++ b/runtime/observatory/tests/service/string_escaping_test.dart
@@ -48,44 +48,47 @@
   malformedWithTrailSurrogate = "before" + "𝄞"[1] + "after";
 }
 
+testStrings(Isolate isolate) async {
+  Library lib = isolate.rootLibrary;
+  await lib.load();
+  for (var variable in lib.variables) {
+    await variable.load();
+  }
+
+  expectFullString(String varName, String varValueAsString) {
+    Field field = lib.variables.singleWhere((v) => v.name == varName);
+    Instance value = field.staticValue;
+    expect(value.valueAsString, equals(varValueAsString));
+    expect(value.valueAsStringIsTruncated, isFalse);
+  }
+
+  expectTruncatedString(String varName, String varValueAsString) {
+    Field field = lib.variables.singleWhere((v) => v.name == varName);
+    Instance value = field.staticValue;
+    print(value.valueAsString);
+    expect(varValueAsString, startsWith(value.valueAsString));
+    expect(value.valueAsStringIsTruncated, isTrue);
+  }
+
+  script();  // Need to initialize variables in the testing isolate.
+  expectFullString('ascii', ascii);
+  expectFullString('latin1', latin1);
+  expectFullString('unicode', unicode);
+  expectFullString('hebrew', hebrew);
+  expectFullString('singleQuotes', singleQuotes);
+  expectFullString('doubleQuotes', doubleQuotes);
+  expectFullString('newLines', newLines);
+  expectFullString('tabs', tabs);
+  expectFullString('suggrogatePairs', suggrogatePairs);
+  expectFullString('nullInTheMiddle', nullInTheMiddle);
+  expectTruncatedString('longStringEven', longStringEven);
+  expectTruncatedString('longStringOdd', longStringOdd);
+  expectFullString('malformedWithLeadSurrogate', malformedWithLeadSurrogate);
+  expectFullString('malformedWithTrailSurrogate', malformedWithTrailSurrogate);
+}
+
 var tests = [
-
-(Isolate isolate) =>
-  isolate.rootLibrary.load().then((Library lib) {
-    expectFullString(String varName, String varValueAsString) {
-      Field field = lib.variables.singleWhere((v) => v.name == varName);
-      field.load().then((_) {
-        Instance value = field.staticValue;
-        expect(value.valueAsString, equals(varValueAsString));
-        expect(value.valueAsStringIsTruncated, isFalse);
-      });
-    }
-    expectTruncatedString(String varName, String varValueAsString) {
-      Field field = lib.variables.singleWhere((v) => v.name == varName);
-      field.load().then((_) {
-        Instance value = field.staticValue;
-        expect(varValueAsString, startsWith(value.valueAsString));
-        expect(value.valueAsStringIsTruncated, isTrue);
-      });
-    }
-
-    script();  // Need to initialize variables in the testing isolate.
-    expectFullString('ascii', ascii);
-    expectFullString('latin1', latin1);
-    expectFullString('unicode', unicode);
-    expectFullString('hebrew', hebrew);
-    expectFullString('singleQuotes', singleQuotes);
-    expectFullString('doubleQuotes', doubleQuotes);
-    expectFullString('newLines', newLines);
-    expectFullString('tabs', tabs);
-    expectFullString('suggrogatePairs', suggrogatePairs);
-    expectFullString('nullInTheMiddle', nullInTheMiddle);
-    expectTruncatedString('longStringEven', longStringEven);
-    expectTruncatedString('longStringOdd', longStringOdd);
-    expectFullString('malformedWithLeadSurrogate', malformedWithLeadSurrogate);
-    expectFullString('malformedWithTrailSurrogate', malformedWithTrailSurrogate);
-  }),
-
+  testStrings,
 ];
 
 main(args) => runIsolateTests(args, tests, testeeBefore: script);
diff --git a/runtime/observatory/tests/service/test_helper.dart b/runtime/observatory/tests/service/test_helper.dart
index e22cbb2..1d2ea9d 100644
--- a/runtime/observatory/tests/service/test_helper.dart
+++ b/runtime/observatory/tests/service/test_helper.dart
@@ -36,7 +36,7 @@
   return Platform.environment[_SKY_SHELL_ENV_KEY];
 }
 
-class _SerivceTesteeRunner {
+class _ServiceTesteeRunner {
   Future run({testeeBefore(): null,
               testeeConcurrent(): null,
               bool pause_on_start: false,
@@ -335,7 +335,7 @@
                         bool pause_on_unhandled_exceptions: false}) async {
   assert(!pause_on_start || testeeBefore == null);
   if (_isTestee()) {
-    new _SerivceTesteeRunner().run(testeeBefore: testeeBefore,
+    new _ServiceTesteeRunner().run(testeeBefore: testeeBefore,
                                    testeeConcurrent: testeeConcurrent,
                                    pause_on_start: pause_on_start,
                                    pause_on_exit: pause_on_exit);
@@ -373,7 +373,7 @@
                                  bool pause_on_unhandled_exceptions: false}) {
   assert(!pause_on_start || testeeBefore == null);
   if (_isTestee()) {
-    new _SerivceTesteeRunner().runSync(testeeBeforeSync: testeeBefore,
+    new _ServiceTesteeRunner().runSync(testeeBeforeSync: testeeBefore,
                                        testeeConcurrentSync: testeeConcurrent,
                                        pause_on_start: pause_on_start,
                                        pause_on_exit: pause_on_exit);
@@ -406,7 +406,7 @@
                    bool verbose_vm: false,
                    bool pause_on_unhandled_exceptions: false}) async {
   if (_isTestee()) {
-    new _SerivceTesteeRunner().run(testeeBefore: testeeBefore,
+    new _ServiceTesteeRunner().run(testeeBefore: testeeBefore,
                                    testeeConcurrent: testeeConcurrent,
                                    pause_on_start: pause_on_start,
                                    pause_on_exit: pause_on_exit);
diff --git a/runtime/platform/assert.cc b/runtime/platform/assert.cc
index e9d1c4f..c5b91e7 100644
--- a/runtime/platform/assert.cc
+++ b/runtime/platform/assert.cc
@@ -4,9 +4,6 @@
 
 #include "platform/assert.h"
 
-#include <sstream>
-#include <string>
-
 #include "platform/globals.h"
 #include "vm/os.h"
 
@@ -18,19 +15,27 @@
 }
 
 void DynamicAssertionHelper::Fail(const char* format, ...) {
-  std::ostringstream stream;
-  stream << file_ << ":" << line_ << ": error: ";
+  // Take only the last 1KB of the file name if it is longer.
+  const intptr_t file_len = strlen(file_);
+  const intptr_t file_offset = (file_len > (1 * KB)) ? file_len - (1 * KB) : 0;
+  const char* file = file_ + file_offset;
 
+  // Print the file and line number into the buffer.
+  char buffer[4 * KB];
+  intptr_t file_and_line_length =
+      snprintf(buffer, sizeof(buffer), "%s: %d: error: ", file, line_);
+
+  // Print the error message into the buffer.
   va_list arguments;
   va_start(arguments, format);
-  char buffer[4 * KB];
-  vsnprintf(buffer, sizeof(buffer), format, arguments);
+  vsnprintf(buffer + file_and_line_length,
+            sizeof(buffer) - file_and_line_length,
+            format,
+            arguments);
   va_end(arguments);
-  stream << buffer << std::endl;
 
-  // Get the message from the string stream and dump it on stderr.
-  std::string message = stream.str();
-  fprintf(stderr, "%s", message.c_str());
+  // Print the buffer on stderr.
+  fprintf(stderr, "%s\n", buffer);
   fflush(stderr);
 
   // In case of failed assertions, abort right away. Otherwise, wait
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 2313aab..1faa41c 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -13,6 +13,9 @@
 cc/ArrayNew_Overflow_Crash: Crash, Timeout
 cc/AllocGeneric_Overflow: Crash, Timeout
 cc/CodeImmutability: Crash
+cc/Fail0: Fail
+cc/Fail1: Fail
+cc/Fail2: Fail
 
 cc/SNPrint_BadArgs: Skip
 
@@ -85,8 +88,8 @@
 [ $builder_tag == asan ]
 cc/CodeImmutability: Fail,OK # Address Sanitizer turns a crash into a failure.
 
-[ $noopt ]
-dart/byte_array_test: Crash # Incompatible flag --disable_alloc_stubs_after_gc
+[ $noopt || $compiler == precompiler ]
+dart/byte_array_test: Skip # Incompatible flag --disable_alloc_stubs_after_gc
 
 [ $noopt || $compiler == precompiler || $mode == product ]
 dart/redirection_type_shuffling_test: SkipByDesign # Imports dart:mirrors
diff --git a/runtime/vm/aot_optimizer.cc b/runtime/vm/aot_optimizer.cc
index 7cae460..89d6b09 100644
--- a/runtime/vm/aot_optimizer.cc
+++ b/runtime/vm/aot_optimizer.cc
@@ -1949,7 +1949,8 @@
 // If type tests specified by 'ic_data' do not depend on type arguments,
 // return mapping cid->result in 'results' (i : cid; i + 1: result).
 // If all tests yield the same result, return it otherwise return Bool::null.
-// If no mapping is possible, 'results' is empty.
+// If no mapping is possible, 'results' has less than
+// (ic_data.NumberOfChecks() * 2) entries
 // An instance-of test returning all same results can be converted to a class
 // check.
 RawBool* AotOptimizer::InstanceOfAsBool(
@@ -2078,7 +2079,7 @@
 // TODO(srdjan): Do also for other than 'int' type.
 static bool TryExpandTestCidsResult(ZoneGrowableArray<intptr_t>* results,
                                     const AbstractType& type) {
-  ASSERT(results->length() >= 2);  // At least on eentry.
+  ASSERT(results->length() >= 2);  // At least on entry.
   const ClassTable& class_table = *Isolate::Current()->class_table();
   if ((*results)[0] != kSmiCid) {
     const Class& cls = Class::Handle(class_table.At(kSmiCid));
@@ -2100,14 +2101,26 @@
 
   ASSERT(type.IsInstantiated() && !type.IsMalformedOrMalbounded());
   ASSERT(results->length() >= 2);
-  if (type.IsIntType()) {
+  if (type.IsSmiType()) {
+    ASSERT((*results)[0] == kSmiCid);
+    return false;
+  } else if (type.IsIntType()) {
     ASSERT((*results)[0] == kSmiCid);
     TryAddTest(results, kMintCid, true);
     TryAddTest(results, kBigintCid, true);
     // Cannot deoptimize since all tests returning true have been added.
     return false;
+  } else if (type.IsNumberType()) {
+    ASSERT((*results)[0] == kSmiCid);
+    TryAddTest(results, kMintCid, true);
+    TryAddTest(results, kBigintCid, true);
+    TryAddTest(results, kDoubleCid, true);
+    return false;
+  } else if (type.IsDoubleType()) {
+    ASSERT((*results)[0] == kSmiCid);
+    TryAddTest(results, kDoubleCid, true);
+    return false;
   }
-
   return true;  // May deoptimize since we have not identified all 'true' tests.
 }
 
@@ -2115,11 +2128,6 @@
 // TODO(srdjan): Use ICData to check if always true or false.
 void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
   ASSERT(Token::IsTypeTestOperator(call->token_kind()));
-  // Guard against repeated speculative inlining.
-  if (!use_speculative_inlining_ ||
-      IsBlackListedForInlining(call->deopt_id())) {
-    return;
-  }
   Definition* left = call->ArgumentAt(0);
   Definition* type_args = NULL;
   AbstractType& type = AbstractType::ZoneHandle(Z);
@@ -2152,46 +2160,6 @@
     negate = Bool::Cast(call->ArgumentAt(3)->OriginalDefinition()
         ->AsConstant()->value()).value();
   }
-  const ICData& unary_checks =
-      ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
-  if ((unary_checks.NumberOfChecks() > 0) &&
-      (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) {
-    ZoneGrowableArray<intptr_t>* results =
-        new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2);
-    Bool& as_bool =
-        Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results));
-    if (as_bool.IsNull()) {
-      if (results->length() == unary_checks.NumberOfChecks() * 2) {
-        const bool can_deopt = TryExpandTestCidsResult(results, type);
-        TestCidsInstr* test_cids = new(Z) TestCidsInstr(
-            call->token_pos(),
-            negate ? Token::kISNOT : Token::kIS,
-            new(Z) Value(left),
-            *results,
-            can_deopt ? call->deopt_id() : Thread::kNoDeoptId);
-        // Remove type.
-        ReplaceCall(call, test_cids);
-        return;
-      }
-    } else {
-      // TODO(srdjan): Use TestCidsInstr also for this case.
-      // One result only.
-      AddReceiverCheck(call);
-      if (negate) {
-        as_bool = Bool::Get(!as_bool.value()).raw();
-      }
-      ConstantInstr* bool_const = flow_graph()->GetConstant(as_bool);
-      for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
-        PushArgumentInstr* push = call->PushArgumentAt(i);
-        push->ReplaceUsesWith(push->value()->definition());
-        push->RemoveFromGraph();
-      }
-      call->ReplaceUsesWith(bool_const);
-      ASSERT(current_iterator()->Current() == call);
-      current_iterator()->RemoveCurrentFromGraph();
-      return;
-    }
-  }
 
   if (TypeCheckAsClassEquality(type)) {
     LoadClassIdInstr* left_cid = new(Z) LoadClassIdInstr(new(Z) Value(left));
@@ -2214,6 +2182,31 @@
     return;
   }
 
+  const ICData& unary_checks =
+      ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
+  if ((unary_checks.NumberOfChecks() > 0) &&
+      (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) {
+    ZoneGrowableArray<intptr_t>* results =
+        new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2);
+    InstanceOfAsBool(unary_checks, type, results);
+    if (results->length() == unary_checks.NumberOfChecks() * 2) {
+      const bool can_deopt = TryExpandTestCidsResult(results, type);
+      if (can_deopt && !IsAllowedForInlining(call->deopt_id())) {
+        // Guard against repeated speculative inlining.
+        return;
+      }
+      TestCidsInstr* test_cids = new(Z) TestCidsInstr(
+          call->token_pos(),
+          negate ? Token::kISNOT : Token::kIS,
+          new(Z) Value(left),
+          *results,
+          can_deopt ? call->deopt_id() : Thread::kNoDeoptId);
+      // Remove type.
+      ReplaceCall(call, test_cids);
+      return;
+    }
+  }
+
   InstanceOfInstr* instance_of =
       new(Z) InstanceOfInstr(call->token_pos(),
                              new(Z) Value(left),
@@ -2228,11 +2221,6 @@
 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids).
 void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) {
   ASSERT(Token::IsTypeCastOperator(call->token_kind()));
-  // Guard against repeated speculative inlining.
-  if (!use_speculative_inlining_ ||
-      IsBlackListedForInlining(call->deopt_id())) {
-    return;
-  }
   Definition* left = call->ArgumentAt(0);
   Definition* type_args = call->ArgumentAt(1);
   const AbstractType& type =
@@ -2247,6 +2235,10 @@
     const Bool& as_bool = Bool::ZoneHandle(Z,
         InstanceOfAsBool(unary_checks, type, results));
     if (as_bool.raw() == Bool::True().raw()) {
+      // Guard against repeated speculative inlining.
+      if (!IsAllowedForInlining(call->deopt_id())) {
+        return;
+      }
       AddReceiverCheck(call);
       // Remove the original push arguments.
       for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
@@ -2272,11 +2264,12 @@
 }
 
 
-bool AotOptimizer::IsBlackListedForInlining(intptr_t call_deopt_id) {
+bool AotOptimizer::IsAllowedForInlining(intptr_t call_deopt_id) {
+  if (!use_speculative_inlining_) return false;
   for (intptr_t i = 0; i < inlining_black_list_->length(); ++i) {
-    if ((*inlining_black_list_)[i] == call_deopt_id) return true;
+    if ((*inlining_black_list_)[i] == call_deopt_id) return false;
   }
-  return false;
+  return true;
 }
 
 
@@ -2329,8 +2322,7 @@
     return;
   }
 
-  if (use_speculative_inlining_ &&
-      !IsBlackListedForInlining(instr->deopt_id()) &&
+  if (IsAllowedForInlining(instr->deopt_id()) &&
       (unary_checks.NumberOfChecks() > 0)) {
     if ((op_kind == Token::kINDEX) && TryReplaceWithIndexedOp(instr)) {
       return;
diff --git a/runtime/vm/aot_optimizer.h b/runtime/vm/aot_optimizer.h
index d608442..6902552 100644
--- a/runtime/vm/aot_optimizer.h
+++ b/runtime/vm/aot_optimizer.h
@@ -163,7 +163,7 @@
 
   const Function& function() const { return flow_graph_->function(); }
 
-  bool IsBlackListedForInlining(intptr_t deopt_id);
+  bool IsAllowedForInlining(intptr_t deopt_id);
 
   FlowGraph* flow_graph_;
 
diff --git a/runtime/vm/assembler_dbc_test.cc b/runtime/vm/assembler_dbc_test.cc
index 5baa5d6..9e4e2cd 100644
--- a/runtime/vm/assembler_dbc_test.cc
+++ b/runtime/vm/assembler_dbc_test.cc
@@ -119,6 +119,22 @@
 }
 
 
+ASSEMBLER_TEST_GENERATE(Nop, assembler) {
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ Nop();
+  __ Nop();
+  __ Nop();
+  __ Nop();
+  __ Nop();
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(Nop, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
 // Called from assembler_test.cc.
 // FP[-kParamEndSlotFromFp - 1]: growable array
 // FP[-kParamEndSlotFromFp - 2]: value
@@ -484,6 +500,413 @@
 }
 
 
+//  - Add, Sub, Mul, Div, Mod, Shl, Shr rA, rB, rC
+//
+//    Arithmetic operations on Smis. FP[rA] <- FP[rB] op FP[rC].
+//    If these instructions can trigger a deoptimization, the following
+//    instruction should be Deopt. If no deoptimization should be triggered,
+//    the immediately following instruction is skipped.
+ASSEMBLER_TEST_GENERATE(AddNoOverflow, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(20)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(22)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+  __ Add(2, 0, 1);
+  __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(AddNoOverflow, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(AddOverflow, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMaxValue)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(1)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+  __ Add(2, 0, 1);
+  __ LoadConstant(2, Smi::Handle(Smi::New(42)));
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(AddOverflow, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(SubNoOverflow, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(64)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(22)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+  __ Sub(2, 0, 1);
+  __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(SubNoOverflow, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(SubOverflow, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMinValue)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(1)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+  __ Sub(2, 0, 1);
+  __ LoadConstant(2, Smi::Handle(Smi::New(42)));
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(SubOverflow, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(MulNoOverflow, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-6)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(-7)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+  __ Mul(2, 0, 1);
+  __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(MulNoOverflow, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(MulOverflow, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMaxValue)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(-8)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+  __ Mul(2, 0, 1);
+  __ LoadConstant(2, Smi::Handle(Smi::New(42)));
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(MulOverflow, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(DivNoDeopt, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(27)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(3)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+  __ Div(2, 0, 1);
+  __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(DivNoDeopt, test) {
+  EXPECT_EQ(9, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(DivZero, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(3)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(0)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+  __ Div(2, 0, 1);
+  __ LoadConstant(2, Smi::Handle(Smi::New(42)));
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(DivZero, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(DivCornerCase, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMinValue)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+  __ Div(2, 0, 1);
+  __ LoadConstant(2, Smi::Handle(Smi::New(42)));
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(DivCornerCase, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(ModPosPos, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(4)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+  __ Mod(2, 0, 1);
+  __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(ModPosPos, test) {
+  EXPECT_EQ(2, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(ModNegPos, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-42)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(4)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+  __ Mod(2, 0, 1);
+  __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(ModNegPos, test) {
+  EXPECT_EQ(2, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(ModPosNeg, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(-4)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+  __ Mod(2, 0, 1);
+  __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(ModPosNeg, test) {
+  EXPECT_EQ(2, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(ModZero, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(3)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(0)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+  __ Mod(2, 0, 1);
+  __ LoadConstant(2, Smi::Handle(Smi::New(42)));
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(ModZero, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(ShlNoDeopt, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(21)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(1)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+  __ Shl(2, 0, 1);
+  __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(ShlNoDeopt, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(ShlOverflow, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMaxValue)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(1)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+  __ Shl(2, 0, 1);
+  __ LoadConstant(2, Smi::Handle(Smi::New(42)));
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(ShlOverflow, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(ShlNegShift, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(21)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+  __ Shl(2, 0, 1);
+  __ LoadConstant(2, Smi::Handle(Smi::New(42)));
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(ShlNegShift, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(ShrNoDeopt, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(84)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(1)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+  __ Shr(2, 0, 1);
+  __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(ShrNoDeopt, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(ShrNegShift, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(21)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+  __ Shr(2, 0, 1);
+  __ LoadConstant(2, Smi::Handle(Smi::New(42)));
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(ShrNegShift, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+//  - Neg rA , rD
+//
+//    FP[rA] <- -FP[rD]. Assumes FP[rD] is a Smi. If there is no overflow the
+//    immediately following instruction is skipped.
+ASSEMBLER_TEST_GENERATE(NegPos, assembler) {
+  __ Frame(2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+  __ Neg(1, 0);
+  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+  __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(NegPos, test) {
+  EXPECT_EQ(-42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(NegNeg, assembler) {
+  __ Frame(2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-42)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+  __ Neg(1, 0);
+  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+  __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(NegNeg, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(NegOverflow, assembler) {
+  __ Frame(2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMinValue)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+  __ Neg(1, 0);
+  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
+  __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(NegOverflow, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+//  - BitOr, BitAnd, BitXor rA, rB, rC
+//
+//    FP[rA] <- FP[rB] op FP[rC]
+ASSEMBLER_TEST_GENERATE(BitOr, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(0x2)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(0x28)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+  __ BitOr(2, 0, 1);
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(BitOr, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(BitAnd, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(0x2b)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(0x6a)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+  __ BitAnd(2, 0, 1);
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(BitAnd, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(BitXor, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(0x37)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(0x1d)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+  __ BitXor(2, 0, 1);
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(BitXor, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+//  - BitNot rA, rD
+//
+//    FP[rA] <- ~FP[rD]. As above, assumes FP[rD] is a Smi.
+ASSEMBLER_TEST_GENERATE(BitNot, assembler) {
+  __ Frame(2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(~42)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+  __ BitNot(1, 0);
+  __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(BitNot, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
 //  - IfNeStrictTOS; IfEqStrictTOS; IfNeStrictNumTOS; IfEqStrictNumTOS
 //
 //    Skips the next instruction unless the given condition holds. 'Num'
@@ -1166,6 +1589,52 @@
   EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
 }
 
+
+//  - CheckClassId rA, D
+//
+//    If the object at FP[rA]'s class id matches hthe class id in PP[D], then
+//    skip the following instruction.
+ASSEMBLER_TEST_GENERATE(CheckClassIdSmiPass, assembler) {
+  __ Frame(1);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ CheckClassId(0, __ AddConstant(Smi::Handle(Smi::New(kSmiCid))));
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(CheckClassIdSmiPass, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(CheckClassIdNonSmiPass, assembler) {
+  __ Frame(1);
+  __ LoadConstant(0, Bool::True());
+  __ CheckClassId(0, __ AddConstant(Smi::Handle(Smi::New(kBoolCid))));
+  __ LoadConstant(0, Bool::False());
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(CheckClassIdNonSmiPass, test) {
+  EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(CheckClassIdFail, assembler) {
+  __ Frame(1);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ CheckClassId(0, __ AddConstant(Smi::Handle(Smi::New(kBoolCid))));
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(CheckClassIdFail, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
 }  // namespace dart
 
 #endif  // defined(TARGET_ARCH_DBC)
diff --git a/runtime/vm/assert_test.cc b/runtime/vm/assert_test.cc
index 625f23b..dc935f1 100644
--- a/runtime/vm/assert_test.cc
+++ b/runtime/vm/assert_test.cc
@@ -46,3 +46,18 @@
   EXPECT_FLOAT_EQ(15.43, 15.44, 0.01);
   EXPECT_FLOAT_EQ(1.43, 1.43, 0.00);
 }
+
+
+UNIT_TEST_CASE(Fail0) {
+  FAIL("This test fails");
+}
+
+
+UNIT_TEST_CASE(Fail1) {
+  FAIL1("This test fails with one argument: %d", 4);
+}
+
+
+UNIT_TEST_CASE(Fail2) {
+  FAIL2("This test fails with two arguments: %d, %d", -100, 42);
+}
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 5d4e3cb..683834b 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -1297,7 +1297,7 @@
     DeoptimizeFunctionsOnStack();
   }
   if (do_reload) {
-    NOT_IN_PRODUCT(isolate->OnStackReload();)
+    NOT_IN_PRODUCT(isolate->ReloadSources();)
   }
   if (FLAG_support_debugger && do_stacktrace) {
     String& var_name = String::Handle();
diff --git a/runtime/vm/constant_propagator.cc b/runtime/vm/constant_propagator.cc
index 4409f3f..6b97f7d 100644
--- a/runtime/vm/constant_propagator.cc
+++ b/runtime/vm/constant_propagator.cc
@@ -1514,8 +1514,9 @@
 
           changed = true;
 
-          if (FLAG_trace_constant_propagation) {
-            OS::Print("Eliminated branch in B%" Pd " common target B%" Pd "\n",
+          if (FLAG_trace_constant_propagation &&
+              FlowGraphPrinter::ShouldPrint(graph_->function())) {
+            THR_Print("Eliminated branch in B%" Pd " common target B%" Pd "\n",
                       block->block_id(), join->block_id());
           }
         }
@@ -1533,7 +1534,8 @@
 
 
 void ConstantPropagator::Transform() {
-  if (FLAG_trace_constant_propagation) {
+  if (FLAG_trace_constant_propagation &&
+      FlowGraphPrinter::ShouldPrint(graph_->function())) {
     FlowGraphPrinter::PrintGraph("Before CP", graph_);
   }
 
@@ -1546,8 +1548,9 @@
        b.Advance()) {
     BlockEntryInstr* block = b.Current();
     if (!reachable_->Contains(block->preorder_number())) {
-      if (FLAG_trace_constant_propagation) {
-        OS::Print("Unreachable B%" Pd "\n", block->block_id());
+      if (FLAG_trace_constant_propagation &&
+          FlowGraphPrinter::ShouldPrint(graph_->function())) {
+        THR_Print("Unreachable B%" Pd "\n", block->block_id());
       }
       // Remove all uses in unreachable blocks.
       block->ClearAllInstructions();
@@ -1618,8 +1621,9 @@
           !defn->IsStoreIndexed() &&
           !defn->IsStoreInstanceField() &&
           !defn->IsStoreStaticField()) {
-        if (FLAG_trace_constant_propagation) {
-          OS::Print("Constant v%" Pd " = %s\n",
+        if (FLAG_trace_constant_propagation &&
+            FlowGraphPrinter::ShouldPrint(graph_->function())) {
+          THR_Print("Constant v%" Pd " = %s\n",
                     defn->ssa_temp_index(),
                     defn->constant_value().ToCString());
         }
@@ -1681,7 +1685,8 @@
   GrowableArray<BitVector*> dominance_frontier;
   graph_->ComputeDominators(&dominance_frontier);
 
-  if (FLAG_trace_constant_propagation) {
+  if (FLAG_trace_constant_propagation &&
+      FlowGraphPrinter::ShouldPrint(graph_->function())) {
     FlowGraphPrinter::PrintGraph("After CP", graph_);
   }
 }
diff --git a/runtime/vm/constants_dbc.h b/runtime/vm/constants_dbc.h
index 1518bfa..4f8aab9 100644
--- a/runtime/vm/constants_dbc.h
+++ b/runtime/vm/constants_dbc.h
@@ -83,6 +83,10 @@
 //
 //    Unreachable instruction.
 //
+//  - Nop
+//
+//    This instuction does nothing.
+//
 //  - Compile
 //
 //    Compile current function and start executing newly produced code
@@ -160,7 +164,29 @@
 //    then pops operands and pushes result on the stack and skips the next
 //    instruction (which implements a slow path fallback).
 //
-//  - StoreStaticTOS D
+//  - Add, Sub, Mul, Div, Mod, Shl, Shr rA, rB, rC
+//
+//    Arithmetic operations on Smis. FP[rA] <- FP[rB] op FP[rC].
+//    If these instructions can trigger a deoptimization, the following
+//    instruction should be Deopt. If no deoptimization should be triggered,
+//    the immediately following instruction is skipped. These instructions
+//    expect their operands to be Smis, but don't check that they are.
+//
+//  - Neg rA , rD
+//
+//    FP[rA] <- -FP[rD]. Assumes FP[rD] is a Smi. If there is no overflow the
+//    immediately following instruction is skipped.
+//
+//  - BitOr, BitAnd, BitXor rA, rB, rC
+//
+//    FP[rA] <- FP[rB] op FP[rC]. These instructions expect their operands to be
+//    Smis, but don't check that they are.
+//
+//  - BitNot rA, rD
+//
+//    FP[rA] <- ~FP[rD]. As above, assumes FP[rD] is a Smi.
+//
+//  - StoreStaticT`OS D
 //
 //    Stores TOS into the static field PP[D].
 //
@@ -327,6 +353,11 @@
 //
 //    If FP[rA] is a Smi, then skip the next instruction.
 //
+//  - CheckClassId rA, D
+//
+//    If the object at FP[rA]'s class id matches hthe class id in PP[D], then
+//    skip the following instruction.
+//
 //  - CheckStack
 //
 //    Compare SP against isolate stack limit and call StackOverflow handler if
@@ -389,6 +420,7 @@
 //
 #define BYTECODES_LIST(V)                              \
   V(Trap,                            0, ___, ___, ___) \
+  V(Nop,                             0, ___, ___, ___) \
   V(Compile,                         0, ___, ___, ___) \
   V(HotCheck,                      A_D, num, num, ___) \
   V(Intrinsic,                       A, num, ___, ___) \
@@ -422,6 +454,18 @@
   V(EqualTOS,                        0, ___, ___, ___) \
   V(LessThanTOS,                     0, ___, ___, ___) \
   V(GreaterThanTOS,                  0, ___, ___, ___) \
+  V(Add,                         A_B_C, reg, reg, reg) \
+  V(Sub,                         A_B_C, reg, reg, reg) \
+  V(Mul,                         A_B_C, reg, reg, reg) \
+  V(Div,                         A_B_C, reg, reg, reg) \
+  V(Mod,                         A_B_C, reg, reg, reg) \
+  V(Shl,                         A_B_C, reg, reg, reg) \
+  V(Shr,                         A_B_C, reg, reg, reg) \
+  V(Neg,                           A_D, reg, reg, ___) \
+  V(BitOr,                       A_B_C, reg, reg, reg) \
+  V(BitAnd,                      A_B_C, reg, reg, reg) \
+  V(BitXor,                      A_B_C, reg, reg, reg) \
+  V(BitNot,                        A_D, reg, reg, ___) \
   V(StoreStaticTOS,                  D, lit, ___, ___) \
   V(PushStatic,                      D, lit, ___, ___) \
   V(InitStaticTOS,                   0, ___, ___, ___) \
@@ -458,6 +502,7 @@
   V(AssertAssignable,                D, num, lit, ___) \
   V(AssertBoolean,                   A, num, ___, ___) \
   V(CheckSmi,                        A, reg, ___, ___) \
+  V(CheckClassId,                  A_D, reg, lit, ___) \
   V(CheckStack,                      0, ___, ___, ___) \
   V(DebugStep,                       0, ___, ___, ___) \
   V(DebugBreak,                      A, num, ___, ___) \
diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc
index 4778d7a..009e500 100644
--- a/runtime/vm/flow_graph_allocator.cc
+++ b/runtime/vm/flow_graph_allocator.cc
@@ -441,6 +441,10 @@
                                        intptr_t to) {
   if (loc.IsRegister()) {
     BlockRegisterLocation(loc, from, to, blocked_cpu_registers_, cpu_regs_);
+#if defined(TARGET_ARCH_DBC)
+    last_used_register_ = Utils::Maximum(last_used_register_,
+                                         loc.register_code());
+#endif
   } else if (loc.IsFpuRegister()) {
     BlockRegisterLocation(loc, from, to, blocked_fpu_registers_, fpu_regs_);
   } else {
@@ -2742,10 +2746,6 @@
       registers_[reg]->Add(range);
     }
   }
-
-#if defined(TARGET_ARCH_DBC)
-  last_used_register_ = -1;
-#endif
 }
 
 
@@ -3010,6 +3010,10 @@
 
   DiscoverLoops();
 
+#if defined(TARGET_ARCH_DBC)
+  last_used_register_ = -1;
+#endif
+
   BuildLiveRanges();
 
   if (FLAG_print_ssa_liveranges) {
@@ -3038,6 +3042,7 @@
   AllocateUnallocatedRanges();
 #if defined(TARGET_ARCH_DBC)
   const intptr_t last_used_cpu_register = last_used_register_;
+  last_used_register_ = -1;
 #endif
 
   cpu_spill_slot_count_ = spill_slots_.length();
diff --git a/runtime/vm/flow_graph_compiler_dbc.cc b/runtime/vm/flow_graph_compiler_dbc.cc
index eae97e2..81c639e8 100644
--- a/runtime/vm/flow_graph_compiler_dbc.cc
+++ b/runtime/vm/flow_graph_compiler_dbc.cc
@@ -233,14 +233,22 @@
   __ PushConstant(dst_type);
   __ PushConstant(dst_name);
   __ AssertAssignable(__ AddConstant(test_cache));
+  if (is_optimizing()) {
+    // Register allocator does not think that our first input (also used as
+    // output) needs to be kept alive across the call because that is how code
+    // is written on other platforms (where registers are always spilled across
+    // the call): inputs are consumed by operation and output is produced so
+    // neither are alive at the safepoint.
+    // We have to mark the slot alive manually to ensure that GC
+    // visits it.
+    locs->SetStackBit(locs->out(0).reg());
+  }
   RecordSafepoint(locs);
   AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id, token_pos);
   if (is_optimizing()) {
     // Assert assignable keeps the instance on the stack as the result,
     // all other arguments are popped.
-    // In optimized code we need to drop it because optimized code
-    // expects the result in the register and it is already there
-    // because locs()->in(0).reg() == locs()->out(0).reg().
+    ASSERT(locs->out(0).reg() == locs->in(0).reg());
     __ Drop1();
   }
 }
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index b51cfe8..bba04b4 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -863,7 +863,7 @@
           }
         }
 
-        if (FLAG_support_il_printer && FLAG_trace_inlining &&
+        if (FLAG_support_il_printer && trace_inlining() &&
             (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) {
           THR_Print("Callee graph for inlining %s\n",
                     function.ToFullyQualifiedCString());
diff --git a/runtime/vm/flow_graph_range_analysis.cc b/runtime/vm/flow_graph_range_analysis.cc
index 18eaa36..9b7eb8b 100644
--- a/runtime/vm/flow_graph_range_analysis.cc
+++ b/runtime/vm/flow_graph_range_analysis.cc
@@ -1569,7 +1569,8 @@
           target->PredecessorAt(0)->last_instruction()->AsBranch();
       if (target == branch->true_successor()) {
         // True unreachable.
-        if (FLAG_trace_constant_propagation) {
+        if (FLAG_trace_constant_propagation &&
+            FlowGraphPrinter::ShouldPrint(flow_graph_->function())) {
           THR_Print("Range analysis: True unreachable (B%" Pd ")\n",
                     branch->true_successor()->block_id());
         }
@@ -1577,7 +1578,8 @@
       } else {
         ASSERT(target == branch->false_successor());
         // False unreachable.
-        if (FLAG_trace_constant_propagation) {
+        if (FLAG_trace_constant_propagation &&
+            FlowGraphPrinter::ShouldPrint(flow_graph_->function())) {
           THR_Print("Range analysis: False unreachable (B%" Pd ")\n",
                     branch->false_successor()->block_id());
         }
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 1763877..85bae29 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -3045,26 +3045,38 @@
     return;
   }
   if (name.raw() == Symbols::Plus().raw()) {
-    __ AddTOS();
+    if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
+      __ AddTOS();
+    }
   } else if (name.raw() == Symbols::Minus().raw()) {
-    __ SubTOS();
+    if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
+      __ SubTOS();
+    }
   } else if (name.raw() == Symbols::EqualOperator().raw()) {
-    __ EqualTOS();
+    if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
+      __ EqualTOS();
+    }
   } else if (name.raw() == Symbols::LAngleBracket().raw()) {
-    __ LessThanTOS();
+    if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
+     __ LessThanTOS();
+    }
   } else if (name.raw() == Symbols::RAngleBracket().raw()) {
-    __ GreaterThanTOS();
+    if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
+      __ GreaterThanTOS();
+    }
   } else if (name.raw() == Symbols::BitAnd().raw()) {
-    __ BitAndTOS();
+    if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
+      __ BitAndTOS();
+    }
   } else if (name.raw() == Symbols::BitOr().raw()) {
-    __ BitOrTOS();
+    if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
+      __ BitOrTOS();
+    }
   } else if (name.raw() == Symbols::Star().raw()) {
-    __ MulTOS();
-  } else {
-    return;
+    if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
+      __ MulTOS();
+    }
   }
-  bool is_smi_two_args_op = call_ic_data->AddSmiSmiCheckForFastSmiStubs();
-  ASSERT(is_smi_two_args_op);
 }
 #endif
 
@@ -3298,9 +3310,6 @@
   // DBC does not use LocationSummaries in the same way as other architectures.
 #if !defined(TARGET_ARCH_DBC)
   ASSERT(locs()->in(0).reg() == locs()->out(0).reg());
-#else
-  ASSERT(!compiler->is_optimizing() ||
-         (locs()->in(0).reg() == locs()->out(0).reg()));
 #endif  // !defined(TARGET_ARCH_DBC)
 }
 
@@ -3312,7 +3321,11 @@
 
 
 void DeoptimizeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+#if !defined(TARGET_ARCH_DBC)
   __ Jump(compiler->AddDeoptStub(deopt_id(), deopt_reason_));
+#else
+  compiler->EmitDeopt(deopt_id(), deopt_reason_);
+#endif
 }
 
 
diff --git a/runtime/vm/intermediate_language_dbc.cc b/runtime/vm/intermediate_language_dbc.cc
index 0e1afc6..d28bbb2 100644
--- a/runtime/vm/intermediate_language_dbc.cc
+++ b/runtime/vm/intermediate_language_dbc.cc
@@ -29,15 +29,13 @@
 DECLARE_FLAG(int, optimization_counter_threshold);
 
 // List of instructions that are still unimplemented by DBC backend.
-#define FOR_EACH_UNIMPLEMENTED_INSTRUCTION(M) \
-  M(Stop)                                                                      \
+#define FOR_EACH_UNIMPLEMENTED_INSTRUCTION(M)                                  \
   M(IndirectGoto)                                                              \
   M(LoadCodeUnits)                                                             \
   M(InstanceOf)                                                                \
   M(LoadUntagged)                                                              \
   M(AllocateUninitializedContext)                                              \
   M(BinaryInt32Op)                                                             \
-  M(UnarySmiOp)                                                                \
   M(UnaryDoubleOp)                                                             \
   M(SmiToDouble)                                                               \
   M(Int32ToDouble)                                                             \
@@ -48,7 +46,6 @@
   M(DoubleToFloat)                                                             \
   M(FloatToDouble)                                                             \
   M(UnboxedConstant)                                                           \
-  M(CheckEitherNonSmi)                                                         \
   M(BinaryDoubleOp)                                                            \
   M(MathUnary)                                                                 \
   M(MathMinMax)                                                                \
@@ -108,9 +105,7 @@
   M(UnboxInteger32)                                                            \
   M(CheckedSmiOp)                                                              \
   M(CheckArrayBound)                                                           \
-  M(CheckClassId)                                                              \
   M(CheckClass)                                                                \
-  M(BinarySmiOp)                                                               \
   M(TestSmi)                                                                   \
   M(RelationalOp)                                                              \
   M(EqualityCompare)                                                           \
@@ -184,7 +179,9 @@
 DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(EqualityCompare)
 
 
-DEFINE_MAKE_LOCATION_SUMMARY(AssertAssignable, 2, Location::SameAsFirstInput());
+DEFINE_MAKE_LOCATION_SUMMARY(AssertAssignable, 2,
+                             Location::SameAsFirstInput(),
+                             LocationSummary::kCall);
 
 
 EMIT_NATIVE_CODE(AssertBoolean,
@@ -219,6 +216,11 @@
 }
 
 
+EMIT_NATIVE_CODE(Stop, 0) {
+  __ Stop(message());
+}
+
+
 EMIT_NATIVE_CODE(CheckStackOverflow,
                  0, Location::NoLocation(),
                  LocationSummary::kCall) {
@@ -913,6 +915,109 @@
                       licm_hoisted_ ? ICData::kHoisted : 0);
 }
 
+
+EMIT_NATIVE_CODE(CheckEitherNonSmi, 2) {
+  intptr_t left_cid = left()->Type()->ToCid();
+  intptr_t right_cid = right()->Type()->ToCid();
+  const Register left = locs()->in(0).reg();
+  const Register right = locs()->in(1).reg();
+  if (this->left()->definition() == this->right()->definition()) {
+    __ CheckSmi(left);
+  } else if (left_cid == kSmiCid) {
+    __ CheckSmi(right);
+  } else if (right_cid == kSmiCid) {
+    __ CheckSmi(left);
+  } else {
+    __ CheckSmi(left);
+    compiler->EmitDeopt(deopt_id(), ICData::kDeoptBinaryDoubleOp,
+                        licm_hoisted_ ? ICData::kHoisted : 0);
+    __ CheckSmi(right);
+  }
+  compiler->EmitDeopt(deopt_id(), ICData::kDeoptBinaryDoubleOp,
+                      licm_hoisted_ ? ICData::kHoisted : 0);
+}
+
+
+EMIT_NATIVE_CODE(CheckClassId, 1) {
+  intptr_t cid = __ AddConstant(Smi::Handle(Smi::New(cid_)));
+  __ CheckClassId(locs()->in(0).reg(), cid);
+  compiler->EmitDeopt(deopt_id(), ICData::kDeoptCheckClass);
+}
+
+
+EMIT_NATIVE_CODE(BinarySmiOp, 2, Location::RequiresRegister()) {
+  const Register left = locs()->in(0).reg();
+  const Register right = locs()->in(1).reg();
+  const Register out = locs()->out(0).reg();
+  const bool can_deopt = CanDeoptimize();
+  bool needs_nop = false;
+  switch (op_kind()) {
+    case Token::kADD:
+      __ Add(out, left, right);
+      needs_nop = true;
+      break;
+    case Token::kSUB:
+      __ Sub(out, left, right);
+      needs_nop = true;
+      break;
+    case Token::kMUL:
+      __ Mul(out, left, right);
+      needs_nop = true;
+      break;
+    case Token::kTRUNCDIV:
+      ASSERT(can_deopt);
+      __ Div(out, left, right);
+      break;
+    case Token::kBIT_AND:
+      ASSERT(!can_deopt);
+      __ BitAnd(out, left, right);
+      break;
+    case Token::kBIT_OR:
+      ASSERT(!can_deopt);
+      __ BitOr(out, left, right);
+      break;
+    case Token::kBIT_XOR:
+      ASSERT(!can_deopt);
+      __ BitXor(out, left, right);
+      break;
+    case Token::kMOD:
+      __ Mod(out, left, right);
+      needs_nop = true;
+      break;
+    case Token::kSHR:
+      __ Shr(out, left, right);
+      needs_nop = true;
+      break;
+    case Token::kSHL:
+      __ Shl(out, left, right);
+      needs_nop = true;
+      break;
+    default:
+      UNREACHABLE();
+  }
+  if (can_deopt) {
+    compiler->EmitDeopt(deopt_id(), ICData::kDeoptBinarySmiOp);
+  } else if (needs_nop) {
+    __ Nop();
+  }
+}
+
+
+EMIT_NATIVE_CODE(UnarySmiOp, 1, Location::RequiresRegister()) {
+  switch (op_kind()) {
+    case Token::kNEGATE: {
+      __ Neg(locs()->out(0).reg(), locs()->in(0).reg());
+      compiler->EmitDeopt(deopt_id(), ICData::kDeoptUnaryOp);
+      break;
+    }
+    case Token::kBIT_NOT:
+      __ BitNot(locs()->out(0).reg(), locs()->in(0).reg());
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 69578c9..5369226 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -813,6 +813,7 @@
       tag_table_(GrowableObjectArray::null()),
       deoptimized_code_array_(GrowableObjectArray::null()),
       sticky_error_(Error::null()),
+      sticky_reload_error_(Error::null()),
       background_compiler_(NULL),
       background_compiler_disabled_depth_(0),
       pending_service_extension_calls_(GrowableObjectArray::null()),
@@ -1066,11 +1067,6 @@
 }
 
 
-void Isolate::OnStackReload() {
-  ReloadSources();
-}
-
-
 void Isolate::ReloadSources(bool test_mode) {
   ASSERT(!IsReloading());
   has_attempted_reload_ = true;
@@ -1090,6 +1086,10 @@
         // context on the isolate so that it can be used by unit tests.
         return;
       }
+      if (reload_context_->has_error()) {
+        // Remember the reload error.
+        sticky_reload_error_ = reload_context_->error();
+      }
       if (!reload_context_->has_error()) {
         reload_context_->ReportSuccess();
       }
@@ -1752,6 +1752,9 @@
   visitor->VisitPointer(
         reinterpret_cast<RawObject**>(&sticky_error_));
 
+  visitor->VisitPointer(
+        reinterpret_cast<RawObject**>(&sticky_reload_error_));
+
   // Visit the pending service extension calls.
   visitor->VisitPointer(
       reinterpret_cast<RawObject**>(&pending_service_extension_calls_));
@@ -2005,6 +2008,11 @@
 }
 
 
+void Isolate::clear_sticky_reload_error() {
+  sticky_reload_error_ = Error::null();
+}
+
+
 void Isolate::set_pending_service_extension_calls(
       const GrowableObjectArray& value) {
   pending_service_extension_calls_ = value.raw();
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 5c219cc..701579c 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -255,7 +255,6 @@
   void DoneLoading();
   void DoneFinalizing();
 
-  void OnStackReload();
   void ReloadSources(bool test_mode = false);
 
   bool MakeRunnable();
@@ -532,6 +531,9 @@
   RawError* sticky_error() const { return sticky_error_; }
   void clear_sticky_error();
 
+  RawError* sticky_reload_error() const { return sticky_reload_error_; }
+  void clear_sticky_reload_error();
+
   bool compilation_allowed() const { return compilation_allowed_; }
   void set_compilation_allowed(bool allowed) {
     compilation_allowed_ = allowed;
@@ -751,6 +753,8 @@
 
   RawError* sticky_error_;
 
+  RawError* sticky_reload_error_;
+
   // Background compilation.
   BackgroundCompiler* background_compiler_;
   intptr_t background_compiler_disabled_depth_;
diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc
index 9b45046..aa8f188 100644
--- a/runtime/vm/isolate_reload_test.cc
+++ b/runtime/vm/isolate_reload_test.cc
@@ -228,6 +228,38 @@
 }
 
 
+TEST_CASE(IsolateReload_ClassFieldAdded2) {
+  const char* kScript =
+      "class Foo {\n"
+      "  var x;\n"
+      "  var y;\n"
+      "}\n"
+      "main() {\n"
+      "  new Foo();\n"
+      "  return 44;\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+
+  EXPECT_EQ(44, SimpleInvoke(lib, "main"));
+
+  const char* kReloadScript =
+      "class Foo {\n"
+      "  var x;\n"
+      "  var y;\n"
+      "  var z;\n"
+      "}\n"
+      "main() {\n"
+      "  new Foo();\n"
+      "  return 44;\n"
+      "}\n";
+
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_ERROR(lib, "Number of instance fields changed");
+}
+
+
 TEST_CASE(IsolateReload_ClassFieldRemoved) {
   const char* kScript =
       "class Foo {\n"
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index c367f2e..f1a0d87 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -146,6 +146,8 @@
       return "File system does not exist";
     case kFileDoesNotExist:
       return "File does not exist";
+    case kIsolateReloadFailed:
+      return "Isolate reload failed";
     default:
       return "Extension error";
   }
diff --git a/runtime/vm/json_stream.h b/runtime/vm/json_stream.h
index 1dec0db..eec69b0 100644
--- a/runtime/vm/json_stream.h
+++ b/runtime/vm/json_stream.h
@@ -59,6 +59,7 @@
   kFileSystemAlreadyExists   = 1001,
   kFileSystemDoesNotExist    = 1002,
   kFileDoesNotExist          = 1003,
+  kIsolateReloadFailed       = 1004,
 };
 
 // Expected that user_data is a JSONStream*.
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index ba5098a..f9c5ad9 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -444,13 +444,22 @@
     const Array& replacement_fields =
         Array::Handle(replacement.OffsetToFieldMap());
 
-    // Check that we have the same number of fields.
+    // Check that the size of the instance is the same.
     if (fields.Length() != replacement_fields.Length()) {
       IRC->ReportError(String::Handle(String::NewFormatted(
           "Number of instance fields changed in %s", ToCString())));
       return false;
     }
 
+    // Check that we have the same next field offset. This check is not
+    // redundant with the one above because the instance OffsetToFieldMap
+    // array length is based on the instance size (which may be aligned up).
+    if (next_field_offset() != replacement.next_field_offset()) {
+      IRC->ReportError(String::Handle(String::NewFormatted(
+          "Number of instance fields changed in %s", ToCString())));
+      return false;
+    }
+
     if (NumTypeArguments() != replacement.NumTypeArguments()) {
       IRC->ReportError(String::Handle(String::NewFormatted(
           "Number of type arguments changed in %s", ToCString())));
@@ -483,7 +492,8 @@
   } else if (is_prefinalized()) {
     if (!replacement.is_prefinalized()) {
       IRC->ReportError(String::Handle(String::NewFormatted(
-          "Original class ('%s') is prefinalized and replacement class ('%s')",
+          "Original class ('%s') is prefinalized and replacement class "
+          "('%s') is not ",
           ToCString(), replacement.ToCString())));
       return false;
     }
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index b8fa54b..4619602 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -2648,17 +2648,18 @@
 
 AstNode* Parser::ParseExternalInitializedField(const Field& field) {
   // Only use this function if the initialized field originates
-  // from a different class. We need to save and restore current
-  // class, library, and token stream (script).
+  // from a different class. We need to save and restore the
+  // library and token stream (script).
+  // The current_class remains unchanged, so that type arguments
+  // are resolved in the correct scope class.
   ASSERT(current_class().raw() != field.Origin());
-  const Class& saved_class = Class::Handle(Z, current_class().raw());
   const Library& saved_library = Library::Handle(Z, library().raw());
   const Script& saved_script = Script::Handle(Z, script().raw());
   const TokenPosition saved_token_pos = TokenPos();
 
-  set_current_class(Class::Handle(Z, field.Origin()));
-  set_library(Library::Handle(Z, current_class().library()));
-  SetScript(Script::Handle(Z, current_class().script()), field.token_pos());
+  const Class& origin_class = Class::Handle(Z, field.Origin());
+  set_library(Library::Handle(Z, origin_class.library()));
+  SetScript(Script::Handle(Z, origin_class.script()), field.token_pos());
 
   ASSERT(IsIdentifier());
   ConsumeToken();
@@ -2678,7 +2679,6 @@
       init_expr = new(Z) LiteralNode(field.token_pos(), expr_value);
     }
   }
-  set_current_class(saved_class);
   set_library(saved_library);
   SetScript(saved_script, saved_token_pos);
   return init_expr;
@@ -6062,6 +6062,9 @@
 void Parser::ParseLibraryPart() {
   const TokenPosition source_pos = TokenPos();
   ConsumeToken();  // Consume "part".
+  if (IsSymbol(Symbols::Of())) {
+    ReportError("part of declarations are not allowed in script files");
+  }
   CheckToken(Token::kSTRING, "url expected");
   AstNode* url_literal = ParseStringLiteral(false);
   ASSERT(url_literal->IsLiteralNode());
@@ -9175,28 +9178,6 @@
 }
 
 
-AstNode* Parser::MakeAssertCall(TokenPosition begin, TokenPosition end) {
-  ArgumentListNode* arguments = new(Z) ArgumentListNode(begin);
-  arguments->Add(new(Z) LiteralNode(begin,
-      Integer::ZoneHandle(Z, Integer::New(begin.value(), Heap::kOld))));
-  arguments->Add(new(Z) LiteralNode(end,
-      Integer::ZoneHandle(Z, Integer::New(end.value(), Heap::kOld))));
-  return MakeStaticCall(Symbols::AssertionError(),
-                        Library::PrivateCoreLibName(Symbols::ThrowNew()),
-                        arguments);
-}
-
-
-AstNode* Parser::HandleAssertCondition(AstNode* condition) {
-  const TokenPosition pos = condition->token_pos();
-  ArgumentListNode* arguments = new(Z) ArgumentListNode(pos);
-  arguments->Add(condition);
-  return MakeStaticCall(Symbols::AssertionError(),
-                        Library::PrivateCoreLibName(Symbols::HandleCondition()),
-                        arguments);
-}
-
-
 AstNode* Parser::ParseAssertStatement() {
   TRACE_PARSER("ParseAssertStatement");
   ConsumeToken();  // Consume assert keyword.
@@ -9210,14 +9191,16 @@
   AstNode* condition = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
   const TokenPosition condition_end = TokenPos();
   ExpectToken(Token::kRPAREN);
-  condition = HandleAssertCondition(condition);
-  condition = new(Z) UnaryOpNode(condition_pos, Token::kNOT, condition);
-  AstNode* assert_throw = MakeAssertCall(condition_pos, condition_end);
-  return new(Z) IfNode(
-      condition_pos,
-      condition,
-      NodeAsSequenceNode(condition_pos, assert_throw, NULL),
-      NULL);
+
+  ArgumentListNode* arguments = new(Z) ArgumentListNode(condition_pos);
+  arguments->Add(condition);
+  arguments->Add(new(Z) LiteralNode(condition_pos,
+      Integer::ZoneHandle(Z, Integer::New(condition_pos.value(), Heap::kOld))));
+  arguments->Add(new(Z) LiteralNode(condition_end,
+      Integer::ZoneHandle(Z, Integer::New(condition_end.value(), Heap::kOld))));
+  return MakeStaticCall(Symbols::AssertionError(),
+                        Library::PrivateCoreLibName(Symbols::CheckAssertion()),
+                        arguments);
 }
 
 
@@ -10256,8 +10239,13 @@
     // Rethrow of current exception.
     ConsumeToken();
     ExpectSemicolon();
-    // Check if it is ok to do a rethrow.
-    if ((try_stack_ == NULL) || !try_stack_->inside_catch()) {
+    // Check if it is ok to do a rethrow. Find the inntermost enclosing
+    // catch block.
+    TryStack* try_statement = try_stack_;
+    while ((try_statement != NULL) && !try_statement->inside_catch()) {
+      try_statement = try_statement->outer_try();
+    }
+    if (try_statement == NULL) {
       ReportError(statement_pos, "rethrow of an exception is not valid here");
     }
 
@@ -10265,7 +10253,7 @@
     // instead of :exception_var and :stack_trace_var.
     // These variables are bound in the block containing the try.
     // Look in the try scope directly.
-    LocalScope* scope = try_stack_->try_block()->scope->parent();
+    LocalScope* scope = try_statement->try_block()->scope->parent();
     ASSERT(scope != NULL);
     LocalVariable* excp_var;
     LocalVariable* trace_var;
@@ -13639,6 +13627,12 @@
   }
   ASSERT(!constructor.IsNull());
 
+  // It is a compile time error to instantiate a const instance of an
+  // abstract class. Factory methods are ok.
+  if (is_const && type_class.is_abstract() && !constructor.IsFactory()) {
+    ReportError(new_pos, "cannot instantiate abstract class");
+  }
+
   // It is ok to call a factory method of an abstract class, but it is
   // a dynamic error to instantiate an abstract class.
   if (type_class.is_abstract() && !constructor.IsFactory()) {
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index 31c6ec0..815f978 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -874,7 +874,6 @@
                           const String& func_name,
                           ArgumentListNode* arguments);
   String& Interpolate(const GrowableArray<AstNode*>& values);
-  AstNode* MakeAssertCall(TokenPosition begin, TokenPosition end);
   AstNode* ThrowTypeError(TokenPosition type_pos,
                           const AbstractType& type,
                           LibraryPrefix* prefix = NULL);
@@ -898,7 +897,6 @@
                                 const String* left_ident,
                                 TokenPosition left_pos,
                                 bool is_compound = false);
-  AstNode* HandleAssertCondition(AstNode* condition);
 
   ConstructorCallNode* CreateConstructorCallNode(
       TokenPosition token_pos,
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 8f6f624..286a5f9 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -2281,10 +2281,7 @@
                  kTwoByteStringCid == kStringCid + 2 &&
                  kExternalOneByteStringCid == kStringCid + 3 &&
                  kExternalTwoByteStringCid == kStringCid + 4);
-  return (index == kOneByteStringCid ||
-          index == kTwoByteStringCid ||
-          index == kExternalOneByteStringCid ||
-          index == kExternalTwoByteStringCid);
+  return (index == kTwoByteStringCid || index == kExternalTwoByteStringCid);
 }
 
 
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 087e47e..09da5f3 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -2484,19 +2484,24 @@
                    "This isolate is being reloaded.");
     return true;
   }
-  DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
-  ASSERT(isolate->CanReload());
-
-  if (stack->Length() > 0) {
-    // TODO(turnidge): We need to support this case.
+  if (!isolate->CanReload()) {
     js->PrintError(kFeatureDisabled,
-                   "Source can only be reloaded when stack is empty.");
+                   "This isolate cannot reload sources right now.");
     return true;
-  } else {
-    isolate->ReloadSources();
   }
 
-  PrintSuccess(js);
+  isolate->ReloadSources();
+
+  const Error& error = Error::Handle(isolate->sticky_reload_error());
+
+  if (error.IsNull()) {
+    PrintSuccess(js);
+  } else {
+    // Clear the sticky error.
+    isolate->clear_sticky_reload_error();
+    js->PrintError(kIsolateReloadFailed,
+                   "Isolate reload failed: %s", error.ToErrorCString());
+  }
   return true;
 }
 
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index 499f604..1938950 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -442,7 +442,7 @@
       : "r"(rhs), "r"(out)
       : "cc", "r12");
 #elif defined(HOST_ARCH_ARM64)
-  int64_t prod_lo;
+  int64_t prod_lo = 0;
   asm volatile(
       "mul %1, %2, %3\n"
       "smulh %2, %2, %3\n"
@@ -451,7 +451,7 @@
       "mov %0, #0;\n"
       "str %1, [%4, #0]\n"
       "1:"
-      : "+r"(res), "=r"(prod_lo), "+r"(lhs)
+      : "=r"(res), "+r"(prod_lo), "+r"(lhs)
       : "r"(rhs), "r"(out)
       : "cc");
 #else
@@ -477,6 +477,7 @@
 #define SMI_GT(lhs, rhs, pres) SMI_COND(>, lhs, rhs, pres)
 #define SMI_BITOR(lhs, rhs, pres) ((*(pres) = (lhs | rhs)), false)
 #define SMI_BITAND(lhs, rhs, pres) ((*(pres) = ((lhs) & (rhs))), false)
+#define SMI_BITXOR(lhs, rhs, pres) ((*(pres) = ((lhs) ^ (rhs))), false)
 
 
 void Simulator::CallRuntime(Thread* thread,
@@ -786,6 +787,28 @@
     }                                                                          \
   }
 
+// Skip the next instruction if there is no overflow.
+#define SMI_OP_CHECK(ResultT, Func)                                            \
+  {                                                                            \
+    const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);                   \
+    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]);                   \
+    ResultT* slot = reinterpret_cast<ResultT*>(&FP[rA]);                       \
+    if (LIKELY(!Func(lhs, rhs, slot))) {                                       \
+      /* Success. Skip the instruction that follows. */                        \
+      pc++;                                                                    \
+    }                                                                          \
+  }
+
+// Do not check for overflow.
+#define SMI_OP_NOCHECK(ResultT, Func)                                          \
+  {                                                                            \
+    const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);                   \
+    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]);                   \
+    ResultT* slot = reinterpret_cast<ResultT*>(&FP[rA]);                       \
+    Func(lhs, rhs, slot);                                                      \
+  }                                                                            \
+
+
 // Exception handling helper. Gets handler FP and PC from the Simulator where
 // they were stored by Simulator::Longjmp and proceeds to execute the handler.
 // Corner case: handler PC can be a fake marker that marks entry frame, which
@@ -1541,6 +1564,112 @@
     SMI_FASTPATH_TOS(RawObject*, SMI_GT);
     DISPATCH();
   }
+  {
+    BYTECODE(Add, A_B_C);
+    SMI_OP_CHECK(intptr_t, SignedAddWithOverflow);
+    DISPATCH();
+  }
+  {
+    BYTECODE(Sub, A_B_C);
+    SMI_OP_CHECK(intptr_t, SignedSubWithOverflow);
+    DISPATCH();
+  }
+  {
+    BYTECODE(Mul, A_B_C);
+    SMI_OP_CHECK(intptr_t, SMI_MUL);
+    DISPATCH();
+  }
+  {
+    BYTECODE(Neg, A_D);
+    const intptr_t value = reinterpret_cast<intptr_t>(FP[rD]);
+    intptr_t* out = reinterpret_cast<intptr_t*>(&FP[rA]);
+    if (LIKELY(!SignedSubWithOverflow(0, value, out))) {
+      pc++;
+    }
+    DISPATCH();
+  }
+  {
+    BYTECODE(BitOr, A_B_C);
+    SMI_OP_NOCHECK(intptr_t, SMI_BITOR);
+    DISPATCH();
+  }
+  {
+    BYTECODE(BitAnd, A_B_C);
+    SMI_OP_NOCHECK(intptr_t, SMI_BITAND);
+    DISPATCH();
+  }
+  {
+    BYTECODE(BitXor, A_B_C);
+    SMI_OP_NOCHECK(intptr_t, SMI_BITXOR);
+    DISPATCH();
+  }
+  {
+    BYTECODE(BitNot, A_D);
+    const intptr_t value = reinterpret_cast<intptr_t>(FP[rD]);
+    *reinterpret_cast<intptr_t*>(&FP[rA]) = ~value & (~kSmiTagMask);
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(Div, A_B_C);
+    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]);
+    if (rhs != 0) {
+      const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
+      const intptr_t res = (lhs >> kSmiTagSize) / (rhs >> kSmiTagSize);
+#if defined(ARCH_IS_64_BIT)
+      const intptr_t untaggable = 0x4000000000000000LL;
+#else
+      const intptr_t untaggable = 0x40000000L;
+#endif  // defined(ARCH_IS_64_BIT)
+      if (res != untaggable) {
+        *reinterpret_cast<intptr_t*>(&FP[rA]) = res << kSmiTagSize;
+        pc++;
+      }
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(Mod, A_B_C);
+    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]);
+    if (rhs != 0) {
+      const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
+      const intptr_t res =
+          ((lhs >> kSmiTagSize) % (rhs >> kSmiTagSize)) << kSmiTagSize;
+      *reinterpret_cast<intptr_t*>(&FP[rA]) =
+          (res < 0) ? ((rhs < 0) ? (res - rhs) : (res + rhs)) : res;
+      pc++;
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(Shl, A_B_C);
+    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]) >> kSmiTagSize;
+    if (rhs >= 0) {
+      const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
+      const intptr_t res = lhs << rhs;
+      if (lhs == (res >> rhs)) {
+        *reinterpret_cast<intptr_t*>(&FP[rA]) = res;
+        pc++;
+      }
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(Shr, A_B_C);
+    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]) >> kSmiTagSize;
+    if (rhs >= 0) {
+      const intptr_t shift_amount =
+          (rhs >= kBitsPerWord) ? (kBitsPerWord - 1) : rhs;
+      const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]) >> kSmiTagSize;
+      *reinterpret_cast<intptr_t*>(&FP[rA]) =
+          (lhs >> shift_amount) << kSmiTagSize;
+      pc++;
+    }
+    DISPATCH();
+  }
 
   // Return and return like instructions (Instrinsic).
   {
@@ -1735,8 +1864,8 @@
         SP[2] = args[3];  // name.
         SP[3] = args[2];  // type.
         Exit(thread, FP, SP + 4, pc);
-        NativeArguments args(thread, 3, SP + 1, SP - 3);
-        INVOKE_RUNTIME(DRT_BadTypeError, args);
+        NativeArguments native_args(thread, 3, SP + 1, SP - 3);
+        INVOKE_RUNTIME(DRT_BadTypeError, native_args);
         UNREACHABLE();
       }
 
@@ -1796,8 +1925,8 @@
       SP[4] = args[3];  // name
       SP[5] = cache;
       Exit(thread, FP, SP + 6, pc);
-      NativeArguments args(thread, 5, SP + 1, SP - 3);
-      INVOKE_RUNTIME(DRT_TypeCheck, args);
+      NativeArguments native_args(thread, 5, SP + 1, SP - 3);
+      INVOKE_RUNTIME(DRT_TypeCheck, native_args);
     }
 
   AssertAssignableOk:
@@ -1838,6 +1967,17 @@
   }
 
   {
+    BYTECODE(CheckClassId, A_D);
+    const RawSmi* actual_cid =
+        SimulatorHelpers::GetClassIdAsSmi(static_cast<RawObject*>(FP[rA]));
+    const RawSmi* desired_cid = RAW_CAST(Smi, LOAD_CONSTANT(rD));
+    if (actual_cid == desired_cid) {
+      pc++;
+    }
+    DISPATCH();
+  }
+
+  {
     BYTECODE(IfEqStrictTOS, 0);
     SP -= 2;
     if (SP[1] != SP[2]) {
@@ -2042,6 +2182,11 @@
   }
 
   {
+    BYTECODE(Nop, 0);
+    DISPATCH();
+  }
+
+  {
     BYTECODE(Trap, 0);
     UNIMPLEMENTED();
     DISPATCH();
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 96b4eba..547c2e5 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -71,7 +71,7 @@
   V(CyclicInitializationError, "CyclicInitializationError")                    \
   V(ThrowNew, "_throwNew")                                                     \
   V(ThrowNewIfNotLoaded, "_throwNewIfNotLoaded")                               \
-  V(HandleCondition, "_handleCondition")                                       \
+  V(CheckAssertion, "_checkAssertion")                                         \
   V(Symbol, "Symbol")                                                          \
   V(SymbolCtor, "Symbol.")                                                     \
   V(List, "List")                                                              \
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 6cfcda8..6f5cf9d 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -2456,8 +2456,9 @@
    *
    * V8 will share the underlying function code objects when the same string is
    * passed to "new Function".  Shared function code objects can lead to
-   * sub-optimal performance due to polymorhism, and can be prevented by
-   * ensuring the strings are different.
+   * sub-optimal performance due to polymorphism, and can be prevented by
+   * ensuring the strings are different, for example, by generating a local
+   * variable with a name dependent on [functionCounter].
    */
   static int functionCounter = 0;
 
@@ -2559,8 +2560,9 @@
         : isCsp
             ? JS('', 'function(a,b,c,d) {this.\$initialize(a,b,c,d)}')
             : JS('',
-                 'new Function("a,b,c,d", "this.\$initialize(a,b,c,d);" + #)',
-                 functionCounter++);
+                 'new Function("a,b,c,d" + #,'
+                 ' "this.\$initialize(a,b,c,d" + # + ")")',
+                 functionCounter, functionCounter++);
 
     // It is necessary to set the constructor property, otherwise it will be
     // "Object".
@@ -2722,12 +2724,14 @@
     }
 
     if (arity == 0) {
+      // Incorporate functionCounter into a local.
+      String selfName = 'self${functionCounter++}';
       return JS(
           '',
           '(new Function(#))()',
           'return function(){'
-            'return this.${BoundClosure.selfFieldName()}.$stubName();'
-            '${functionCounter++}'
+            'var $selfName = this.${BoundClosure.selfFieldName()};'
+            'return $selfName.$stubName();'
           '}');
     }
     assert (1 <= arity && arity < 27);
@@ -2735,12 +2739,12 @@
         'String',
         '"abcdefghijklmnopqrstuvwxyz".split("").splice(0,#).join(",")',
         arity);
+    arguments += '${functionCounter++}';
     return JS(
         '',
         '(new Function(#))()',
         'return function($arguments){'
           'return this.${BoundClosure.selfFieldName()}.$stubName($arguments);'
-          '${functionCounter++}'
         '}');
   }
 
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status
index 948470b..d531a08 100644
--- a/tests/co19/co19-co19.status
+++ b/tests/co19/co19-co19.status
@@ -28,6 +28,9 @@
 Language/Classes/same_name_type_variable_t04: Pass, MissingCompileTimeError, Fail # Issue 14513,25525
 Language/Classes/same_name_type_variable_t07: Pass, MissingCompileTimeError, Fail # Issue 14513,25525
 
+Language/Expressions/Instance_Creation/Const/abstract_class_t01: Pass, Fail # co19 issue 66
+Language/Expressions/Instance_Creation/Const/abstract_class_t03: Pass, Fail # co19 issue 66
+
 LibTest/math/acos_A01_t01: PASS, FAIL, OK  # Issue 26261
 LibTest/math/asin_A01_t01: PASS, FAIL, OK  # Issue 26261
 LibTest/math/atan_A01_t01: PASS, FAIL, OK  # Issue 26261
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index c4c30e7..4dbd24a 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -72,8 +72,6 @@
 Language/Expressions/Identifier_Reference/built_in_not_dynamic_t15: MissingCompileTimeError # Issue 26581
 Language/Expressions/Identifier_Reference/built_in_not_dynamic_t19: MissingCompileTimeError # Issue 25732
 Language/Expressions/Identifier_Reference/syntax_built_in_t01: fail # Issue 21154
-Language/Expressions/Instance_Creation/Const/abstract_class_t01: CompileTimeError # Please triage this failure
-Language/Expressions/Instance_Creation/Const/abstract_class_t03: CompileTimeError # Please triage this failure
 Language/Expressions/Instance_Creation/New/evaluation_t19: RuntimeError # Please triage this failure
 Language/Expressions/Instance_Creation/New/evaluation_t20: RuntimeError # Please triage this failure
 Language/Expressions/Maps/key_value_equals_operator_t02: CompileTimeError # Please triage this failure
@@ -632,6 +630,7 @@
 LayoutTests/fast/dom/cssTarget-crash_t01: Skip # Test reloads itself. Issue 18558.
 LayoutTests/fast/dom/empty-hash-and-search_t01: Skip # Test reloads itself. Issue 18558.
 LayoutTests/fast/dom/shadow/form-in-shadow_t01: Skip # Test reloads itself. Issue 18558.
+LayoutTests/fast/forms/date/date-interactive-validation-required_t01: Skip # Test reloads itself. Issue 18558.
 LayoutTests/fast/forms/datetimelocal/datetimelocal-interactive-validation-required_t01: Skip # Test reloads itself. Issue 18558.
 LayoutTests/fast/forms/form-submission-create-crash_t01: Skip # Test reloads itself. Issue 18558.
 LayoutTests/fast/forms/formmethod-attribute-button-html_t01: Skip # Test reloads itself. Issue 18558.
@@ -771,6 +770,8 @@
 LayoutTests/fast/animation/request-animation-frame-timestamps-advance_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/animation/request-animation-frame-timestamps_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/animation/request-animation-frame-within-callback_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/backgrounds/background-position-parsing-2_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/backgrounds/background-shorthand-with-backgroundSize-style_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/backgrounds/repeat/parsing-background-repeat_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/borders/border-width-percent_t01: RuntimeError # Issue 25155
 LayoutTests/fast/canvas/2d.fillText.gradient_t01: RuntimeError # Please triage this failure
@@ -868,7 +869,6 @@
 LayoutTests/fast/css/aspect-ratio-parsing-tests_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/auto-min-size_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/checked-pseudo-selector_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/computed-offset-with-zoom_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/content/content-none_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/content/content-normal_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/content/content-quotes-01_t01: RuntimeError # Issue https://github.com/dart-lang/co19/issues/46
@@ -888,11 +888,13 @@
 LayoutTests/fast/css/font-face-unicode-range-load_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/font-face-unicode-range-monospace_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/font-face-unicode-range-overlap-load_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/css/font-family-trailing-bracket-gunk_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/font-shorthand-from-longhands_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/fontfaceset-events_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/fontfaceset-loadingdone_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/getComputedStyle/computed-style-border-image_t01: RuntimeError # co19 issue 14
 LayoutTests/fast/css/getComputedStyle/computed-style-cross-fade_t01: RuntimeError # co19 issue 14
+LayoutTests/fast/css/getComputedStyle/font-family-fallback-reset_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/html-attr-case-sensitivity_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/id-or-class-before-stylesheet_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/implicit-attach-marking_t01: Skip # Times out. Please triage this failure
@@ -992,6 +994,7 @@
 LayoutTests/fast/dom/HTMLScriptElement/remove-in-beforeload_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLScriptElement/remove-source_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLScriptElement/script-set-src_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/dom/HTMLSelectElement/change-multiple-preserve-selection_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLTemplateElement/custom-element-wrapper-gc_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLTemplateElement/innerHTML_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLTemplateElement/ownerDocumentXHTML_t01: RuntimeError # Please triage this failure
@@ -1055,6 +1058,11 @@
 LayoutTests/fast/dom/shadow/event-path_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/host-context-pseudo-class-css-text_t01: RuntimeError # https://github.com/dart-lang/co19/issues/49
 LayoutTests/fast/dom/shadow/host-pseudo-class-css-text_t01: RuntimeError # https://github.com/dart-lang/co19/issues/49
+LayoutTests/fast/dom/shadow/olderShadowRoot_t01: RuntimeError # Issue 26729
+LayoutTests/fast/dom/shadow/shadowdom-for-input-spellcheck_t01: RuntimeError # Issue 26729
+LayoutTests/fast/dom/shadow/shadowdom-for-input-type-change_t01: RuntimeError # Issue 26729
+LayoutTests/fast/dom/shadow/shadowroot-clonenode_t01: RuntimeError # Issue 26729
+LayoutTests/fast/dom/shadow/shadowroot-host_t01: RuntimeError # Issue 26729
 LayoutTests/fast/dom/shadow/no-renderers-for-light-children_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/pseudoclass-update-checked-option_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/pseudoclass-update-disabled-optgroup_t01: RuntimeError # Please triage this failure
@@ -1238,7 +1246,6 @@
 LayoutTests/fast/table/col-width-span-expand_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/table/css-table-max-height_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/table/css-table-max-width_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/table/css-table-width-with-border-padding_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/table/hittest-tablecell-bottom-edge_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/table/hittest-tablecell-right-edge_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/table/hittest-tablecell-with-borders-bottom-edge_t01: RuntimeError # Please triage this failure
@@ -1291,7 +1298,6 @@
 LayoutTests/fast/url/segments-from-data-url_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/url/segments_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/url/standard-url_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/writing-mode/auto-sizing-orthogonal-flows_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/writing-mode/flipped-blocks-hit-test-overflow-scroll_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/writing-mode/flipped-blocks-hit-test-overflow_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/writing-mode/positionForPoint_t01: RuntimeError # Please triage this failure
@@ -1315,6 +1321,7 @@
 LayoutTests/fast/xpath/node-name-case-sensitivity_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/xpath/node-name-case-sensitivity_t02: RuntimeError # Please triage this failure
 LayoutTests/fast/xpath/position_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/xpath/py-dom-xpath/abbreviations_t01: RuntimeError # Issue 24398
 LayoutTests/fast/xpath/py-dom-xpath/axes_t01: RuntimeError # Dartium JSInterop failure
 LayoutTests/fast/xpath/py-dom-xpath/data_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/xpath/py-dom-xpath/expressions_t01: RuntimeError # Please triage this failure
@@ -1512,7 +1519,6 @@
 WebPlatformTest/html/semantics/scripting-1/the-script-element/async_t11: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/scripting-1/the-script-element/script-text_t02: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/selectors/pseudo-classes/checked_t01: RuntimeError # Please triage this failure
-WebPlatformTest/html/semantics/selectors/pseudo-classes/default_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/selectors/pseudo-classes/dir_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/selectors/pseudo-classes/disabled_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/selectors/pseudo-classes/enabled_t01: RuntimeError # Please triage this failure
@@ -1564,11 +1570,12 @@
 WebPlatformTest/shadow-dom/events/retargeting-focus-events/test-001_t05: Skip # Times out. Please triage this failure
 WebPlatformTest/shadow-dom/events/retargeting-focus-events/test-001_t06: Skip # Times out. Please triage this failure
 WebPlatformTest/shadow-dom/events/retargeting-focus-events/test-002_t01: Pass, RuntimeError, Timeout # Please triage this failure
-WebPlatformTest/shadow-dom/events/retargeting-focus-events/test-003_t01: Pass, RuntimeError # Please triage this failure
+WebPlatformTest/shadow-dom/events/retargeting-focus-events/test-003_t01: Skip # Times out. Please triage this failure
 WebPlatformTest/shadow-dom/events/retargeting-relatedtarget/test-003_t01: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/html-elements-and-their-shadow-trees/test-001_t01: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/html-elements-and-their-shadow-trees/test-002_t01: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/html-elements-and-their-shadow-trees/test-003_t01: RuntimeError # Please triage this failure
+WebPlatformTest/shadow-dom/html-elements-and-their-shadow-trees/test-004_t01: RuntimeError # Issue 26729
 WebPlatformTest/shadow-dom/shadow-trees/custom-pseudo-elements/test-001_t01: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/shadow-trees/distributed-pseudo-element/test-001_t01: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/shadow-trees/distributed-pseudo-element/test-002_t01: RuntimeError # Please triage this failure
@@ -1657,6 +1664,7 @@
 Language/Expressions/Function_Invocation/async_invokation_t04: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/canvas-test_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/canvas/webgl/draw-webgl-to-canvas-2d_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/oes-vertex-array-object_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLOutputElement/htmloutputelement_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/MutationObserver/observe-attributes_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/multicol/newmulticol/balance_t04: RuntimeError # Please triage this failure
@@ -1768,7 +1776,6 @@
 LayoutTests/fast/canvas/webgl/webgl-texture-binding-preserved_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/webgl-unprefixed-context-id_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/webgl-viewport-parameters-preserved_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/Element/getBoundingClientRect-getClientRects-relative-to-viewport_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/newmulticol/balance_t04: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/vertical-rl/image-inside-nested-blocks-with-border_t01: RuntimeError # co19 issue #65
 LayoutTests/fast/shapes/shape-outside-floats/shape-outside-floats-inset-rounded-different-writing-modes-left_t01: RuntimeError # Please triage this failure
@@ -1781,13 +1788,8 @@
 Language/Expressions/Bitwise_Expressions/method_invocation_super_t01: Pass, Slow # Issue 25940
 Language/Classes/Constructors/Generative_Constructors/execution_of_an_initializer_t04: Pass, Slow # Issue 25940
 
-[ $compiler == dart2js && $runtime == chrome && $system != linux ]
-LayoutTests/fast/multicol/hit-test-gap-between-pages-flipped_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/xpath/py-dom-xpath/abbreviations_t01: RuntimeError # Issue 24398
-
 [ $compiler == dart2js && $runtime == chrome && $system == linux]
 LayoutTests/fast/text/international/combining-marks-position_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/xpath/py-dom-xpath/abbreviations_t01: RuntimeError # Dartium JSInterop failure
 
 [ $compiler == dart2js && $runtime == ff ]
 Language/Expressions/Postfix_Expressions/property_decrement_t02: Skip # Times out. Please triage this failure
@@ -1871,6 +1873,7 @@
 LayoutTests/fast/canvas/webgl/context-lost_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/oes-vertex-array-object_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/renderer-and-vendor-strings_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-array-buffer-view_t01: Skip # Times out.
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgb565_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgba4444_t01: RuntimeError # Please triage this failure
@@ -1954,7 +1957,6 @@
 LayoutTests/fast/css/box-sizing-backwards-compat-prefix_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/checked-pseudo-selector_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/child-selector-implicit-tbody_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/computed-offset-with-zoom_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/content/content-none_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/content/content-normal_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/content/content-quotes-01_t01: RuntimeError # co19 issue 61
@@ -2298,6 +2300,7 @@
 LayoutTests/fast/dom/horizontal-scrollbar-in-rtl_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/horizontal-scrollbar-when-dir-change_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLDialogElement/dialog-return-value_t01: RuntimeError # Dartium JSInterop failure
+LayoutTests/fast/dom/icon-size-property_t01: RuntimeError # Issue 26714
 LayoutTests/fast/dom/importNode-unsupported-node-type_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/insert-span-into-long-text-bug-28245_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/insertBefore-refChild-crash_t01: RuntimeError # Please triage this failure
@@ -2515,7 +2518,6 @@
 LayoutTests/fast/forms/date/ValidityState-stepMismatch-date_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/ValidityState-typeMismatch-date_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/date-input-type_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/forms/date/date-interactive-validation-required_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/date-pseudo-classes_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/input-date-validation-message_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/input-valueasdate-date_t01: RuntimeError # Please triage this failure
@@ -3182,106 +3184,19 @@
 Language/Classes/Constructors/Factories/return_type_t03: Pass, Slow # Issue 25940
 Language/Classes/Constructors/Factories/return_wrong_type_t02: Pass, Slow # Issue 25940
 Language/Classes/Constructors/Factories/return_type_t05: Pass, Slow # Issue 25940
-LayoutTests/fast/canvas/webgl/array-bounds-clamping_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/attrib-location-length-limits_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/bad-arguments-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/buffer-bind-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/buffer-data-array-buffer_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/canvas-2d-webgl-texture_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/canvas-resize-crash_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/canvas-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/canvas-zero-size_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/css-webkit-canvas_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/compressed-tex-image_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/copy-tex-image-and-sub-image-2d_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/draw-arrays-out-of-bounds_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/draw-elements-out-of-bounds_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/draw-webgl-to-canvas-2d_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/drawingbuffer-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/error-reporting_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/framebuffer-bindings-unaffected-on-resize_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/framebuffer-object-attachment_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/framebuffer-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/functions-returning-strings_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/get-active-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-bind-attrib-location-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-enable-enum-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-enum-tests_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-get-calls_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-getshadersource_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-getstring_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-object-get-calls_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-pixelstorei_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-teximage_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-uniformmatrix4fv_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-vertex-attrib-zero-issues_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-vertex-attrib_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-vertexattribpointer_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/glsl-conformance_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/incorrect-context-object-behaviour_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/index-validation-copies-indices_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/index-validation-crash-with-buffer-sub-data_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/index-validation-verifies-too-many-indices_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/index-validation-with-resized-buffer_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/index-validation_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/invalid-UTF-16_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/invalid-passed-params_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/is-object_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/null-object-behaviour_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/null-uniform-location_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/object-deletion-behaviour_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/oes-element-index-uint_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/point-size_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/premultiplyalpha-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/program-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/read-pixels-pack-alignment_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/read-pixels-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/renderbuffer-initialization_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/shader-precision-format_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-array-buffer-view_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-canvas-rgb565_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-canvas-rgba4444_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-canvas-rgba5551_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-canvas_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data-rgb565_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data-rgba4444_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data-rgba5551_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgb565_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgba4444_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgba5551_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-uniform-binding-bugs_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-webgl_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-sub-image-2d_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-sub-image-cube-maps_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texImage2DImageDataTest_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texImageTest_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texture-active-bind_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texture-bindings-uneffected-on-resize_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texture-complete_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texture-color-profile_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texture-npot_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/triangle_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/uniform-location-length-limits_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/viewport-unchanged-upon-resize_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/webgl-composite-modes-repaint_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/webgl-composite-modes_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/webgl-exceptions_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/webgl-layer-update_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/webgl-specific_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/webgl-texture-binding-preserved_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/webgl-unprefixed-context-id_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/webgl-viewport-parameters-preserved_t01: RuntimeError # Please triage this failure
 
 [ $compiler == dart2js && $runtime == ff && $system != windows ]
 LayoutTests/fast/xpath/4XPath/Core/test_parser_t01: RuntimeError # Dartium JSInterop failure
 LayoutTests/fast/xpath/py-dom-xpath/abbreviations_t01: RuntimeError # Dartium JSInterop failure
 
 [ $compiler == dart2js && $runtime == ff && $system == linux]
+LayoutTests/fast/canvas/webgl/*: Timeout, Pass # Issue 26725
 LayoutTests/fast/canvas/canvas-composite-text-alpha_t01: RuntimeError # co19 issue 16
 LayoutTests/fast/text/whitespace/nowrap-line-break-after-white-space_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/oes-element-index-uint_t01: Skip # Times out always
+LayoutTests/fast/canvas/webgl/texture-complete_t01: Skip # Times out sometimes
+LayoutTests/fast/canvas/webgl/texture-npot_t01: Skip # Times out sometimes
+LayoutTests/fast/dom/HTMLOutputElement/htmloutputelement_t01: RuntimeError # Issue 26714
 
 [ $compiler == dart2js && $runtime == safari ]
 Language/Statements/Yield_and_Yield_Each/Yield/execution_async_t01: RuntimeError # Issue 26615
@@ -3820,7 +3735,6 @@
 LayoutTests/fast/forms/date/ValidityState-stepMismatch-date_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/ValidityState-typeMismatch-date_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/date-input-type_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/forms/date/date-interactive-validation-required_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/date-pseudo-classes_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/date-setrangetext_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/input-date-validation-message_t01: RuntimeError # Please triage this failure
@@ -3875,7 +3789,6 @@
 LayoutTests/fast/inline/positioned-element-padding-contributes-width_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/innerHTML/innerHTML-svg-write_t01: RuntimeError # Issue 25941
 LayoutTests/fast/innerHTML/javascript-url_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/layers/normal-flow-hit-test_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/loader/about-blank-hash-change_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/loader/about-blank-hash-kept_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/loader/hashchange-event-properties_t01: RuntimeError # Please triage this failure
@@ -3952,7 +3865,6 @@
 LayoutTests/fast/storage/disallowed-storage_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/storage/storage-disallowed-in-data-url_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/sub-pixel/cssom-subpixel-precision_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/sub-pixel/float-containing-block-with-margin_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/sub-pixel/shadows-computed-style_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/svg/tabindex-focus_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/svg/whitespace-angle_t01: RuntimeError # Please triage this failure
@@ -3965,7 +3877,6 @@
 LayoutTests/fast/table/col-width-span-expand_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/table/css-table-max-height_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/table/css-table-max-width_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/table/css-table-width-with-border-padding_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/table/fixed-table-layout-width-change_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/table/hittest-tablecell-bottom-edge_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/table/hittest-tablecell-right-edge_t01: RuntimeError # Please triage this failure
@@ -4036,7 +3947,6 @@
 LayoutTests/fast/url/segments-from-data-url_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/url/segments_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/url/standard-url_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/writing-mode/auto-sizing-orthogonal-flows_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/writing-mode/positionForPoint_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/writing-mode/table-hit-test_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/writing-mode/vertical-font-vmtx-units-per-em_t01: RuntimeError # Please triage this failure
@@ -4433,15 +4343,10 @@
 
 LayoutTests/fast/canvas/webgl/context-lost_t01: Skip
 
-LayoutTests/fast/canvas/canvas-strokePath-gradient-shadow_t01: RuntimeError # Fails 10 out of 10.
-LayoutTests/fast/canvas/canvas-strokeRect-gradient-shadow_t01: RuntimeError # Fails 10 out of 10.
-LayoutTests/fast/css/css-selector-text_t01: RuntimeError # Fails 10 out of 10.
-LayoutTests/fast/css/ex-unit-with-no-x-height_t01: RuntimeError # Fails 10 out of 10.
 LayoutTests/fast/css/font-property-priority_t01: RuntimeError # Fails 10 out of 10.
 LayoutTests/fast/css/inherited-properties-rare-text_t01: RuntimeError # Fails 10 out of 10.
 LayoutTests/fast/css/invalid-not-with-simple-selector-sequence_t01: RuntimeError # Fails 10 out of 10.
 LayoutTests/fast/css/parsing-font-variant-ligatures_t01: RuntimeError # Fails 10 out of 10.
-LayoutTests/fast/css/pseudo-valid-unapplied_t01: RuntimeError # Fails 10 out of 10.
 LayoutTests/fast/dom/HTMLLinkElement/resolve-url-on-insertion_t01: RuntimeError # Fails 10 out of 10.
 LayoutTests/fast/dom/css-selectorText_t01: RuntimeError # Fails 10 out of 10.
 LayoutTests/fast/forms/datalist/datalist-child-validation_t01: RuntimeError # Fails 10 out of 10.
@@ -5131,7 +5036,6 @@
 LayoutTests/fast/forms/datalist/input-list_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-change-layout-by-value_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-onblur-setvalue-onfocusremoved_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/forms/date/date-interactive-validation-required_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/input-date-validation-message_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/input-valueasdate-date_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/input-valueasnumber-date_t01: RuntimeError # Please triage this failure
@@ -6164,7 +6068,7 @@
 LayoutTests/fast/css/link-alternate-stylesheet-3_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/link-alternate-stylesheet-4_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/link-alternate-stylesheet-5_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/link-disabled-attr-parser_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/link-disabled-attr-parser_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/list-item-text-align_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/margin-start-end_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/max-device-aspect-ratio_t01: Pass, RuntimeError # Please triage this failure
@@ -6798,7 +6702,6 @@
 LayoutTests/fast/forms/date/ValidityState-stepMismatch-date_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/ValidityState-typeMismatch-date_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/date-input-type_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/forms/date/date-interactive-validation-required_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/date-pseudo-classes_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/input-date-validation-message_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/input-valueasdate-date_t01: RuntimeError # Please triage this failure
@@ -8074,7 +7977,7 @@
 LayoutTests/fast/css/dynamic-class-backdrop-pseudo_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/dynamic-class-pseudo-elements_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/first-child-display-change-inverse_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/font-face-cache-bug_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/font-face-cache-bug_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/font-face-insert-link_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/font-face-multiple-ranges-for-unicode-range_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/font-face-unicode-range-load_t01: RuntimeError # Please triage this failure
@@ -8580,7 +8483,7 @@
 LayoutTests/fast/dom/shadow/remove-styles-in-shadow-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/shadow-aware-shadow-root_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/shadow-content-crash_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/shadow/shadow-disable_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/shadow/shadow-disable_t01: Skip # Issue 26737. Makes next test time out.
 LayoutTests/fast/dom/shadow/shadow-element-inactive_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/dom/shadow/shadow-element_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/shadow-hierarchy-exception_t01: RuntimeError # Please triage this failure
@@ -8749,7 +8652,6 @@
 LayoutTests/fast/forms/date/ValidityState-stepMismatch-date_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/ValidityState-typeMismatch-date_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/date-input-type_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/forms/date/date-interactive-validation-required_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/date-pseudo-classes_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/input-date-validation-message_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/date/input-valueasdate-date_t01: RuntimeError # Please triage this failure
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 5a12788..b5bdadc 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -54,7 +54,7 @@
 [ ($runtime == vm || $runtime == dart_precompiled || $runtime == dart_app) && $system == windows ]
 Language/Expressions/Function_Invocation/async_invokation_t04: Pass, RuntimeError # co19 issue 54
 
-[ ($runtime == vm || $runtime == dart_precompiled || $runtime == dart_app) && ($arch != x64 && $arch != simarm64 && $arch != arm64) ]
+[ ($runtime == vm || $runtime == dart_precompiled || $runtime == dart_app) && ($arch != x64 && $arch != simarm64 && $arch != arm64 && $arch != simdbc && $arch != simdbc64) ]
 LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
 
 [ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && ($arch == mips || $arch == arm64) ]
@@ -64,7 +64,7 @@
 LibTest/collection/ListMixin/ListMixin_class_A01_t02: Skip # co19 issue 673
 LibTest/collection/ListBase/ListBase_class_A01_t02: Skip # co19 issue 673
 
-[ ($runtime == vm || $runtime == dart_precompiled || $runtime == dart_app) && ($arch == simarm || $arch == simarmv6 || $arch == simarmv5te || $arch == simmips || $arch == simarm64) ]
+[ ($runtime == vm || $runtime == dart_precompiled || $runtime == dart_app) && ($arch == simarm || $arch == simarmv6 || $arch == simarmv5te || $arch == simmips || $arch == simarm64 || $arch == simdbc || $arch == simdbc64) ]
 LibTest/core/Uri/Uri_A06_t03: Skip  # Timeout
 LibTest/collection/ListMixin/ListMixin_class_A01_t01: Skip  # Timeout
 LibTest/collection/ListBase/ListBase_class_A01_t01: Skip  # Timeout
diff --git a/tests/compiler/dart2js/mirrors_used_test.dart b/tests/compiler/dart2js/mirrors_used_test.dart
index dffab8a..fc08b6b 100644
--- a/tests/compiler/dart2js/mirrors_used_test.dart
+++ b/tests/compiler/dart2js/mirrors_used_test.dart
@@ -127,18 +127,22 @@
       });
     }
 
-    // There should at least be one metadata constant:
-    // 1. The constructed constant for 'MirrorsUsed'.
-    Expect.isTrue(backend.metadataConstants.length >= 1);
-
+    int metadataCount = 0;
     Set<ConstantValue> compiledConstants = backend.constants.compiledConstants;
     // Make sure that most of the metadata constants aren't included in the
     // generated code.
-    for (var dependency in backend.metadataConstants) {
-      ConstantValue constant = dependency.constant;
+    backend.processMetadata(
+        compiler.enqueuer.resolution.processedElements, (metadata) {
+      ConstantValue constant =
+          backend.constants.getConstantValueForMetadata(metadata);
       Expect.isFalse(compiledConstants.contains(constant),
                      constant.toStructuredText());
-    }
+      metadataCount++;
+    });
+
+    // There should at least be one metadata constant:
+    // 1. The constructed constant for 'MirrorsUsed'.
+    Expect.isTrue(metadataCount >= 1);
 
     // The type literal 'Foo' is both used as metadata, and as a plain value in
     // the program. Make sure that it isn't duplicated.
diff --git a/tests/compiler/dart2js/serialization/compilation_test.dart b/tests/compiler/dart2js/serialization/compilation_test.dart
index b770f51..9889bf4 100644
--- a/tests/compiler/dart2js/serialization/compilation_test.dart
+++ b/tests/compiler/dart2js/serialization/compilation_test.dart
@@ -38,10 +38,6 @@
      int index,
      Test test,
      bool verbose: false}) async {
-  if (test != null && test.name == 'Disable tree shaking through reflection') {
-    // TODO(johnniwinther): Support serialization of native element data.
-    return;
-  }
   String testDescription = test != null ? test.name : '${entryPoint}';
   String id = index != null ? '$index: ' : '';
   print('------------------------------------------------------------------');
diff --git a/tests/compiler/dart2js/serialization/equivalence_test.dart b/tests/compiler/dart2js/serialization/equivalence_test.dart
index bd903da..e6ae2d4 100644
--- a/tests/compiler/dart2js/serialization/equivalence_test.dart
+++ b/tests/compiler/dart2js/serialization/equivalence_test.dart
@@ -248,6 +248,16 @@
                   list1, list2, checkElementProperties);
 }
 
+/// Check the equivalence of the two metadata annotations, [metadata1] and
+/// [metadata2].
+///
+/// Uses [object1], [object2] and [property] to provide context for failures.
+checkMetadata(Object object1, Object object2, String property,
+    MetadataAnnotation metadata1, MetadataAnnotation metadata2) {
+  check(object1, object2, property,
+      metadata1, metadata2, areMetadataAnnotationsEquivalent);
+}
+
 /// Visitor that checks for equivalence of [Element] properties.
 class ElementPropertyEquivalence extends BaseElementVisitor<dynamic, Element> {
   const ElementPropertyEquivalence();
@@ -277,6 +287,18 @@
         element1.isClassMember, element2.isClassMember);
     check(element1, element2, 'isInstanceMember',
         element1.isInstanceMember, element2.isInstanceMember);
+    List<MetadataAnnotation> metadata1 = <MetadataAnnotation>[];
+    metadata1.addAll(element1.metadata);
+    if (element1.isPatched) {
+      metadata1.addAll(element1.implementation.metadata);
+    }
+    List<MetadataAnnotation> metadata2 = <MetadataAnnotation>[];
+    metadata2.addAll(element2.metadata);
+    if (element2.isPatched) {
+      metadata2.addAll(element2.implementation.metadata);
+    }
+    checkListEquivalence(element1, element2, 'metadata',
+        metadata1, metadata2, checkMetadata);
   }
 
   @override
@@ -382,7 +404,7 @@
           throw message;
         }
       }
-      currentCheck = new Check(currentCheck, element1, element1,
+      currentCheck = new Check(currentCheck, element1, element2,
           'member:$name', member1, member2);
       visit(member1, member2);
       currentCheck = currentCheck.parent;
@@ -430,6 +452,10 @@
         element1.isAbstract, element2.isAbstract);
     check(element1, element2, 'isUnnamedMixinApplication',
         element1.isUnnamedMixinApplication, element2.isUnnamedMixinApplication);
+    check(element1, element2, 'isProxy',
+        element1.isProxy, element2.isProxy);
+    check(element1, element2, 'isInjected',
+        element1.isInjected, element2.isInjected);
     check(element1, element2, 'isEnumClass',
         element1.isEnumClass, element2.isEnumClass);
     if (element1.isEnumClass) {
@@ -515,6 +541,8 @@
           element1.isStatic, element2.isStatic);
     check(element1, element2, 'isInstanceMember',
           element1.isInstanceMember, element2.isInstanceMember);
+    check(element1, element2, 'isInjected',
+        element1.isInjected, element2.isInjected);
 
     checkElementIdentities(
         element1, element2, 'library',
@@ -548,6 +576,8 @@
         element1, element2, 'asyncMarker',
         element1.asyncMarker,
         element2.asyncMarker);
+    check(element1, element2, 'isInjected',
+        element1.isInjected, element2.isInjected);
 
     checkElementIdentities(
         element1, element2, 'library',
@@ -652,6 +682,8 @@
         element2.immediateRedirectionTarget);
     checkElementIdentities(element1, element2, 'redirectionDeferredPrefix',
         element1.redirectionDeferredPrefix, element2.redirectionDeferredPrefix);
+    check(element1, element2, 'isInjected',
+        element1.isInjected, element2.isInjected);
   }
 
   @override
diff --git a/tests/compiler/dart2js/serialization/helper.dart b/tests/compiler/dart2js/serialization/helper.dart
index 3f2b429..e70b2ac 100644
--- a/tests/compiler/dart2js/serialization/helper.dart
+++ b/tests/compiler/dart2js/serialization/helper.dart
@@ -127,25 +127,39 @@
       print('Loading data from $file');
       serializedData = new SerializedData(uri, file.readAsStringSync());
     }
+  } else {
+    SerializationResult result = await serialize(Uris.dart_core, uri);
+    serializedData = result.serializedData;
   }
-  if (serializedData == null) {
-    Compiler compiler = compilerFor(
-        options: [Flags.analyzeAll]);
-    compiler.serialization.supportSerialization = true;
-    await compiler.run(Uris.dart_core);
-    BufferedEventSink sink = new BufferedEventSink();
-    compiler.serialization.serializeToSink(
-        sink, compiler.libraryLoader.libraries);
-    serializedData = new SerializedData(uri, sink.text);
-    if (arguments.saveSerializedData) {
-      File file = new File(arguments.serializedDataFileName);
-      print('Saving data to $file');
-      file.writeAsStringSync(serializedData.data);
-    }
+  if (arguments.saveSerializedData) {
+    File file = new File(arguments.serializedDataFileName);
+    print('Saving data to $file');
+    file.writeAsStringSync(serializedData.data);
   }
   return serializedData;
 }
 
+class SerializationResult {
+  final Compiler compiler;
+  final SerializedData serializedData;
+
+  SerializationResult(this.compiler, this.serializedData);
+}
+
+Future<SerializationResult> serialize(Uri entryPoint, [Uri dataUri]) async {
+  if (dataUri == null) {
+    dataUri = Uri.parse('memory:${DEFAULT_DATA_FILE_NAME}');
+  }
+  Compiler compiler = compilerFor(options: [Flags.analyzeAll]);
+  compiler.serialization.supportSerialization = true;
+  await compiler.run(entryPoint);
+  BufferedEventSink sink = new BufferedEventSink();
+  compiler.serialization.serializeToSink(
+      sink, compiler.libraryLoader.libraries);
+  SerializedData serializedData = new SerializedData(dataUri, sink.text);
+  return new SerializationResult(compiler, serializedData);
+}
+
 class SerializedData {
   final Uri uri;
   final String data;
diff --git a/tests/compiler/dart2js/serialization/model_test.dart b/tests/compiler/dart2js/serialization/model_test.dart
index d7eeed6..37b99df 100644
--- a/tests/compiler/dart2js/serialization/model_test.dart
+++ b/tests/compiler/dart2js/serialization/model_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 library dart2js.serialization_model_test;
-
 import 'dart:async';
 import 'dart:io';
 import 'package:async_helper/async_helper.dart';
@@ -13,6 +12,7 @@
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/elements/elements.dart';
 import 'package:compiler/src/filenames.dart';
+import 'package:compiler/src/js_backend/js_backend.dart';
 import 'package:compiler/src/serialization/equivalence.dart';
 import 'package:compiler/src/tree/nodes.dart';
 import 'package:compiler/src/universe/class_set.dart';
@@ -33,7 +33,7 @@
           resolutionInputs: serializedData.toUris());
     } else {
       Uri entryPoint = Uri.parse('memory:main.dart');
-      arguments.forEachTest(serializedData, TESTS, checkModels);
+      await arguments.forEachTest(serializedData, TESTS, checkModels);
     }
   });
 }
@@ -45,11 +45,6 @@
      int index,
      Test test,
      bool verbose: false}) async {
-  if (test != null && test.name == 'Disable tree shaking through reflection') {
-    // TODO(johnniwinther): Support serialization of metadata.
-    return;
-  }
-
   String testDescription = test != null ? test.name : '${entryPoint}';
   String id = index != null ? '$index: ' : '';
   print('------------------------------------------------------------------');
@@ -121,6 +116,19 @@
       compilerDeserialized.world.getClassHierarchyNode(
           compilerDeserialized.coreClasses.objectClass),
       verbose: verbose);
+
+  Expect.equals(compilerNormal.enabledInvokeOn,
+      compilerDeserialized.enabledInvokeOn,
+      "Compiler.enabledInvokeOn mismatch");
+  Expect.equals(compilerNormal.enabledFunctionApply,
+      compilerDeserialized.enabledFunctionApply,
+      "Compiler.enabledFunctionApply mismatch");
+  Expect.equals(compilerNormal.enabledRuntimeType,
+      compilerDeserialized.enabledRuntimeType,
+      "Compiler.enabledRuntimeType mismatch");
+  Expect.equals(compilerNormal.hasIsolateSupport,
+      compilerDeserialized.hasIsolateSupport,
+      "Compiler.hasIsolateSupport mismatch");
 }
 
 void checkElements(
@@ -133,11 +141,11 @@
     AstElement astElement1 = element1;
     AstElement astElement2 = element2;
     ClosureClassMap closureData1 =
-    compiler1.closureToClassMapper.computeClosureToClassMapping(
-        astElement1.resolvedAst);
+        compiler1.closureToClassMapper.computeClosureToClassMapping(
+            astElement1.resolvedAst);
     ClosureClassMap closureData2 =
-    compiler2.closureToClassMapper.computeClosureToClassMapping(
-        astElement2.resolvedAst);
+        compiler2.closureToClassMapper.computeClosureToClassMapping(
+            astElement2.resolvedAst);
 
     checkElementIdentities(closureData1, closureData2,
         '$element1.closureElement',
@@ -174,6 +182,12 @@
         areLocalsEquivalent,
         verbose: verbose);
   }
+  JavaScriptBackend backend1 = compiler1.backend;
+  JavaScriptBackend backend2 = compiler2.backend;
+  Expect.equals(
+      backend1.inlineCache.getCurrentCacheDecisionForTesting(element1),
+      backend2.inlineCache.getCurrentCacheDecisionForTesting(element2),
+      "Inline cache decision mismatch for $element1 vs $element2");
 }
 
 void checkMixinUses(
@@ -240,128 +254,6 @@
   checkMixinUses(compiler1, compiler2, node1.cls, node2.cls, verbose: verbose);
 }
 
-void checkSets(
-    Iterable set1,
-    Iterable set2,
-    String messagePrefix,
-    bool sameElement(a, b),
-    {bool failOnUnfound: true,
-     bool verbose: false,
-     void onSameElement(a, b)}) {
-  List common = [];
-  List unfound = [];
-  Set remaining = computeSetDifference(
-      set1, set2, common, unfound,
-      sameElement: sameElement,
-      checkElements: onSameElement);
-  StringBuffer sb = new StringBuffer();
-  sb.write("$messagePrefix:");
-  if (verbose) {
-    sb.write("\n Common:\n  ${common.join('\n  ')}");
-  }
-  if (unfound.isNotEmpty || verbose) {
-    sb.write("\n Unfound:\n  ${unfound.join('\n  ')}");
-  }
-  if (remaining.isNotEmpty || verbose) {
-    sb.write("\n Extra: \n  ${remaining.join('\n  ')}");
-  }
-  String message = sb.toString();
-  if (unfound.isNotEmpty || remaining.isNotEmpty) {
-
-    if (failOnUnfound || remaining.isNotEmpty) {
-      Expect.fail(message);
-    } else {
-      print(message);
-    }
-  } else if (verbose) {
-    print(message);
-  }
-}
-
-String defaultToString(obj) => '$obj';
-
-void checkMaps(
-    Map map1,
-    Map map2,
-    String messagePrefix,
-    bool sameKey(a, b),
-    bool sameValue(a, b),
-    {bool failOnUnfound: true,
-     bool failOnMismatch: true,
-     bool verbose: false,
-     String keyToString(key): defaultToString,
-     String valueToString(key): defaultToString}) {
-  List common = [];
-  List unfound = [];
-  List<List> mismatch = <List>[];
-  Set remaining = computeSetDifference(
-      map1.keys, map2.keys, common, unfound,
-      sameElement: sameKey,
-      checkElements: (k1, k2) {
-        var v1 = map1[k1];
-        var v2 = map2[k2];
-        if (!sameValue(v1, v2)) {
-          mismatch.add([k1, k2]);
-        }
-      });
-  StringBuffer sb = new StringBuffer();
-  sb.write("$messagePrefix:");
-  if (verbose) {
-    sb.write("\n Common: \n");
-    for (List pair in common) {
-      var k1 = pair[0];
-      var k2 = pair[1];
-      var v1 = map1[k1];
-      var v2 = map2[k2];
-      sb.write(" key1   =${keyToString(k1)}\n");
-      sb.write(" key2   =${keyToString(k2)}\n");
-      sb.write("  value1=${valueToString(v1)}\n");
-      sb.write("  value2=${valueToString(v2)}\n");
-    }
-  }
-  if (unfound.isNotEmpty || verbose) {
-    sb.write("\n Unfound: \n");
-    for (var k1 in unfound) {
-      var v1 = map1[k1];
-      sb.write(" key1   =${keyToString(k1)}\n");
-      sb.write("  value1=${valueToString(v1)}\n");
-    }
-  }
-  if (remaining.isNotEmpty || verbose) {
-    sb.write("\n Extra: \n");
-    for (var k2 in remaining) {
-      var v2 = map2[k2];
-      sb.write(" key2   =${keyToString(k2)}\n");
-      sb.write("  value2=${valueToString(v2)}\n");
-    }
-  }
-  if (mismatch.isNotEmpty || verbose) {
-    sb.write("\n Mismatch: \n");
-    for (List pair in mismatch) {
-      var k1 = pair[0];
-      var k2 = pair[1];
-      var v1 = map1[k1];
-      var v2 = map2[k2];
-      sb.write(" key1   =${keyToString(k1)}\n");
-      sb.write(" key2   =${keyToString(k2)}\n");
-      sb.write("  value1=${valueToString(v1)}\n");
-      sb.write("  value2=${valueToString(v2)}\n");
-    }
-  }
-  String message = sb.toString();
-  if (unfound.isNotEmpty || mismatch.isNotEmpty || remaining.isNotEmpty) {
-    if ((unfound.isNotEmpty && failOnUnfound) ||
-        (mismatch.isNotEmpty && failOnMismatch) ||
-        remaining.isNotEmpty) {
-      Expect.fail(message);
-    } else {
-      print(message);
-    }
-  } else if (verbose) {
-    print(message);
-  }
-}
-
 bool areLocalsEquivalent(Local a, Local b) {
   if (a == b) return true;
   if (a == null || b == null) return false;
diff --git a/tests/compiler/dart2js/serialization/native_data_test.dart b/tests/compiler/dart2js/serialization/native_data_test.dart
new file mode 100644
index 0000000..d2a9173
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/native_data_test.dart
@@ -0,0 +1,100 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.serialization.native_data_test;
+
+import 'dart:async';
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/common/names.dart';
+import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/js_backend/js_backend.dart';
+import 'package:compiler/src/js_backend/native_data.dart';
+import 'package:compiler/src/filenames.dart';
+import 'package:compiler/src/serialization/equivalence.dart';
+import '../memory_compiler.dart';
+import 'helper.dart';
+import 'test_helper.dart';
+
+main(List<String> args) {
+  asyncTest(() async {
+    Arguments arguments = new Arguments.from(args);
+    Uri uri = Uris.dart_html;
+    if (arguments.filename != null) {
+      uri = Uri.base.resolve(nativeToUriPath(arguments.filename));
+    }
+    await checkNativeData(uri, verbose: arguments.verbose);
+  });
+}
+
+Future checkNativeData(Uri uri, {bool verbose: false}) async {
+  print('------------------------------------------------------------------');
+  print('analyze normal: $uri');
+  print('------------------------------------------------------------------');
+  SerializationResult result = await serialize(uri);
+  Compiler compiler1 = result.compiler;
+  SerializedData serializedData = result.serializedData;
+
+  print('------------------------------------------------------------------');
+  print('analyze deserialized: $uri');
+  print('------------------------------------------------------------------');
+  Compiler compiler2 = compilerFor(
+      memorySourceFiles: serializedData.toMemorySourceFiles(),
+      resolutionInputs: serializedData.toUris(),
+      options: [Flags.analyzeAll]);
+  await compiler2.run(uri);
+
+  JavaScriptBackend backend1 = compiler1.backend;
+  JavaScriptBackend backend2 = compiler2.backend;
+  NativeData nativeData1 = backend1.nativeData;
+  NativeData nativeData2 = backend2.nativeData;
+
+  checkMaps(
+      nativeData1.jsInteropNames,
+      nativeData2.jsInteropNames,
+      "NativeData.jsInteropNames",
+      areElementsEquivalent,
+      equality,
+      verbose: verbose);
+
+  checkMaps(
+      nativeData1.nativeMemberName,
+      nativeData2.nativeMemberName,
+      "NativeData.nativeMemberName",
+      areElementsEquivalent,
+      equality,
+      verbose: verbose);
+
+  checkMaps(
+      nativeData1.nativeClassTagInfo,
+      nativeData2.nativeClassTagInfo,
+      "NativeData.nativeClassTagInfo",
+      areElementsEquivalent,
+      equality,
+      verbose: verbose);
+
+  checkMaps(
+      nativeData1.nativeMethodBehavior,
+      nativeData2.nativeMethodBehavior,
+      "NativeData.nativeMethodBehavior",
+      areElementsEquivalent,
+      testNativeBehavior,
+      verbose: verbose);
+
+  checkMaps(
+      nativeData1.nativeFieldLoadBehavior,
+      nativeData2.nativeFieldLoadBehavior,
+      "NativeData.nativeFieldLoadBehavior",
+      areElementsEquivalent,
+      testNativeBehavior,
+      verbose: verbose);
+
+  checkMaps(
+      nativeData1.nativeFieldStoreBehavior,
+      nativeData2.nativeFieldStoreBehavior,
+      "NativeData.nativeFieldStoreBehavior",
+      areElementsEquivalent,
+      testNativeBehavior,
+      verbose: verbose);
+}
diff --git a/tests/compiler/dart2js/serialization/test_helper.dart b/tests/compiler/dart2js/serialization/test_helper.dart
index 4bbed39..a6dddf9 100644
--- a/tests/compiler/dart2js/serialization/test_helper.dart
+++ b/tests/compiler/dart2js/serialization/test_helper.dart
@@ -12,6 +12,7 @@
 import 'package:compiler/src/elements/elements.dart';
 import 'package:compiler/src/serialization/equivalence.dart';
 import 'package:compiler/src/tree/nodes.dart';
+import 'package:expect/expect.dart';
 
 Check currentCheck;
 
@@ -185,7 +186,7 @@
 Set computeSetDifference(
     Iterable set1,
     Iterable set2,
-    List common,
+    List<List> common,
     List unfound,
     {bool sameElement(a, b): equality,
      void checkElements(a, b)}) {
@@ -197,19 +198,19 @@
   // set.difference would work)
   Set remaining = set2.toSet();
   for (var element1 in set1) {
-    bool found = false;
+    var correspondingElement;
     for (var element2 in remaining) {
       if (sameElement(element1, element2)) {
         if (checkElements != null) {
           checkElements(element1, element2);
         }
-        found = true;
+        correspondingElement = element2;
         remaining.remove(element2);
         break;
       }
     }
-    if (found) {
-      common.add(element1);
+    if (correspondingElement != null) {
+      common.add([element1, correspondingElement]);
     } else {
       unfound.add(element1);
     }
@@ -229,7 +230,7 @@
     Iterable set2,
     bool sameElement(a, b),
     {void onSameElement(a, b)}) {
-  List common = [];
+  List<List> common = <List>[];
   List unfound = [];
   Set remaining =
       computeSetDifference(set1, set2, common, unfound,
@@ -428,3 +429,127 @@
 
   testResolutionImpactEquivalence(impact1, impact2, const CheckStrategy());
 }
+
+void checkSets(
+    Iterable set1,
+    Iterable set2,
+    String messagePrefix,
+    bool sameElement(a, b),
+    {bool failOnUnfound: true,
+    bool failOnExtra: true,
+    bool verbose: false,
+    void onSameElement(a, b)}) {
+  List<List> common = <List>[];
+  List unfound = [];
+  Set remaining = computeSetDifference(
+      set1, set2, common, unfound,
+      sameElement: sameElement,
+      checkElements: onSameElement);
+  StringBuffer sb = new StringBuffer();
+  sb.write("$messagePrefix:");
+  if (verbose) {
+    sb.write("\n Common:\n  ${common.join('\n  ')}");
+  }
+  if (unfound.isNotEmpty || verbose) {
+    sb.write("\n Unfound:\n  ${unfound.join('\n  ')}");
+  }
+  if (remaining.isNotEmpty || verbose) {
+    sb.write("\n Extra: \n  ${remaining.join('\n  ')}");
+  }
+  String message = sb.toString();
+  if (unfound.isNotEmpty || remaining.isNotEmpty) {
+
+    if ((failOnUnfound && unfound.isNotEmpty) ||
+        (failOnExtra && remaining.isNotEmpty)) {
+      Expect.fail(message);
+    } else {
+      print(message);
+    }
+  } else if (verbose) {
+    print(message);
+  }
+}
+
+String defaultToString(obj) => '$obj';
+
+void checkMaps(
+    Map map1,
+    Map map2,
+    String messagePrefix,
+    bool sameKey(a, b),
+    bool sameValue(a, b),
+    {bool failOnUnfound: true,
+    bool failOnMismatch: true,
+    bool verbose: false,
+    String keyToString(key): defaultToString,
+    String valueToString(key): defaultToString}) {
+  List<List> common = <List>[];
+  List unfound = [];
+  List<List> mismatch = <List>[];
+  Set remaining = computeSetDifference(
+      map1.keys, map2.keys, common, unfound,
+      sameElement: sameKey,
+      checkElements: (k1, k2) {
+        var v1 = map1[k1];
+        var v2 = map2[k2];
+        if (!sameValue(v1, v2)) {
+          mismatch.add([k1, k2]);
+        }
+      });
+  StringBuffer sb = new StringBuffer();
+  sb.write("$messagePrefix:");
+  if (verbose) {
+    sb.write("\n Common: \n");
+    for (List pair in common) {
+      var k1 = pair[0];
+      var k2 = pair[1];
+      var v1 = map1[k1];
+      var v2 = map2[k2];
+      sb.write(" key1   =${keyToString(k1)}\n");
+      sb.write(" key2   =${keyToString(k2)}\n");
+      sb.write("  value1=${valueToString(v1)}\n");
+      sb.write("  value2=${valueToString(v2)}\n");
+    }
+  }
+  if (unfound.isNotEmpty || verbose) {
+    sb.write("\n Unfound: \n");
+    for (var k1 in unfound) {
+      var v1 = map1[k1];
+      sb.write(" key1   =${keyToString(k1)}\n");
+      sb.write("  value1=${valueToString(v1)}\n");
+    }
+  }
+  if (remaining.isNotEmpty || verbose) {
+    sb.write("\n Extra: \n");
+    for (var k2 in remaining) {
+      var v2 = map2[k2];
+      sb.write(" key2   =${keyToString(k2)}\n");
+      sb.write("  value2=${valueToString(v2)}\n");
+    }
+  }
+  if (mismatch.isNotEmpty || verbose) {
+    sb.write("\n Mismatch: \n");
+    for (List pair in mismatch) {
+      var k1 = pair[0];
+      var k2 = pair[1];
+      var v1 = map1[k1];
+      var v2 = map2[k2];
+      sb.write(" key1   =${keyToString(k1)}\n");
+      sb.write(" key2   =${keyToString(k2)}\n");
+      sb.write("  value1=${valueToString(v1)}\n");
+      sb.write("  value2=${valueToString(v2)}\n");
+    }
+  }
+  String message = sb.toString();
+  if (unfound.isNotEmpty || mismatch.isNotEmpty || remaining.isNotEmpty) {
+    if ((unfound.isNotEmpty && failOnUnfound) ||
+        (mismatch.isNotEmpty && failOnMismatch) ||
+        remaining.isNotEmpty) {
+      Expect.fail(message);
+    } else {
+      print(message);
+    }
+  } else if (verbose) {
+    print(message);
+  }
+}
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index 897d5b3..df4de07 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -84,3 +84,6 @@
 
 [ $compiler == dart2js && $runtime == ff && $system == windows ]
 consistent_index_error_string_test: Pass, Slow # Issue 25940
+
+[ $compiler == dart2js && $runtime == ff && $system == linux ]
+mirror_printer_test: Pass, Slow # Issue 25940
diff --git a/tests/html/html.status b/tests/html/html.status
index c36e35a..670665a 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -104,6 +104,7 @@
 element_types_test/supported_object: RuntimeError # Issue 25155
 element_types_test/supported_embed: RuntimeError # Issue 25155
 svgelement_test/PathElement: RuntimeError # Issue 25665
+element_animate_test/timing_dict: RuntimeError # Issue 26730
 
 [ $runtime == chrome && $system == macos ]
 canvasrenderingcontext2d_test/drawImage_video_element: Skip # Times out. Please triage this failure.
@@ -301,43 +302,6 @@
 js_test/JsArray: RuntimeError # Fails 10 out of 10.
 indexeddb_3_test: Skip # Times out 1 out of 10.
 
-[ $runtime == opera ]
-blob_constructor_test: Fail
-canvas_test: Fail
-canvas_test: Pass,Fail
-cssstyledeclaration_test: Fail
-document_test/document: Fail # Issue: 7413
-element_add_test: Fail
-element_constructor_1_test: Fail
-element_test/children: Fail # Issue: 7413
-element_test/constructors: Fail
-element_test/elements: Fail
-element_test/eventListening: Crash
-element_test/eventListening: Fail # Issue: 7413
-element_test/queryAll: Fail
-fileapi_test: Skip # Timeout.
-form_data_test: Fail # Issue: 7413
-htmlelement_test: Fail
-isolates_test: Skip # Timeout.
-keyboard_event_test: Fail # Issue: 7413
-serialized_script_value_test: Fail
-typed_arrays_arraybuffer_test: Fail
-url_test: Fail
-
-# Opera Feature support statuses-
-# All changes should be accompanied by platform support annotation changes.
-audiobuffersourcenode_test/supported: Fail
-audiocontext_test/supported: Fail
-crypto_test/supported: Fail
-css_test/supportsPointConversions: Fail
-element_types_test/supported_template: Fail
-indexeddb_1_test/supported: Fail
-indexeddb_1_test/supportsDatabaseNames: Fail
-mutationobserver_test/supported: Fail
-performance_api_test/supported: Fail
-speechrecognition_test/supported: Fail
-websql_test/supported: Fail
-
 [  $compiler == dart2js && $runtime == ff ]
 history_test/history: Skip # Issue 22050
 xhr_test/xhr: Pass, Fail # Issue 11602
diff --git a/tests/language/const_constructor_super2_test.dart b/tests/language/const_constructor_super2_test.dart
new file mode 100644
index 0000000..8832d24
--- /dev/null
+++ b/tests/language/const_constructor_super2_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+class A {
+  final a;
+
+  const A(this.a);
+}
+
+class B extends A {
+  final b;
+
+  const B(a, this.b) : super(a);
+}
+
+@NoInline()
+foo() => const B(1, 2);
+
+@NoInline()
+bar() => const B(2, 2);
+
+void main() {
+  Expect.notEquals(foo(), bar());
+  Expect.notEquals(foo().a, bar().a);
+  Expect.equals(foo().b, bar().b);
+}
\ No newline at end of file
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index d80aae4..aec3d55 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -16,6 +16,8 @@
 deep_nesting1_negative_test: Crash # Issue 25557
 deep_nesting2_negative_test: Crash # Issue 25557
 
+regress_18713_test: Fail # Issue 26743
+
 call_function_apply_test: RuntimeError # Issue 23873
 mixin_supertype_subclass_test: CompileTimeError # Issue 23773
 mixin_supertype_subclass2_test: CompileTimeError # Issue 23773
@@ -227,6 +229,9 @@
 [ $compiler == dart2js && $runtime == ff ]
 round_test: Pass, Fail, OK # Fixed in ff 35. Common JavaScript engine Math.round bug.
 
+[ $compiler == dart2js && $runtime == chrome && $system == macos ]
+await_future_test: Pass, Timeout # Issue 26735
+
 [ $compiler == dart2js && ($runtime == safari || $runtime == safarimobilesim)]
 # Safari codegen bug, fixed on some versions of Safari 7.1 (Version 7.1 (9537.85.10.17.1))
 call_through_getter_test: Fail, OK
diff --git a/tests/language/regress_18713_test.dart b/tests/language/regress_18713_test.dart
new file mode 100644
index 0000000..b0d8736
--- /dev/null
+++ b/tests/language/regress_18713_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class T<X> {
+  final Type tType = X;
+  Type get getTType => X;
+}
+
+class S<Y> {
+  final Type sType = Y;
+  Type get getSType => Y;
+}
+
+class TS<A, B> = T<A> with S<B>;
+
+main() {
+  var ts = new TS<int, String>();
+  Expect.equals("String", ts.sType.toString());
+  Expect.equals("int", ts.tType.toString());
+  Expect.equals("String", ts.getSType.toString());
+  Expect.equals("int", ts.getTType.toString());
+}
diff --git a/tests/language/regress_26530_test.dart b/tests/language/regress_26530_test.dart
new file mode 100644
index 0000000..a41761a
--- /dev/null
+++ b/tests/language/regress_26530_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+var trace = "";
+
+main() {
+  var x = 0;
+  try {
+    try {
+      throw x++;  // 1
+    } on int catch (e) {
+      trace += "$e";
+      trace += "-$x";
+      x++;  // 2
+      try {
+        x++;  // 3
+        rethrow;
+      } finally {
+        trace += "-f";
+        x++;  // 4
+      }
+    }
+  } catch (e) {
+    trace += "-c";
+    trace += "-$e";
+    trace += "-$x";
+  }
+  Expect.equals("0-1-f-c-0-4", trace);
+}
diff --git a/tests/lib/async/timer_regress22626_test.dart b/tests/lib/async/timer_regress22626_test.dart
index 483b9338..810be7c 100644
--- a/tests/lib/async/timer_regress22626_test.dart
+++ b/tests/lib/async/timer_regress22626_test.dart
@@ -12,7 +12,7 @@
 import 'dart:math';
 import 'package:expect/expect.dart';
 
-int countdown = 10;
+int countdown = 5;
 var rng = new Random(1234);
 
 void test(int delay, int delta) {
@@ -31,5 +31,5 @@
 }
 
 void main() {
-  test(50, 2);
+  test(200, 2);
 }
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 07ac39b..7a60549 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -229,6 +229,9 @@
 # TODO(efortuna): Investigate.
 async/timer_test: Fail, Pass
 
+[ $runtime == vm ]
+convert/streamed_conversion_json_utf8_decode_test: Pass, Slow # Infrequent timeouts.
+
 [ ($runtime == vm || $runtime == dart_precompiled || $runtime == dart_app) ]
 async/timer_not_available_test: Fail, OK
 mirrors/native_class_test: Fail, OK # This test is meant to run in a browser.
diff --git a/tests/standalone/packages_file_test.dart b/tests/standalone/packages_file_test.dart
index 9902d69..d41e46b 100644
--- a/tests/standalone/packages_file_test.dart
+++ b/tests/standalone/packages_file_test.dart
@@ -85,26 +85,11 @@
 /// This should not change the expected results compared to running it
 /// directly.
 Configuration spawn(Configuration conf) {
-  // TODO(26555): Clean up when fixed.
-  // TEMPORARY FIX FOR ISSUE #26555 (http://dartbug.com/26555)
-  if (conf.expect["iroot"] == null &&
-      conf.expect["iconf"] == null &&
-      conf.expect["pconf"] != null) {
-    // The spawned isolate will do a search for a package file or root,
-    // which is not what the original did. Skip test for now.
-    return null;
-  }
-  // REMOVE WHEN ISSUE FIXED!
   return conf.update(
     description: conf.description + "/spawn",
     main: "spawnMain",
     newArgs: [conf.mainType],
-    // TEMPORARY FIX FOR ISSUE #26555 (http://dartbug.com/26555)
-    expect: {
-      "proot": conf.expect["iroot"],
-      "pconf": conf.expect["iconf"],
-    }
-    // REMOVE WHEN ISSUE FIXED!
+    expect: null
   );
 }
 
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index c039aad..5c03bea 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -7,7 +7,7 @@
 # listed in tests/lib/analyzer/analyze_tests.status without the "standalone"
 # prefix.
 
-packages_file_test: Pass, Slow
+packages_file_test: Skip # Issue 26715
 packages_file_test/none: Skip   # contains no tests.
 
 package/invalid_uri_test: Fail, OK # CompileTimeErrors intentionally
diff --git a/tools/VERSION b/tools/VERSION
index 4fd0654..67e5d05 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 1
 MINOR 18
 PATCH 0
-PRERELEASE 1
+PRERELEASE 2
 PRERELEASE_PATCH 0