Version 1.19.0-dev.0.0

Merge 9d5fd9d5bd9dea0098a8f49a87300ab578eb765c into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8f44d60..26425b5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,4 @@
-## 1.18.0
+## 1.18.0 - 2016-07-27
 
 ### Core library changes
 
diff --git a/DEPS b/DEPS
index cbcfa64..3b3ac3b 100644
--- a/DEPS
+++ b/DEPS
@@ -56,7 +56,7 @@
   "dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
   "dart_style_tag": "@0.2.4",
   "dartdoc_tag" : "@v0.9.6+2",
-  "dev_compiler_rev": "@7e9708eb5e9f3fcdc68b9af039d78cf39ce502b7",
+  "dev_compiler_rev": "@108f2a2a03b1926e640013f3244df625b42ec380",
   "fixnum_tag": "@0.10.5",
   "func_rev": "@8d4aea75c21be2179cb00dc2b94a71414653094e",
   "glob_rev": "@704cf75e4f26b417505c5c611bdaacd8808467dd",
@@ -68,6 +68,7 @@
   "idl_parser_rev": "@7fbe68cab90c38147dee4f48c30ad0d496c17915",
   "initialize_rev": "@595d501a92c3716395ad2d81f9aabdb9f90879b6",
   "intl_tag": "@0.13.0",
+  "isolate_tag": "@0.2.2",
   "jinja2_rev": "@2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_tag": "@2.0.0",
   "linter_rev": "@7ca3aab6ca45b988440e425c187993a533fbe27e",
@@ -92,7 +93,7 @@
   "quiver_tag": "@0.21.4",
   "resource_rev":"@a49101ba2deb29c728acba6fb86000a8f730f4b1",
   "root_certificates_rev": "@aed07942ce98507d2be28cbd29e879525410c7fc",
-  "scheduled_test_tag": "@0.12.5+2",
+  "scheduled_test_tag": "@0.12.6",
   "shelf_static_tag": "@0.2.3+4",
   "shelf_tag": "@0.6.5+2",
   "shelf_web_socket_tag": "@0.2.0",
@@ -106,7 +107,7 @@
   "string_scanner_tag": "@0.1.4",
   "sunflower_rev": "@879b704933413414679396b129f5dfa96f7a0b1e",
   "test_reflective_loader_tag": "@0.0.3",
-  "test_tag": "@0.12.13+5",
+  "test_tag": "@0.12.15+1",
   "typed_data_tag": "@1.1.2",
   "usage_rev": "@b5080dac0d26a5609b266f8fdb0d053bc4c1c638",
   "utf_rev": "@1f55027068759e2d52f2c12de6a57cce5f3c5ee6",
@@ -222,6 +223,8 @@
       (Var("github_dartlang") % "initialize") + Var("initialize_rev"),
   Var("dart_root") + "/third_party/pkg/intl":
       (Var("github_mirror") % "intl") + Var("intl_tag"),
+  Var("dart_root") + "/third_party/pkg/isolate":
+      (Var("github_dartlang") % "isolate") + Var("isolate_tag"),
   Var("dart_root") + "/third_party/pkg/json_rpc_2":
       (Var("github_mirror") % "json_rpc_2") + Var("json_rpc_2_tag"),
   Var("dart_root") + "/third_party/pkg/linter":
diff --git a/README.fuchsia b/README.fuchsia
deleted file mode 100644
index f09ff26..0000000
--- a/README.fuchsia
+++ /dev/null
@@ -1,41 +0,0 @@
-This is a README file describing how to build Dart for Fuchsia. It assumes that
-you have built the magenta kernel under //magenta, its toolchains are
-under //toolchains, and that you have a Dart checkout under //dart. It is early
-days and this is crufty. The process will improve from here.
-
-1. First, set up some symlinks in your Dart checkout:
-
-  //dart/third_party/fuchsia_tools/toolchains
-      -> symlinked to //toolchains
-  //dart/third_party/fuchsia_tools/sysroot/x86_64/usr
-      -> symlinked to //magenta/build-magenta-qemu-x86-64/sysroot/
-
-  Also, copy the linker script:
-
-  //magenta$ cp kernel/arch/x86/64/user.ld build-magenta-qemu-x86-64/sysroot/
-
-  and similarly for arm64.
-
-2. Build:
-
-  //dart$ tools/build.py -m product -a x64 --os=fuchsia fuchsia_test
-
-  This will produce //dart/out/ProductFuchsiaX64/fuchsia_test
-
-3. Strip it:
-
-  //dart$ third_party/fuchsia_tools/toolchains/x86_64-elf-5.3.0-Linux-x86_64/bin/x86_64-elf-strip out/ProductFuchsiaX64/fuchsia_test -o out/ProductFuchsiaX64/fuchsia_test.stripped
-
-4. Make a file //magenta/fuchsia_test.manifest containing:
-
-  bin/fuchsia_test=//dart/out/ProductFuchsiaX64/fuchsia_test.stripped
-
-  Where //dart is the actual path to your Dart checkout.
-
-5. Make an extra bootfs:
-
-  //magenta$ build-magenta-qemu-x86-64/tools/mkbootfs -o fuchsia_test.bootfs fuchsia_test.manifest
-
-6. Run:
-
-  //magenta$ ./scripts/run-magenta-x86-64 -x fuchsia_test.bootfs
diff --git a/dart.gyp b/dart.gyp
index f513625..b942371 100644
--- a/dart.gyp
+++ b/dart.gyp
@@ -35,13 +35,6 @@
       ],
     },
     {
-      'target_name': 'fuchsia_test',
-      'type': 'none',
-      'dependencies': [
-        'runtime/dart-runtime.gyp:fuchsia_test',
-      ],
-    },
-    {
       # This is the target that is built on the VM build bots.  It
       # must depend on anything that is required by the VM test
       # suites.
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index 140a8df..0b76367 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -655,9 +655,11 @@
 It is a compile-time error if a formal parameter is declared as a constant variable (\ref{variables}).
 
 \begin{grammar}
-{\bf formalParameterList:}`(' `)';
- `(' normalFormalParameters ( `,'  optionalFormalParameters)? `)';
-  `(' optionalFormalParameters `)'
+{\bf formalParameterList:}
+     `(' `)';
+     `(' normalFormalParameters `,'? `)';
+     `(' normalFormalParameters `,'  optionalFormalParameters `)';
+     `(' optionalFormalParameters `)'
    .
 %\end{grammar}
 %}
@@ -673,18 +675,21 @@
       normalFormalParameter (`,' normalFormalParameter)*
     .
 
-{\bf optionalFormalParameters:}optionalPositionalFormalParameters;
+{\bf optionalFormalParameters:}
+      optionalPositionalFormalParameters;
       namedFormalParameters
     .
 
 {\bf optionalPositionalFormalParameters:}
-      `[' defaultFormalParameter (`,' defaultFormalParameter)* `]'
+      `[' defaultFormalParameter (`,' defaultFormalParameter)* `,'? `]'
     .
 {\bf namedFormalParameters:}
-      `\{' defaultNamedParameter (`,' defaultNamedParameter)* `\}'
+      `\{' defaultNamedParameter (`,' defaultNamedParameter)* `,'? `\}'
     .
 \end{grammar}
 
+Formal parameter lists allow an optional trailing comma after the last parameter ($`,'?$). A parameter list with such a trailing comma is equivalent in all ways to the same parameter list without the trailing comma. All parameter lists in this specification are shown without a trailing comma, but the rules and semantics apply equally to the corresponding parameter list with a trailing comma.
+
 %Formal parameters are always \FINAL{}.
 %\Q{We're awaiting some data on whether enforcing this would cause widespread pain.}
 %A formal parameter is always considered to be initialized.  \rationale{This is because it will always be initialized by the call - even if it is optional.}
@@ -3608,10 +3613,11 @@
 
 \begin{grammar}
 {\bf arguments:}
-      `(' argumentList? `)'
+      `(' (argumentList  `,'?)? `)'
     .
 
-{\bf argumentList:}namedArgument (`,' namedArgument)*;
+{\bf argumentList:}
+      namedArgument (`,' namedArgument)*;
   %    expressionList ',' spreadArgument;
       expressionList (`,' namedArgument)*
 %      spreadArgument
@@ -3622,6 +3628,8 @@
     .
  \end{grammar}
 
+Argument lists allow an optional trailing comma after the last argument ($`,'?$). An argument list with such a trailing comma is equivalent in all ways to the same parameter list without the trailing comma. All argument lists in this specification are shown without a trailing comma, but the rules and semantics apply equally to the corresponding argument list with a trailing comma.
+
 \LMHash{}
 Evaluation of an actual argument list of the form
 
diff --git a/pkg/analysis_server/benchmark/perf/benchmark_flutter.dart b/pkg/analysis_server/benchmark/perf/benchmark_flutter.dart
new file mode 100644
index 0000000..87ccc30
--- /dev/null
+++ b/pkg/analysis_server/benchmark/perf/benchmark_flutter.dart
@@ -0,0 +1,217 @@
+// 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 'dart:async';
+
+import 'package:analysis_server/plugin/protocol/protocol.dart';
+
+import 'benchmark_scenario.dart';
+import 'memory_tests.dart';
+
+main(List<String> args) async {
+  int length = args.length;
+  if (length < 1) {
+    print('Usage: dart benchmark_local.dart path_to_flutter_checkout'
+        ' [benchmark_id]');
+    return;
+  }
+  paths = new PathHolder(flutterPath: args[0]);
+  String id = args.length >= 2 ? args[1] : null;
+  if (id == null) {
+    for (String id in benchmarks.keys) {
+      BenchmarkFunction benchmark = benchmarks[id];
+      await benchmark(id);
+    }
+  } else {
+    BenchmarkFunction benchmark = benchmarks[id];
+    if (benchmark != null) {
+      benchmark(id);
+    }
+  }
+}
+
+const Map<String, BenchmarkFunction> benchmarks =
+    const <String, BenchmarkFunction>{
+  'flutter-initialAnalysis-1': run_flutter_initialAnalysis_1,
+  'flutter-initialAnalysis-2': run_flutter_initialAnalysis_2,
+  'flutter-change-1': run_flutter_change_1,
+  'flutter-change-2': run_flutter_change_2,
+  'flutter-completion-1': run_flutter_completion_1,
+  'flutter-completion-2': run_flutter_completion_2,
+  'flutter-refactoring-1': run_flutter_refactoring_1,
+  'flutter-memory-initialAnalysis-1': run_flutter_memory_initialAnalysis_1,
+  'flutter-memory-initialAnalysis-2': run_flutter_memory_initialAnalysis_2,
+};
+
+PathHolder paths;
+
+Future run_flutter_change_1(String id) async {
+  String description = r'''
+1. Open 'packages/flutter'.
+2. Change a method body in lib/src/painting/colors.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: [paths.packageFlutter],
+      file: '${paths.packageFlutter}/lib/src/painting/colors.dart',
+      fileChange: new FileChange(
+          afterStr: 'final double h = hue % 360;', insertStr: 'print(12345);'),
+      numOfRepeats: 10);
+  printBenchmarkResults(id, description, times);
+}
+
+Future run_flutter_change_2(String id) async {
+  String description = r'''
+1. Open 'packages/flutter'.
+2. Change the name of a public method in lib/src/painting/colors.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: [paths.packageFlutter],
+      file: '${paths.packageFlutter}/lib/src/painting/colors.dart',
+      fileChange: new FileChange(
+          afterStr: 'withValue(dou', afterStrBack: 4, insertStr: 'NewName'),
+      numOfRepeats: 5);
+  printBenchmarkResults(id, description, times);
+}
+
+Future run_flutter_completion_1(String id) async {
+  String description = r'''
+1. Open 'packages/flutter'.
+2. Change a method body in packages/flutter/lib/src/material/button.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).
+''';
+  String completionMarker = 'print(12345);';
+  List<int> times = await new BenchmarkScenario()
+      .waitAnalyze_change_getCompletion(
+          roots: [paths.packageFlutter],
+          file: '${paths.packageFlutter}/lib/src/material/button.dart',
+          fileChange: new FileChange(
+              afterStr: 'Widget build(BuildContext context) {',
+              insertStr: completionMarker),
+          completeAfterStr: completionMarker,
+          numOfRepeats: 10);
+  printBenchmarkResults(id, description, times);
+}
+
+Future run_flutter_completion_2(String id) async {
+  String description = r'''
+1. Open 'packages/flutter'.
+2. Change the name of a public method in lib/src/rendering/layer.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: [paths.packageFlutter],
+          file: '${paths.packageFlutter}/lib/src/rendering/layer.dart',
+          fileChange: new FileChange(
+              replaceWhat: 'void removeAllChildren() {',
+              replaceWith: 'void removeAllChildren2() {print(12345);parent.'),
+          completeAfterStr: 'print(12345);parent.',
+          numOfRepeats: 5);
+  printBenchmarkResults(id, description, times);
+}
+
+Future run_flutter_initialAnalysis_1(String id) async {
+  String description = r'''
+1. Start server, set 'hello_world' 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: [paths.exampleHelloWorld], numOfRepeats: 5);
+  printBenchmarkResults(id, description, times);
+}
+
+Future run_flutter_initialAnalysis_2(String id) async {
+  String description = r'''
+1. Start server, set 'hello_world' and 'flutter_gallery' 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: [paths.exampleHelloWorld, paths.exampleGallery], numOfRepeats: 5);
+  printBenchmarkResults(id, description, times);
+}
+
+Future run_flutter_memory_initialAnalysis_1(String id) async {
+  String description = r'''
+1. Start server, set 'packages/flutter' as the analysis root.
+2. Measure the memory usage after finishing initial analysis.
+3. Shutdown the server.
+4. Go to (1).
+''';
+  List<int> sizes = await AnalysisServerMemoryUsageTest
+      .start_waitInitialAnalysis_shutdown(
+          roots: <String>[paths.packageFlutter], numOfRepeats: 3);
+  printMemoryResults(id, description, sizes);
+}
+
+Future run_flutter_memory_initialAnalysis_2(String id) async {
+  String description = r'''
+1. Start server, set 'packages/flutter' and 'packages/flutter_markdown' analysis roots.
+2. Measure the memory usage after finishing initial analysis.
+3. Shutdown the server.
+4. Go to (1).
+''';
+  List<int> sizes = await AnalysisServerMemoryUsageTest
+      .start_waitInitialAnalysis_shutdown(
+          roots: <String>[paths.packageFlutter, paths.packageMarkdown],
+          numOfRepeats: 3);
+  printMemoryResults(id, description, sizes);
+}
+
+Future run_flutter_refactoring_1(String id) async {
+  String description = r'''
+1. Open 'packages/flutter'.
+2. Change the name of a public method in lib/src/rendering/layer.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: [paths.packageFlutter],
+          file: '${paths.packageFlutter}/lib/src/rendering/layer.dart',
+          fileChange: new FileChange(
+              replaceWhat: 'void removeAllChildren() {',
+              replaceWith: 'void removeAllChildren2() {'),
+          refactoringAtStr: 'addToScene(ui.SceneBuilder builder',
+          refactoringKind: RefactoringKind.RENAME,
+          refactoringOptions: new RenameOptions('addToScene2'),
+          numOfRepeats: 5);
+  printBenchmarkResults(id, description, times);
+}
+
+typedef BenchmarkFunction(String id);
+
+class PathHolder {
+  String exampleHelloWorld;
+  String exampleGallery;
+  String exampleStocks;
+  String packageFlutter;
+  String packageMarkdown;
+  String packageSprites;
+
+  PathHolder({String flutterPath}) {
+    exampleHelloWorld = '$flutterPath/examples/hello_world';
+    exampleGallery = '$flutterPath/examples/flutter_gallery';
+    exampleStocks = '$flutterPath/examples/stocks';
+    packageFlutter = '$flutterPath/packages/flutter';
+    packageMarkdown = '$flutterPath/packages/flutter_markdown';
+    packageSprites = '$flutterPath/packages/flutter_sprites';
+  }
+}
diff --git a/pkg/analysis_server/benchmark/perf/benchmark_local.dart b/pkg/analysis_server/benchmark/perf/benchmark_local.dart
deleted file mode 100644
index 8cbdb89..0000000
--- a/pkg/analysis_server/benchmark/perf/benchmark_local.dart
+++ /dev/null
@@ -1,272 +0,0 @@
-// 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 'dart:async';
-
-import 'package:analysis_server/plugin/protocol/protocol.dart';
-
-import 'benchmark_scenario.dart';
-import 'memory_tests.dart';
-
-main(List<String> args) async {
-  int length = args.length;
-  if (length < 1) {
-    print(
-        'Usage: dart benchmark_local.dart path_to_sdk_checkout [path_to_flutter_checkout]');
-    return;
-  } else if (length == 1) {
-    paths = new PathHolder(sdkPath: args[0]);
-  } else {
-    paths = new PathHolder(sdkPath: args[0], flutterPath: args[1]);
-  }
-  String now = new DateTime.now().toUtc().toIso8601String();
-  print('Benchmark started: $now');
-  print('');
-  print('');
-  await run_local_initialAnalysis_1();
-  await run_local_initialAnalysis_2();
-  await run_local_initialAnalysis_3();
-  await run_local_change_1();
-  await run_local_change_2();
-  await run_local_completion_1();
-  await run_local_completion_2();
-  await run_local_completion_3();
-  await run_local_completion_4();
-  await run_local_refactoring_1();
-
-  await run_memory_initialAnalysis_1();
-  await run_memory_initialAnalysis_2();
-}
-
-PathHolder paths;
-
-Future run_local_change_1() async {
-  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: [paths.analyzer],
-      file: '${paths.analyzer}/lib/src/task/dart.dart',
-      fileChange: new FileChange(
-          afterStr: 'if (hasDirectiveChange) {', insertStr: 'print(12345);'),
-      numOfRepeats: 10);
-  printBenchmarkResults(id, description, times);
-}
-
-Future run_local_change_2() async {
-  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: [paths.analyzer],
-      file: '${paths.analyzer}/lib/src/task/dart.dart',
-      fileChange: new FileChange(
-          afterStr: 'resolveDirective(An',
-          afterStrBack: 3,
-          insertStr: 'NewName'),
-      numOfRepeats: 5);
-  printBenchmarkResults(id, description, times);
-}
-
-Future run_local_completion_1() async {
-  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: [paths.analyzer],
-          file: '${paths.analyzer}/lib/src/task/dart.dart',
-          fileChange: new FileChange(
-              afterStr: 'if (hasDirectiveChange) {',
-              insertStr: 'print(12345);'),
-          completeAfterStr: 'print(12345);',
-          numOfRepeats: 10);
-  printBenchmarkResults(id, description, times);
-}
-
-Future run_local_completion_2() async {
-  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: [paths.analyzer],
-          file: '${paths.analyzer}/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);
-}
-
-Future run_local_completion_3() async {
-  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: [paths.analysisServer, paths.analyzer],
-          file: '${paths.analyzer}/lib/src/task/dart.dart',
-          fileChange: new FileChange(
-              afterStr: 'if (hasDirectiveChange) {',
-              insertStr: 'print(12345);'),
-          completeAfterStr: 'print(12345);',
-          numOfRepeats: 10);
-  printBenchmarkResults(id, description, times);
-}
-
-Future run_local_completion_4() async {
-  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: [paths.analysisServer, paths.analyzer],
-          file: '${paths.analyzer}/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);
-}
-
-Future run_local_initialAnalysis_1() async {
-  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: [paths.analyzer], numOfRepeats: 3);
-  printBenchmarkResults(id, description, times);
-}
-
-Future run_local_initialAnalysis_2() async {
-  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: [paths.analyzer, paths.analysisServer], numOfRepeats: 3);
-  printBenchmarkResults(id, description, times);
-}
-
-Future run_local_initialAnalysis_3() async {
-  String id = 'local-initialAnalysis-3';
-  String description = r'''
-1. Start server, set 'hello_world' and 'stocks' 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: [paths.flutterHelloWorld, paths.flutterStocks], numOfRepeats: 3);
-  printBenchmarkResults(id, description, times);
-}
-
-Future run_local_refactoring_1() async {
-  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: [paths.analyzer],
-          file: '${paths.analyzer}/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);
-}
-
-Future run_memory_initialAnalysis_1() async {
-  String id = 'memory-initialAnalysis-1';
-  String description = r'''
-1. Start server, set 'analyzer' and 'analysis_server' analysis roots.
-2. Measure the memory usage after finishing initial analysis.
-3. Shutdown the server.
-4. Go to (1).
-''';
-  List<int> sizes = await AnalysisServerMemoryUsageTest
-      .start_waitInitialAnalysis_shutdown(
-          roots: <String>[paths.analyzer], numOfRepeats: 3);
-  printMemoryResults(id, description, sizes);
-}
-
-Future run_memory_initialAnalysis_2() async {
-  String id = 'memory-initialAnalysis-2';
-  String description = r'''
-1. Start server, set 'analyzer' and 'analysis_server' analysis roots.
-2. Measure the memory usage after finishing initial analysis.
-3. Shutdown the server.
-4. Go to (1).
-''';
-  List<int> sizes = await AnalysisServerMemoryUsageTest
-      .start_waitInitialAnalysis_shutdown(
-          roots: <String>[paths.analyzer, paths.analysisServer],
-          numOfRepeats: 3);
-  printMemoryResults(id, description, sizes);
-}
-
-class PathHolder {
-  String analysisServer;
-  String analyzer;
-  String flutterHelloWorld;
-  String flutterStocks;
-
-  PathHolder({String sdkPath, String flutterPath}) {
-    analysisServer = '$sdkPath/pkg/analysis_server';
-    analyzer = '$sdkPath/pkg/analyzer';
-    flutterHelloWorld = '$flutterPath/examples/hello_world';
-    flutterStocks = '$flutterPath/examples/stocks';
-  }
-}
diff --git a/pkg/analysis_server/benchmark/perf/benchmark_scenario.dart b/pkg/analysis_server/benchmark/perf/benchmark_scenario.dart
index aac844b..3ec4c4c 100644
--- a/pkg/analysis_server/benchmark/perf/benchmark_scenario.dart
+++ b/pkg/analysis_server/benchmark/perf/benchmark_scenario.dart
@@ -6,6 +6,7 @@
 
 import 'dart:async';
 import 'dart:io';
+import 'dart:math';
 
 import 'package:analysis_server/plugin/protocol/protocol.dart';
 import 'package:unittest/unittest.dart';
@@ -13,9 +14,11 @@
 import 'performance_tests.dart';
 
 void printBenchmarkResults(String id, String description, List<int> times) {
+  int minTime = times.fold(1 << 20, min);
   String now = new DateTime.now().toUtc().toIso8601String();
   print('$now ========== $id');
   print('times: $times');
+  print('min_time: $minTime');
   print(description.trim());
   print('--------------------');
   print('');
@@ -185,11 +188,19 @@
    */
   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);
+    String updatedContent;
+    if (desc.afterStr != null) {
+      int offset = _indexOfEnd(file, originalContent, desc.afterStr);
+      offset -= desc.afterStrBack;
+      updatedContent = originalContent.substring(0, offset) +
+          desc.insertStr +
+          originalContent.substring(offset);
+    } else if (desc.replaceWhat != null) {
+      int offset = _indexOf(file, originalContent, desc.replaceWhat);
+      updatedContent = originalContent.substring(0, offset) +
+          desc.replaceWith +
+          originalContent.substring(offset + desc.replaceWhat.length);
+    }
     await sendAnalysisUpdateContent(
         {file: new AddContentOverlay(updatedContent)});
     return updatedContent;
@@ -279,9 +290,14 @@
   final String afterStr;
   final int afterStrBack;
   final String insertStr;
+  final String replaceWhat;
+  final String replaceWith;
 
-  FileChange({this.afterStr, this.afterStrBack: 0, this.insertStr}) {
-    expect(afterStr, isNotNull, reason: 'afterStr');
-    expect(insertStr, isNotNull, reason: 'insertStr');
+  FileChange({this.afterStr, this.afterStrBack: 0, this.insertStr, this.replaceWhat, this.replaceWith}) {
+    if (afterStr != null) {
+      expect(insertStr, isNotNull, reason: 'insertStr');
+    } else if (replaceWhat != null) {
+      expect(replaceWith, isNotNull, reason: 'replaceWith');
+    }
   }
 }
diff --git a/pkg/analysis_server/benchmark/perf/memory_tests.dart b/pkg/analysis_server/benchmark/perf/memory_tests.dart
index 8522430..a648344 100644
--- a/pkg/analysis_server/benchmark/perf/memory_tests.dart
+++ b/pkg/analysis_server/benchmark/perf/memory_tests.dart
@@ -5,6 +5,7 @@
 import 'dart:async';
 import 'dart:convert';
 import 'dart:io';
+import 'dart:math';
 
 import 'package:analysis_server/plugin/protocol/protocol.dart';
 import 'package:unittest/unittest.dart';
@@ -12,9 +13,13 @@
 import '../../test/integration/integration_tests.dart';
 
 void printMemoryResults(String id, String description, List<int> sizes) {
+  int minMemory = sizes.fold(sizes.first, min);
+  int maxMemory = sizes.fold(sizes.first, max);
   String now = new DateTime.now().toUtc().toIso8601String();
   print('$now ========== $id');
   print('memory: $sizes');
+  print('min_memory: $minMemory');
+  print('max_memory: $maxMemory');
   print(description.trim());
   print('--------------------');
   print('');
@@ -98,7 +103,7 @@
    *  1. Start Analysis Server.
    *  2. Set the analysis [roots].
    *  3. Wait for analysis to complete.
-   *  4. Record the time to finish analysis.
+   *  4. Record the heap size after analysis is finished.
    *  5. Shutdown.
    *  6. Go to (1).
    */
diff --git a/pkg/analysis_server/benchmark/perf/performance_tests.dart b/pkg/analysis_server/benchmark/perf/performance_tests.dart
index 6d301c9..d6be917 100644
--- a/pkg/analysis_server/benchmark/perf/performance_tests.dart
+++ b/pkg/analysis_server/benchmark/perf/performance_tests.dart
@@ -46,7 +46,7 @@
       expect(serverConnected.isCompleted, isFalse);
       serverConnected.complete();
     });
-    return startServer().then((_) {
+    return startServer(checked: false).then((_) {
       server.listenToOutput(dispatchNotification);
       server.exitCode.then((_) {
         skipShutdown = true;
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 7e695a2..ca87546 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -699,23 +699,6 @@
     return nodes;
   }
 
-// TODO(brianwilkerson) Add the following method after 'prioritySources' has
-// been added to InternalAnalysisContext.
-//  /**
-//   * Return a list containing the full names of all of the sources that are
-//   * priority sources.
-//   */
-//  List<String> getPriorityFiles() {
-//    List<String> priorityFiles = new List<String>();
-//    folderMap.values.forEach((ContextDirectory directory) {
-//      InternalAnalysisContext context = directory.context;
-//      context.prioritySources.forEach((Source source) {
-//        priorityFiles.add(source.fullName);
-//      });
-//    });
-//    return priorityFiles;
-//  }
-
   /**
    * Returns resolved [CompilationUnit]s of the Dart file with the given [path].
    *
@@ -745,6 +728,23 @@
     return units;
   }
 
+// TODO(brianwilkerson) Add the following method after 'prioritySources' has
+// been added to InternalAnalysisContext.
+//  /**
+//   * Return a list containing the full names of all of the sources that are
+//   * priority sources.
+//   */
+//  List<String> getPriorityFiles() {
+//    List<String> priorityFiles = new List<String>();
+//    folderMap.values.forEach((ContextDirectory directory) {
+//      InternalAnalysisContext context = directory.context;
+//      context.prioritySources.forEach((Source source) {
+//        priorityFiles.add(source.fullName);
+//      });
+//    });
+//    return priorityFiles;
+//  }
+
   /**
    * Handle a [request] that was read from the communication channel.
    */
@@ -929,6 +929,32 @@
   }
 
   /**
+   * Schedule cache consistency validation in [context].
+   * The most of the validation must be done asynchronously.
+   */
+  void scheduleCacheConsistencyValidation(AnalysisContext context) {
+    if (context is InternalAnalysisContext) {
+      CacheConsistencyValidator validator = context.cacheConsistencyValidator;
+      List<Source> sources = validator.getSourcesToComputeModificationTimes();
+      // Compute modification times and notify the validator asynchronously.
+      new Future(() async {
+        try {
+          List<int> modificationTimes =
+              await resourceProvider.getModificationTimes(sources);
+          bool cacheInconsistencyFixed = validator
+              .sourceModificationTimesComputed(sources, modificationTimes);
+          if (cacheInconsistencyFixed) {
+            scheduleOperation(new PerformAnalysisOperation(context, false));
+          }
+        } catch (exception, stackTrace) {
+          sendServerErrorNotification(
+              'Failed to check cache consistency', exception, stackTrace);
+        }
+      });
+    }
+  }
+
+  /**
    * Schedules execution of the given [ServerOperation].
    */
   void scheduleOperation(ServerOperation operation) {
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 585da46..347788b 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -625,7 +625,7 @@
     if (analyzer is Map) {
       // Set ignore patterns.
       YamlList exclude = analyzer[AnalyzerOptions.exclude];
-      List<String> excludeList = _toStringList(exclude);
+      List<String> excludeList = toStringList(exclude);
       if (excludeList != null) {
         setIgnorePatternsForContext(info, excludeList);
       }
@@ -1594,25 +1594,6 @@
   }
 
   /**
-   * If all of the elements of [list] are strings, return a list of strings
-   * containing the same elements. Otherwise, return `null`.
-   */
-  List<String> _toStringList(YamlList list) {
-    if (list == null) {
-      return null;
-    }
-    List<String> stringList = <String>[];
-    for (var element in list) {
-      if (element is String) {
-        stringList.add(element);
-      } else {
-        return null;
-      }
-    }
-    return stringList;
-  }
-
-  /**
    * If the given [object] is a map, and all of the keys in the map are strings,
    * return a map containing the same mappings. Otherwise, return `null`.
    */
diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
index 76b27ae..b99cec3 100644
--- a/pkg/analysis_server/lib/src/operation/operation_analysis.dart
+++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
@@ -372,12 +372,7 @@
     List<ChangeNotice> notices = result.changeNotices;
     // nothing to analyze
     if (notices == null) {
-      bool cacheInconsistencyFixed = context.validateCacheConsistency();
-      if (cacheInconsistencyFixed) {
-        server.addOperation(new PerformAnalysisOperation(context, true));
-        return;
-      }
-      // analysis is done
+      server.scheduleCacheConsistencyValidation(context);
       setCacheSize(context, IDLE_CACHE_SIZE);
       server.sendContextAnalysisDoneNotifications(
           context, AnalysisDoneReason.COMPLETE);
diff --git a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart
index bbf9cb5..7e7ae5c 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart
@@ -22,6 +22,13 @@
     if (args.isEmpty) {
       return 0;
     }
+    if (entity == argList.rightParenthesis) {
+      // Parser ignores trailing commas
+      if (argList.rightParenthesis.previous?.lexeme == ',') {
+        return args.length;
+      }
+      return args.length - 1;
+    }
   }
   return null;
 }
diff --git a/pkg/analysis_server/lib/src/search/search_domain.dart b/pkg/analysis_server/lib/src/search/search_domain.dart
index 4a0e1b7..37c58a69 100644
--- a/pkg/analysis_server/lib/src/search/search_domain.dart
+++ b/pkg/analysis_server/lib/src/search/search_domain.dart
@@ -118,6 +118,15 @@
   Future findTopLevelDeclarations(protocol.Request request) async {
     var params =
         new protocol.SearchFindTopLevelDeclarationsParams.fromRequest(request);
+    try {
+      // validate the regex
+      new RegExp(params.pattern);
+    } on FormatException catch (exception) {
+      server.sendResponse(new protocol.Response.invalidParameter(
+          request, 'pattern', exception.message));
+      return;
+    }
+
     await server.onAnalysisComplete;
     // respond
     String searchId = (_nextSearchId++).toString();
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
index f29e7a6..3b26f60 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
@@ -19,6 +19,12 @@
 int _argCount(DartCompletionRequest request) {
   AstNode node = request.target.containingNode;
   if (node is ArgumentList) {
+    if (request.target.entity == node.rightParenthesis) {
+      // Parser ignores trailing commas
+      if (node.rightParenthesis.previous?.lexeme == ',') {
+        return node.arguments.length + 1;
+      }
+    }
     return node.arguments.length;
   }
   return 0;
@@ -96,12 +102,15 @@
 }
 
 /**
- * Determine if the completion target is an emtpy argument list.
+ * Return `true` if the [request] is inside of a [NamedExpression] name.
  */
-bool _isEmptyArgList(DartCompletionRequest request) {
-  AstNode node = request.target.containingNode;
-  return node is ArgumentList &&
-      node.leftParenthesis.next == node.rightParenthesis;
+bool _isInNamedExpression(DartCompletionRequest request) {
+  Object entity = request.target.entity;
+  if (entity is NamedExpression) {
+    Label name = entity.name;
+    return name.offset < request.offset && request.offset < name.end;
+  }
+  return false;
 }
 
 /**
@@ -217,61 +226,30 @@
     return EMPTY_LIST;
   }
 
-  void _addArgListSuggestion(Iterable<ParameterElement> requiredParam) {
-    // DEPRECATED... argument lists are no longer suggested.
-    // See https://github.com/dart-lang/sdk/issues/25197
-
-    // String _getParamType(ParameterElement param) {
-    //   DartType type = param.type;
-    //   if (type != null) {
-    //     return type.displayName;
-    //   }
-    //   return 'dynamic';
-    // }
-
-    // StringBuffer completion = new StringBuffer('(');
-    // List<String> paramNames = new List<String>();
-    // List<String> paramTypes = new List<String>();
-    // for (ParameterElement param in requiredParam) {
-    //   String name = param.name;
-    //   if (name != null && name.length > 0) {
-    //     if (completion.length > 1) {
-    //       completion.write(', ');
-    //     }
-    //     completion.write(name);
-    //     paramNames.add(name);
-    //     paramTypes.add(_getParamType(param));
-    //   }
-    // }
-    // completion.write(')');
-    // CompletionSuggestion suggestion = new CompletionSuggestion(
-    //     CompletionSuggestionKind.ARGUMENT_LIST,
-    //     DART_RELEVANCE_HIGH,
-    //     completion.toString(),
-    //     completion.length,
-    //     0,
-    //     false,
-    //     false);
-    // suggestion.parameterNames = paramNames;
-    // suggestion.parameterTypes = paramTypes;
-    // suggestions.add(suggestion);
-  }
-
   void _addDefaultParamSuggestions(Iterable<ParameterElement> parameters,
       [bool appendComma = false]) {
+    bool appendColon = !_isInNamedExpression(request);
     Iterable<String> namedArgs = _namedArgs(request);
     for (ParameterElement param in parameters) {
       if (param.parameterKind == ParameterKind.NAMED) {
         _addNamedParameterSuggestion(request, namedArgs, param.name,
-            param.type?.displayName, appendComma);
+            param.type?.displayName, appendColon, appendComma);
       }
     }
   }
 
-  void _addNamedParameterSuggestion(DartCompletionRequest request,
-      List<String> namedArgs, String name, String paramType, bool appendComma) {
+  void _addNamedParameterSuggestion(
+      DartCompletionRequest request,
+      List<String> namedArgs,
+      String name,
+      String paramType,
+      bool appendColon,
+      bool appendComma) {
     if (name != null && name.length > 0 && !namedArgs.contains(name)) {
-      String completion = '$name: ';
+      String completion = name;
+      if (appendColon) {
+        completion += ': ';
+      }
       if (appendComma) {
         completion += ',';
       }
@@ -295,10 +273,6 @@
     Iterable<ParameterElement> requiredParam = parameters.where(
         (ParameterElement p) => p.parameterKind == ParameterKind.REQUIRED);
     int requiredCount = requiredParam.length;
-    if (requiredCount > 0 && _isEmptyArgList(request)) {
-      _addArgListSuggestion(requiredParam);
-      return;
-    }
     // TODO (jwren) _isAppendingToArgList can be split into two cases (with and
     // without preceded), then _isAppendingToArgList,
     // _isInsertingToArgListWithNoSynthetic and
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 917542c..132c823 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/optype.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/optype.dart
@@ -184,8 +184,19 @@
         if (elem is FunctionTypedElement) {
           List<ParameterElement> parameters = elem.parameters;
           if (parameters != null) {
-            int index =
-                node.arguments.isEmpty ? 0 : node.arguments.indexOf(entity);
+            int index;
+            if (node.arguments.isEmpty) {
+              index = 0;
+            } else if (entity == node.rightParenthesis) {
+              // Parser ignores trailing commas
+              if (node.rightParenthesis.previous?.lexeme == ',') {
+                index = node.arguments.length;
+              } else {
+                index = node.arguments.length - 1;
+              }
+            } else {
+              index = node.arguments.indexOf(entity);
+            }
             if (0 <= index && index < parameters.length) {
               ParameterElement param = parameters[index];
               if (param?.parameterKind == ParameterKind.NAMED) {
diff --git a/pkg/analysis_server/lib/src/services/correction/assist.dart b/pkg/analysis_server/lib/src/services/correction/assist.dart
index 2024b75..2bcf316 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist.dart
@@ -89,6 +89,10 @@
       'CONVERT_INTO_EXPRESSION_BODY', 30, "Convert into expression body");
   static const CONVERT_INTO_FOR_INDEX = const AssistKind(
       'CONVERT_INTO_FOR_INDEX', 30, "Convert into for-index loop");
+  static const CONVERT_INTO_FINAL_FIELD = const AssistKind(
+      'CONVERT_INTO_FINAL_FIELD', 30, "Convert into final field");
+  static const CONVERT_INTO_GETTER =
+      const AssistKind('CONVERT_INTO_GETTER', 30, "Convert into getter");
   static const CONVERT_INTO_IS_NOT =
       const AssistKind('CONVERT_INTO_IS_NOT', 30, "Convert into is!");
   static const CONVERT_INTO_IS_NOT_EMPTY = const AssistKind(
diff --git a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
index f58469d..1ae3201 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -97,6 +97,8 @@
     _addProposal_addTypeAnnotation_SimpleFormalParameter();
     _addProposal_addTypeAnnotation_VariableDeclaration();
     _addProposal_assignToLocalVariable();
+    _addProposal_convertIntoFinalField();
+    _addProposal_convertIntoGetter();
     _addProposal_convertDocumentationIntoBlock();
     _addProposal_convertDocumentationIntoLine();
     _addProposal_convertToBlockFunctionBody();
@@ -481,6 +483,113 @@
     _addAssist(DartAssistKind.CONVERT_DOCUMENTATION_INTO_LINE, []);
   }
 
+  void _addProposal_convertIntoFinalField() {
+    // Find the enclosing getter.
+    MethodDeclaration getter;
+    for (AstNode n = node; n != null; n = n.parent) {
+      if (n is MethodDeclaration) {
+        getter = n;
+        break;
+      }
+      if (n is SimpleIdentifier || n is TypeName || n is TypeArgumentList) {
+        continue;
+      }
+      break;
+    }
+    if (getter == null || !getter.isGetter) {
+      return;
+    }
+    // Check that there is no corresponding setter.
+    {
+      ExecutableElement element = getter.element;
+      if (element == null) {
+        return;
+      }
+      Element enclosing = element.enclosingElement;
+      if (enclosing is ClassElement) {
+        if (enclosing.getSetter(element.name) != null) {
+          return;
+        }
+      }
+    }
+    // Try to find the returned expression.
+    Expression expression;
+    {
+      FunctionBody body = getter.body;
+      if (body is ExpressionFunctionBody) {
+        expression = body.expression;
+      } else if (body is BlockFunctionBody) {
+        List<Statement> statements = body.block.statements;
+        if (statements.length == 1) {
+          Statement statement = statements.first;
+          if (statement is ReturnStatement) {
+            expression = statement.expression;
+          }
+        }
+      }
+    }
+    // Use the returned expression as the field initializer.
+    if (expression != null) {
+      AstNode beginNodeToReplace = getter.name;
+      String code = 'final';
+      if (getter.returnType != null) {
+        beginNodeToReplace = getter.returnType;
+        code += ' ' + _getNodeText(getter.returnType);
+      }
+      code += ' ' + _getNodeText(getter.name);
+      if (expression is! NullLiteral) {
+        code += ' = ' + _getNodeText(expression);
+      }
+      code += ';';
+      _addReplaceEdit(rangeStartEnd(beginNodeToReplace, getter), code);
+      _addAssist(DartAssistKind.CONVERT_INTO_FINAL_FIELD, []);
+    }
+  }
+
+  void _addProposal_convertIntoGetter() {
+    // Find the enclosing field declaration.
+    FieldDeclaration fieldDeclaration;
+    for (AstNode n = node; n != null; n = n.parent) {
+      if (n is FieldDeclaration) {
+        fieldDeclaration = n;
+        break;
+      }
+      if (n is SimpleIdentifier ||
+          n is VariableDeclaration ||
+          n is VariableDeclarationList ||
+          n is TypeName ||
+          n is TypeArgumentList) {
+        continue;
+      }
+      break;
+    }
+    if (fieldDeclaration == null) {
+      return;
+    }
+    // The field must be final and has only one variable.
+    VariableDeclarationList fieldList = fieldDeclaration.fields;
+    if (!fieldList.isFinal || fieldList.variables.length != 1) {
+      return;
+    }
+    VariableDeclaration field = fieldList.variables.first;
+    // Prepare the initializer.
+    Expression initializer = field.initializer;
+    if (initializer == null) {
+      return;
+    }
+    // Add proposal.
+    String code = '';
+    if (fieldList.type != null) {
+      code += _getNodeText(fieldList.type) + ' ';
+    }
+    code += 'get';
+    code += ' ' + _getNodeText(field.name);
+    code += ' => ' + _getNodeText(initializer);
+    code += ';';
+    _addReplaceEdit(rangeStartEnd(fieldList.keyword, fieldDeclaration), code);
+    _addAssist(DartAssistKind.CONVERT_INTO_GETTER, []);
+  }
+
   void _addProposal_convertToBlockFunctionBody() {
     FunctionBody body = getEnclosingFunctionBody();
     // prepare expression body
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 117884d..4daa06e 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -293,17 +293,17 @@
       _addFix_updateConstructor_forUninitializedFinalFields();
     }
     if (errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER) {
-      bool isAsync = _addFix_addAsync();
-      if (!isAsync) {
-        _addFix_undefinedClassAccessor_useSimilar();
-        _addFix_createClass();
-        _addFix_createField();
-        _addFix_createGetter();
-        _addFix_createFunction_forFunctionType();
-        _addFix_importLibrary_withType();
-        _addFix_importLibrary_withTopLevelVariable();
-        _addFix_createLocalVariable();
-      }
+      _addFix_undefinedClassAccessor_useSimilar();
+      _addFix_createClass();
+      _addFix_createField();
+      _addFix_createGetter();
+      _addFix_createFunction_forFunctionType();
+      _addFix_importLibrary_withType();
+      _addFix_importLibrary_withTopLevelVariable();
+      _addFix_createLocalVariable();
+    }
+    if (errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT) {
+      _addFix_addAsync();
     }
     if (errorCode == StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE) {
       _addFix_illegalAsyncReturnType();
@@ -371,8 +371,8 @@
     doSourceChange_addElementEdit(change, target, edit);
   }
 
-  void _addFix(FixKind kind, List args) {
-    if (change.edits.isEmpty) {
+  void _addFix(FixKind kind, List args, {bool importsOnly: false}) {
+    if (change.edits.isEmpty && !importsOnly) {
       return;
     }
     // configure Change
@@ -397,14 +397,12 @@
    */
   bool _addFix_addAsync() {
     AstNode node = this.node;
-    if (_isAwaitNode()) {
-      FunctionBody body = node.getAncestor((n) => n is FunctionBody);
-      if (body != null && body.keyword == null) {
-        _addReplaceEdit(rf.rangeStartLength(body, 0), 'async ');
-        _replaceReturnTypeWithFuture(body);
-        _addFix(DartFixKind.ADD_ASYNC, []);
-        return true;
-      }
+    FunctionBody body = node.getAncestor((n) => n is FunctionBody);
+    if (body != null && body.keyword == null) {
+      _addReplaceEdit(rf.rangeStartLength(body, 0), 'async ');
+      _replaceReturnTypeWithFuture(body);
+      _addFix(DartFixKind.ADD_ASYNC, []);
+      return true;
     }
     return false;
   }
@@ -1349,7 +1347,10 @@
       sb.append(prefix);
     }
     // return type
-    _appendType(sb, element.type.returnType);
+    if (!isSetter) {
+      _appendType(sb, element.type.returnType);
+    }
+    // keyword
     if (isGetter) {
       sb.append('get ');
     } else if (isSetter) {
@@ -1424,40 +1425,11 @@
     _addFix(DartFixKind.REPLACE_RETURN_TYPE_FUTURE, []);
   }
 
-  void _addFix_importLibrary(FixKind kind, String importPath) {
-    CompilationUnitElement libraryUnitElement =
-        unitLibraryElement.definingCompilationUnit;
-    CompilationUnit libraryUnit = getParsedUnit(libraryUnitElement);
-    // prepare new import location
-    int offset = 0;
-    String prefix;
-    String suffix;
-    {
-      // if no directives
-      prefix = '';
-      suffix = eol;
-      CorrectionUtils libraryUtils = new CorrectionUtils(libraryUnit);
-      // after last directive in library
-      for (Directive directive in libraryUnit.directives) {
-        if (directive is LibraryDirective || directive is ImportDirective) {
-          offset = directive.end;
-          prefix = eol;
-          suffix = '';
-        }
-      }
-      // if still beginning of file, skip shebang and line comments
-      if (offset == 0) {
-        CorrectionUtils_InsertDesc desc = libraryUtils.getInsertDescTop();
-        offset = desc.offset;
-        prefix = desc.prefix;
-        suffix = '${desc.suffix}$eol';
-      }
-    }
-    // insert new import
-    String importSource = "${prefix}import '$importPath';$suffix";
-    _addInsertEdit(offset, importSource, libraryUnitElement);
-    // add proposal
-    _addFix(kind, [importPath]);
+  void _addFix_importLibrary(FixKind kind, LibraryElement libraryElement) {
+    librariesToImport.add(libraryElement);
+    Source librarySource = libraryElement.source;
+    String libraryUri = getLibrarySourceUri(unitLibraryElement, librarySource);
+    _addFix(kind, [libraryUri], importsOnly: true);
   }
 
   void _addFix_importLibrary_withElement(String name, ElementKind kind) {
@@ -1544,7 +1516,7 @@
           continue;
         }
         // add import
-        _addFix_importLibrary(DartFixKind.IMPORT_LIBRARY_SDK, libraryUri);
+        _addFix_importLibrary(DartFixKind.IMPORT_LIBRARY_SDK, libraryElement);
       }
     }
     // check project libraries
@@ -1576,21 +1548,8 @@
         if (element.kind != kind) {
           continue;
         }
-        // prepare "library" file
-        String libraryFile = librarySource.fullName;
-        // may be "package:" URI
-        {
-          String libraryPackageUri = findNonFileUri(context, libraryFile);
-          if (libraryPackageUri != null) {
-            _addFix_importLibrary(
-                DartFixKind.IMPORT_LIBRARY_PROJECT, libraryPackageUri);
-            continue;
-          }
-        }
-        // relative URI
-        String relativeFile = relative(libraryFile, from: unitLibraryFolder);
-        relativeFile = split(relativeFile).join('/');
-        _addFix_importLibrary(DartFixKind.IMPORT_LIBRARY_PROJECT, relativeFile);
+        _addFix_importLibrary(
+            DartFixKind.IMPORT_LIBRARY_PROJECT, libraryElement);
       }
     }
   }
diff --git a/pkg/analysis_server/lib/src/services/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart
index 551964a..445aab2 100644
--- a/pkg/analysis_server/lib/src/services/correction/util.dart
+++ b/pkg/analysis_server/lib/src/services/correction/util.dart
@@ -33,38 +33,91 @@
     Set<LibraryElement> libraries) {
   CompilationUnitElement libUnitElement = targetLibrary.definingCompilationUnit;
   CompilationUnit libUnit = getParsedUnit(libUnitElement);
-  // prepare new import location
-  int offset = 0;
-  String prefix;
-  String suffix;
-  {
-    // if no directives
-    prefix = '';
-    CorrectionUtils libraryUtils = new CorrectionUtils(libUnit);
-    String eol = libraryUtils.endOfLine;
-    suffix = eol;
-    // after last directive in library
-    for (Directive directive in libUnit.directives) {
-      if (directive is LibraryDirective || directive is ImportDirective) {
-        offset = directive.end;
-        prefix = eol;
-        suffix = '';
-      }
-    }
-    // if still at the beginning of the file, skip shebang and line comments
-    if (offset == 0) {
-      CorrectionUtils_InsertDesc desc = libraryUtils.getInsertDescTop();
-      offset = desc.offset;
-      prefix = desc.prefix;
-      suffix = desc.suffix + eol;
+  CorrectionUtils libUtils = new CorrectionUtils(libUnit);
+  String eol = libUtils.endOfLine;
+  // Prepare information about existing imports.
+  LibraryDirective libraryDirective;
+  List<_ImportDirectiveInfo> importDirectives = <_ImportDirectiveInfo>[];
+  for (Directive directive in libUnit.directives) {
+    if (directive is LibraryDirective) {
+      libraryDirective = directive;
+    } else if (directive is ImportDirective) {
+      importDirectives.add(new _ImportDirectiveInfo(
+          directive.uriContent, directive.offset, directive.end));
     }
   }
-  // insert imports
-  for (LibraryElement library in libraries) {
-    String importPath = getLibrarySourceUri(targetLibrary, library.source);
-    String importCode = "${prefix}import '$importPath';$suffix";
-    doSourceChange_addElementEdit(
-        change, targetLibrary, new SourceEdit(offset, 0, importCode));
+
+  // Prepare all URIs to import.
+  List<String> uriList = libraries
+      .map((library) => getLibrarySourceUri(targetLibrary, library.source))
+      .toList();
+  uriList.sort((a, b) => a.compareTo(b));
+
+  // Insert imports: between existing imports.
+  if (importDirectives.isNotEmpty) {
+    bool isFirstPackage = true;
+    for (String importUri in uriList) {
+      bool inserted = false;
+      bool isPackage = importUri.startsWith('package:');
+      bool isAfterDart = false;
+      for (_ImportDirectiveInfo existingImport in importDirectives) {
+        if (existingImport.uri.startsWith('dart:')) {
+          isAfterDart = true;
+        }
+        if (existingImport.uri.startsWith('package:')) {
+          isFirstPackage = false;
+        }
+        if (importUri.compareTo(existingImport.uri) < 0) {
+          String importCode = "import '$importUri';$eol";
+          doSourceChange_addElementEdit(change, targetLibrary,
+              new SourceEdit(existingImport.offset, 0, importCode));
+          inserted = true;
+          break;
+        }
+      }
+      if (!inserted) {
+        String importCode = "${eol}import '$importUri';";
+        if (isPackage && isFirstPackage && isAfterDart) {
+          importCode = eol + importCode;
+        }
+        doSourceChange_addElementEdit(change, targetLibrary,
+            new SourceEdit(importDirectives.last.end, 0, importCode));
+      }
+      if (isPackage) {
+        isFirstPackage = false;
+      }
+    }
+    return;
+  }
+
+  // Insert imports: after the library directive.
+  if (libraryDirective != null) {
+    String prefix = eol + eol;
+    for (String importUri in uriList) {
+      String importCode = "${prefix}import '$importUri';";
+      prefix = eol;
+      doSourceChange_addElementEdit(change, targetLibrary,
+          new SourceEdit(libraryDirective.end, 0, importCode));
+    }
+    return;
+  }
+
+  // If still at the beginning of the file, skip shebang and line comments.
+  {
+    CorrectionUtils_InsertDesc desc = libUtils.getInsertDescTop();
+    int offset = desc.offset;
+    for (int i = 0; i < uriList.length; i++) {
+      String importUri = uriList[i];
+      String importCode = "import '$importUri';$eol";
+      if (i == 0) {
+        importCode = desc.prefix + importCode;
+      }
+      if (i == uriList.length - 1) {
+        importCode = importCode + desc.suffix;
+      }
+      doSourceChange_addElementEdit(
+          change, targetLibrary, new SourceEdit(offset, 0, importCode));
+    }
   }
 }
 
@@ -1466,6 +1519,14 @@
   }
 }
 
+class _ImportDirectiveInfo {
+  final String uri;
+  final int offset;
+  final int end;
+
+  _ImportDirectiveInfo(this.uri, this.offset, this.end);
+}
+
 /**
  * A container with a source and its precedence.
  */
diff --git a/pkg/analysis_server/lib/src/services/search/hierarchy.dart b/pkg/analysis_server/lib/src/services/search/hierarchy.dart
index c6b552f..b6e1c9e 100644
--- a/pkg/analysis_server/lib/src/services/search/hierarchy.dart
+++ b/pkg/analysis_server/lib/src/services/search/hierarchy.dart
@@ -76,8 +76,8 @@
 Future<Set<ClassMemberElement>> getHierarchyMembers(
     SearchEngine searchEngine, ClassMemberElement member) {
   Set<ClassMemberElement> result = new HashSet<ClassMemberElement>();
-  // constructor
-  if (member is ConstructorElement) {
+  // static elements
+  if (member.isStatic || member is ConstructorElement) {
     result.add(member);
     return new Future.value(result);
   }
diff --git a/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart b/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
index 2d6f815..47eb392 100644
--- a/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
+++ b/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
@@ -35,7 +35,8 @@
   }
 
   @override
-  Future<List<SearchMatch>> searchMemberDeclarations(String pattern) {
+  Future<List<SearchMatch>> searchMemberDeclarations(String name) {
+    String pattern = '^$name\$';
     return _searchDefinedNames(pattern, IndexNameKind.classMember);
   }
 
diff --git a/pkg/analysis_server/lib/src/status/get_handler.dart b/pkg/analysis_server/lib/src/status/get_handler.dart
index 0e9a2ed..13a149a 100644
--- a/pkg/analysis_server/lib/src/status/get_handler.dart
+++ b/pkg/analysis_server/lib/src/status/get_handler.dart
@@ -21,6 +21,7 @@
 import 'package:analysis_server/src/socket_server.dart';
 import 'package:analysis_server/src/status/ast_writer.dart';
 import 'package:analysis_server/src/status/element_writer.dart';
+import 'package:analysis_server/src/status/memory_use.dart';
 import 'package:analysis_server/src/status/validator.dart';
 import 'package:analysis_server/src/utilities/average.dart';
 import 'package:analyzer/dart/ast/ast.dart';
@@ -258,6 +259,11 @@
   static const String ELEMENT_PATH = '/element';
 
   /**
+   * The path used to request an analysis of the memory use of the analyzer.
+   */
+  static const String MEMORY_USE_PATH = '/memoryUse';
+
+  /**
    * The path used to request an overlay contents.
    */
   static const String OVERLAY_PATH = '/overlay';
@@ -390,6 +396,8 @@
       _returnDiagnosticInfo(request);
     } else if (path == ELEMENT_PATH) {
       _returnElement(request);
+    } else if (path == MEMORY_USE_PATH) {
+      _returnMemoryUsage(request);
     } else if (path == OVERLAY_PATH) {
       _returnOverlayContents(request);
     } else if (path == OVERLAYS_PATH) {
@@ -812,6 +820,30 @@
                 classes: [null, "right"]);
           }
           buffer.write('</table>');
+
+          {
+            buffer.write('<p><b>Cache consistency statistics</b></p>');
+            buffer.write(
+                '<table style="border-collapse: separate; border-spacing: 10px 5px;">');
+            _writeRow(buffer, ['Name', 'Count'], header: true);
+            _writeRow(buffer, [
+              'Modified',
+              PerformanceStatistics
+                  .cacheConsistencyValidationStatistics.numOfModified
+            ], classes: [
+              null,
+              "right"
+            ]);
+            _writeRow(buffer, [
+              'Deleted',
+              PerformanceStatistics
+                  .cacheConsistencyValidationStatistics.numOfDeleted
+            ], classes: [
+              null,
+              "right"
+            ]);
+            buffer.write('</table>');
+          }
         }, (StringBuffer buffer) {
           //
           // Write task model timing information.
@@ -1620,6 +1652,84 @@
     });
   }
 
+  void _returnMemoryUsage(HttpRequest request) {
+    _writeResponse(request, (StringBuffer buffer) {
+      _writePage(buffer, 'Analysis Server - Memory Use', [],
+          (StringBuffer buffer) {
+        AnalysisServer server = _server.analysisServer;
+        MemoryUseData data = new MemoryUseData();
+        data.processAnalysisServer(server);
+        Map<Type, Set> instances = data.instances;
+        List<Type> instanceTypes = instances.keys.toList();
+        instanceTypes.sort((Type left, Type right) =>
+            left.toString().compareTo(right.toString()));
+        Map<Type, Set> ownerMap = data.ownerMap;
+        List<Type> ownerTypes = ownerMap.keys.toList();
+        ownerTypes.sort((Type left, Type right) =>
+            left.toString().compareTo(right.toString()));
+
+        _writeTwoColumns(buffer, (StringBuffer buffer) {
+          buffer.write('<h3>Instance Counts (reachable from contexts)</h3>');
+          buffer.write('<table>');
+          _writeRow(buffer, ['Count', 'Class name'], header: true);
+          instanceTypes.forEach((Type type) {
+            _writeRow(buffer, [instances[type].length, type],
+                classes: ['right', null]);
+          });
+          buffer.write('</table>');
+
+          buffer.write(
+              '<h3>Ownership (which classes of objects hold on to others)</h3>');
+          buffer.write('<table>');
+          _writeRow(buffer, ['Referenced Type', 'Referencing Types'],
+              header: true);
+          ownerTypes.forEach((Type type) {
+            List<String> referencingTypes =
+                ownerMap[type].map((Type type) => type.toString()).toList();
+            referencingTypes.sort();
+            _writeRow(buffer, [type, referencingTypes.join('<br>')]);
+          });
+          buffer.write('</table>');
+
+          buffer.write('<h3>Other Data</h3>');
+          buffer.write('<p>');
+          buffer.write(data.uniqueTargetedResults.length);
+          buffer.write(' non-equal TargetedResults</p>');
+          buffer.write('<p>');
+          buffer.write(data.uniqueLSUs.length);
+          buffer.write(' non-equal LibrarySpecificUnits</p>');
+          int count = data.mismatchedTargets.length;
+          buffer.write('<p>');
+          buffer.write(count);
+          buffer.write(' mismatched targets</p>');
+          if (count < 100) {
+            for (AnalysisTarget target in data.mismatchedTargets) {
+              buffer.write(target);
+              buffer.write('<br>');
+            }
+          }
+        }, (StringBuffer buffer) {
+          void writeCountMap(String title, Map<Type, int> counts) {
+            List<Type> classNames = counts.keys.toList();
+            classNames.sort((Type left, Type right) =>
+                left.toString().compareTo(right.toString()));
+
+            buffer.write('<h3>$title</h3>');
+            buffer.write('<table>');
+            _writeRow(buffer, ['Count', 'Class name'], header: true);
+            classNames.forEach((Type type) {
+              _writeRow(buffer, [counts[type], type], classes: ['right', null]);
+            });
+            buffer.write('</table>');
+          }
+          writeCountMap('Directly Held AST Nodes', data.directNodeCounts);
+          writeCountMap('Indirectly Held AST Nodes', data.indirectNodeCounts);
+          writeCountMap('Directly Held Elements', data.elementCounts);
+        });
+      });
+    });
+  }
+
   void _returnOverlayContents(HttpRequest request) {
     String path = request.requestedUri.queryParameters[PATH_PARAM];
     if (path == null) {
@@ -2204,6 +2314,7 @@
     int length = keys.length;
     buffer.write('{');
     for (int i = 0; i < length; i++) {
+      buffer.write('<br>');
       String key = keys[i];
       if (i > 0) {
         buffer.write(', ');
@@ -2212,7 +2323,7 @@
       buffer.write(' = ');
       buffer.write(map[key]);
     }
-    buffer.write('}');
+    buffer.write('<br>}');
   }
 
   /**
@@ -2265,6 +2376,8 @@
         'table.column {border: 0px solid black; width: 100%; table-layout: fixed;}');
     buffer.write('td.column {vertical-align: top; width: 50%;}');
     buffer.write('td.right {text-align: right;}');
+    buffer.write('th {text-align: left; vertical-align:top;}');
+    buffer.write('tr {vertical-align:top;}');
     buffer.write('</style>');
     buffer.write('</head>');
 
@@ -2423,6 +2536,9 @@
       buffer.write('<p>');
       buffer.write(makeLink(DIAGNOSTIC_PATH, {}, 'General diagnostics'));
       buffer.write('</p>');
+      buffer.write('<p>');
+      buffer.write(makeLink(MEMORY_USE_PATH, {}, 'Memory usage'));
+      buffer.write(' <small>(long running)</small></p>');
     }, (StringBuffer buffer) {
       _writeSubscriptionList(buffer, ServerService.VALUES, services);
     });
diff --git a/pkg/analysis_server/lib/src/status/memory_use.dart b/pkg/analysis_server/lib/src/status/memory_use.dart
new file mode 100644
index 0000000..92657bc
--- /dev/null
+++ b/pkg/analysis_server/lib/src/status/memory_use.dart
@@ -0,0 +1,314 @@
+// 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 analysis_server.src.status.memory_use;
+
+import 'dart:collection';
+
+import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/visitor.dart';
+import 'package:analyzer/src/context/cache.dart';
+import 'package:analyzer/src/context/context.dart' show AnalysisContextImpl;
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/task/dart.dart';
+import 'package:analyzer/task/model.dart';
+
+/**
+ * A visitor that will count the number of instances of each type of AST node.
+ */
+class AstNodeCounter extends UnifyingAstVisitor<Null> {
+  /**
+   * A table mapping the types of the AST nodes to the number of instances
+   * visited.
+   */
+  final Map<Type, int> nodeCounts;
+
+  /**
+   * Initialize a newly created counter to increment the counts in the given map
+   * of [nodeCounts].
+   */
+  AstNodeCounter(this.nodeCounts);
+
+  @override
+  visitNode(AstNode node) {
+    Type type = node.runtimeType;
+    int count = nodeCounts[type] ?? 0;
+    nodeCounts[type] = count + 1;
+    super.visitNode(node);
+  }
+}
+
+/**
+ * A visitor that will count the number of instances of each type of element.
+ */
+class ElementCounter extends GeneralizingElementVisitor<Null> {
+  /**
+   * A table mapping the types of the elements to the number of instances
+   * visited.
+   */
+  final Map<Type, int> elementCounts;
+
+  /**
+   * A table mapping the types of the AST nodes to the number of instances
+   * visited.
+   */
+  final Map<Type, int> nodeCounts;
+
+  /**
+   * Initialize a newly created counter to increment the counts in the given map
+   * of [elementCounts].
+   */
+  ElementCounter(this.elementCounts, this.nodeCounts);
+
+  @override
+  visitConstructorElement(ConstructorElement element) {
+    if (element is ConstructorElementImpl) {
+      List<ConstructorInitializer> initializers = element.constantInitializers;
+      if (initializers != null) {
+        initializers.forEach((ConstructorInitializer initializer) {
+          _countNodes(initializer);
+        });
+      }
+    }
+    visitElement(element);
+  }
+
+  @override
+  visitElement(Element element) {
+    Type type = element.runtimeType;
+    int count = elementCounts[type] ?? 0;
+    elementCounts[type] = count + 1;
+    element.metadata.forEach((ElementAnnotation annotation) {
+      if (annotation is ElementAnnotationImpl) {
+        _countNodes(annotation.annotationAst);
+      }
+    });
+    super.visitElement(element);
+  }
+
+  visitFieldElement(FieldElement element) {
+    if (element is ConstVariableElement) {
+      _countInitializer(element as ConstVariableElement);
+    }
+    visitElement(element);
+  }
+
+  visitLocalVariableElement(LocalVariableElement element) {
+    if (element is ConstVariableElement) {
+      _countInitializer(element as ConstVariableElement);
+    }
+    visitElement(element);
+  }
+
+  visitParameterElement(ParameterElement element) {
+    if (element is ConstVariableElement) {
+      _countInitializer(element as ConstVariableElement);
+    }
+    visitElement(element);
+  }
+
+  visitTopLevelVariableElement(TopLevelVariableElement element) {
+    if (element is ConstVariableElement) {
+      _countInitializer(element as ConstVariableElement);
+    }
+    visitElement(element);
+  }
+
+  void _countInitializer(ConstVariableElement element) {
+    _countNodes(element.constantInitializer);
+  }
+
+  void _countNodes(AstNode node) {
+    if (node != null) {
+      node.accept(new AstNodeCounter(nodeCounts));
+    }
+  }
+}
+
+/**
+ * A set used when the number of instances of some type is too large to be kept.
+ */
+class InfiniteSet implements Set {
+  /**
+   * The unique instance of this class.
+   */
+  static final InfiniteSet instance = new InfiniteSet();
+
+  @override
+  int get length => -1;
+
+  @override
+  dynamic noSuchMethod(Invocation invocation) {
+    throw new UnsupportedError('Do not use instances of InfiniteSet');
+  }
+}
+
+/**
+ * Computes memory usage data by traversing the data structures reachable from
+ * an analysis server.
+ */
+class MemoryUseData {
+  /**
+   * The maximum size of an instance set.
+   */
+  static const int maxInstanceSetSize = 1000000;
+
+  /**
+   * A table mapping classes to instances of the class.
+   */
+  Map<Type, Set> instances = new HashMap<Type, Set>();
+
+  /**
+   * A table mapping classes to the classes of objects from which they were
+   * reached.
+   */
+  Map<Type, Set<Type>> ownerMap = new HashMap<Type, Set<Type>>();
+
+  /**
+   * A set of all the library specific units, using equality rather than
+   * identity in order to determine whether re-using equal instances would save
+   * significant space.
+   */
+  Set<LibrarySpecificUnit> uniqueLSUs = new HashSet<LibrarySpecificUnit>();
+
+  /**
+   * A set of all the targeted results, using equality rather than identity in
+   * order to determine whether re-using equal instances would save significant
+   * space.
+   */
+  Set<TargetedResult> uniqueTargetedResults = new HashSet<TargetedResult>();
+
+  /**
+   * A set containing all of the analysis targets for which the key in the
+   * cache partition is not the same instance as the target stored in the entry.
+   */
+  Set<AnalysisTarget> mismatchedTargets = new HashSet<AnalysisTarget>();
+
+  /**
+   * A table mapping the types of AST nodes to the number of instances being
+   * held directly (as values in the cache).
+   */
+  Map<Type, int> directNodeCounts = new HashMap<Type, int>();
+
+  /**
+   * A table mapping the types of AST nodes to the number of instances being
+   * held indirectly (such as nodes reachable from element models).
+   */
+  Map<Type, int> indirectNodeCounts = new HashMap<Type, int>();
+
+  /**
+   * A table mapping the types of the elements to the number of instances being
+   * held directly (as values in the cache).
+   */
+  final Map<Type, int> elementCounts = new HashMap<Type, int>();
+
+  /**
+   * Initialize a newly created instance.
+   */
+  MemoryUseData();
+
+  /**
+   * Traverse an analysis [server] to compute memory usage data.
+   */
+  void processAnalysisServer(AnalysisServer server) {
+    _recordInstance(server, null);
+    Iterable<AnalysisContext> contexts = server.analysisContexts;
+    for (AnalysisContextImpl context in contexts) {
+      _processAnalysisContext(context, server);
+    }
+    DartSdkManager manager = server.sdkManager;
+    List<SdkDescription> descriptors = manager.sdkDescriptors;
+    for (SdkDescription descriptor in descriptors) {
+      _processAnalysisContext(
+          manager.getSdk(descriptor, () => null).context, manager);
+    }
+  }
+
+  void _processAnalysisContext(AnalysisContextImpl context, Object owner) {
+    _recordInstance(context, owner);
+    _recordInstance(context.analysisCache, context);
+    CachePartition partition = context.privateAnalysisCachePartition;
+    Map<AnalysisTarget, CacheEntry> map = partition.entryMap;
+    map.forEach((AnalysisTarget target, CacheEntry entry) {
+      _processAnalysisTarget(target, partition);
+      _processCacheEntry(entry, partition);
+      if (!identical(entry.target, target)) {
+        mismatchedTargets.add(target);
+      }
+    });
+  }
+
+  void _processAnalysisTarget(AnalysisTarget target, Object owner) {
+    _recordInstance(target, owner);
+  }
+
+  void _processCacheEntry(CacheEntry entry, Object owner) {
+    _recordInstance(entry, owner);
+    List<ResultDescriptor> descriptors = entry.nonInvalidResults;
+    for (ResultDescriptor descriptor in descriptors) {
+      _recordInstance(descriptor, entry);
+      _processResultData(entry.getResultDataOrNull(descriptor), entry);
+    }
+  }
+
+  void _processResultData(ResultData resultData, Object owner) {
+    _recordInstance(resultData, owner);
+    if (resultData != null) {
+      _recordInstance(resultData.state, resultData);
+      _recordInstance(resultData.value, resultData,
+          onFirstOccurrence: (Object object) {
+        if (object is AstNode) {
+          object.accept(new AstNodeCounter(directNodeCounts));
+        } else if (object is Element) {
+          object.accept(new ElementCounter(elementCounts, indirectNodeCounts));
+        }
+      });
+      resultData.dependedOnResults.forEach((TargetedResult result) =>
+          _processTargetedResult(result, resultData));
+      resultData.dependentResults.forEach((TargetedResult result) =>
+          _processTargetedResult(result, resultData));
+    }
+  }
+
+  void _processTargetedResult(TargetedResult result, Object owner) {
+    _recordInstance(result, owner);
+    uniqueTargetedResults.add(result);
+    _recordInstance(result.target, result);
+    _recordInstance(result.result, result);
+  }
+
+  /**
+   * Record the given [instance] that was found. If this is the first time that
+   * the instance has been found, execute the [onFirstOccurrence] function.
+   *
+   * Note that instances will not be recorded if there are more than
+   * [maxInstanceSetSize] instances of the same type, and that the
+   * [onFirstOccurrence] function will not be executed if the instance is not
+   * recorded.
+   */
+  void _recordInstance(Object instance, Object owner,
+      {void onFirstOccurrence(Object object)}) {
+    Type type = instance.runtimeType;
+    Set instanceSet = instances.putIfAbsent(type, () => new HashSet.identity());
+    if (instanceSet != InfiniteSet.instance) {
+      if (instanceSet.add(instance) && onFirstOccurrence != null) {
+        onFirstOccurrence(instance);
+      }
+      if (instanceSet.length >= maxInstanceSetSize) {
+        instances[type] = InfiniteSet.instance;
+      }
+    }
+    ownerMap
+        .putIfAbsent(instance.runtimeType, () => new HashSet<Type>())
+        .add(owner.runtimeType);
+    if (instance is LibrarySpecificUnit) {
+      uniqueLSUs.add(instance);
+    }
+  }
+}
diff --git a/pkg/analysis_server/pubspec.yaml b/pkg/analysis_server/pubspec.yaml
index 03722a1..9b4a4ff 100644
--- a/pkg/analysis_server/pubspec.yaml
+++ b/pkg/analysis_server/pubspec.yaml
@@ -9,6 +9,7 @@
   analyzer: ^0.27.0
   args: '>=0.13.0 <0.14.0'
   dart_style: '>=0.2.0 <0.3.0'
+  isolate: ^0.2.2
   linter: ^0.1.16
   logging: any
   path: any
diff --git a/pkg/analysis_server/test/analysis_server_test.dart b/pkg/analysis_server/test/analysis_server_test.dart
index eaea9a6..7699859e 100644
--- a/pkg/analysis_server/test/analysis_server_test.dart
+++ b/pkg/analysis_server/test/analysis_server_test.dart
@@ -447,7 +447,6 @@
     AnalysisResult firstResult = new AnalysisResult([notice], 0, '', 0);
     AnalysisResult lastResult = new AnalysisResult(null, 1, '', 1);
     when(context.analysisOptions).thenReturn(new AnalysisOptionsImpl());
-    when(context.validateCacheConsistency()).thenReturn(false);
     when(context.performAnalysisTask)
         .thenReturnList([firstResult, firstResult, firstResult, lastResult]);
     server.serverServices.add(ServerService.STATUS);
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index 2f481cc..5b2416e 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -2659,7 +2659,7 @@
       }
     }
     resolvers.addAll(disposition.createPackageUriResolvers(resourceProvider));
-    resolvers.add(new ResourceUriResolver(PhysicalResourceProvider.INSTANCE));
+    resolvers.add(new ResourceUriResolver(resourceProvider));
     currentContext.analysisOptions = options;
     currentContext.sourceFactory =
         new SourceFactory(resolvers, disposition.packages);
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index ec7c520..81d8a35 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -51,9 +51,9 @@
   test_ArgumentList_imported_function_named_param_label1() async {
     addTestFile('main() { int.parse("16", r^: 16);}');
     await getSuggestions();
-    assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'radix: ',
+    assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'radix',
         relevance: DART_RELEVANCE_NAMED_PARAMETER);
-    assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'onError: ',
+    assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'onError',
         relevance: DART_RELEVANCE_NAMED_PARAMETER);
     expect(suggestions, hasLength(2));
   }
diff --git a/pkg/analysis_server/test/integration/analysis/highlights_test2.dart b/pkg/analysis_server/test/integration/analysis/highlights_test2.dart
index 3ac66ce..bd07449 100644
--- a/pkg/analysis_server/test/integration/analysis/highlights_test2.dart
+++ b/pkg/analysis_server/test/integration/analysis/highlights_test2.dart
@@ -20,9 +20,11 @@
 
 @reflectiveTest
 class AnalysisHighlightsTest extends AbstractAnalysisServerIntegrationTest {
-  Future startServer({int servicesPort}) {
+  Future startServer({int servicesPort, bool checked: true}) {
     return server.start(
-        servicesPort: servicesPort, useAnalysisHighlight2: true);
+        servicesPort: servicesPort,
+        checked: checked,
+        useAnalysisHighlight2: true);
   }
 
   test_highlights() {
diff --git a/pkg/analysis_server/test/integration/integration_tests.dart b/pkg/analysis_server/test/integration/integration_tests.dart
index 9e764a0..9835a1e 100644
--- a/pkg/analysis_server/test/integration/integration_tests.dart
+++ b/pkg/analysis_server/test/integration/integration_tests.dart
@@ -205,8 +205,8 @@
   /**
    * Start [server].
    */
-  Future startServer({int servicesPort}) =>
-      server.start(servicesPort: servicesPort);
+  Future startServer({int servicesPort, bool checked: true}) =>
+      server.start(servicesPort: servicesPort, checked: checked);
 
   /**
    * After every test, the server is stopped and [sourceDirectory] is deleted.
@@ -601,6 +601,7 @@
       int diagnosticPort,
       bool profileServer: false,
       int servicesPort,
+      bool checked: true,
       bool useAnalysisHighlight2: false}) {
     if (_process != null) {
       throw new Exception('Process already started');
@@ -627,7 +628,9 @@
     if (Platform.packageRoot != null) {
       arguments.add('--package-root=${Platform.packageRoot}');
     }
-    arguments.add('--checked');
+    if (checked) {
+      arguments.add('--checked');
+    }
     arguments.add(serverPath);
     if (diagnosticPort != null) {
       arguments.add('--port');
diff --git a/pkg/analysis_server/test/search/element_references_test.dart b/pkg/analysis_server/test/search/element_references_test.dart
index 809a962..cdd7e13 100644
--- a/pkg/analysis_server/test/search/element_references_test.dart
+++ b/pkg/analysis_server/test/search/element_references_test.dart
@@ -268,13 +268,13 @@
   test_hierarchy_method() async {
     addTestFile('''
 class A {
-  mmm() {} // in A
+  mmm(_) {} // in A
 }
 class B extends A {
-  mmm() {} // in B
+  mmm(_) {} // in B
 }
 class C extends B {
-  mmm() {} // in C
+  mmm(_) {} // in C
 }
 main(A a, B b, C c) {
   a.mmm(10);
@@ -282,13 +282,36 @@
   c.mmm(30);
 }
 ''');
-    await findElementReferences('mmm() {} // in B', false);
+    await findElementReferences('mmm(_) {} // in B', false);
     expect(searchElement.kind, ElementKind.METHOD);
     assertHasResult(SearchResultKind.INVOCATION, 'mmm(10)');
     assertHasResult(SearchResultKind.INVOCATION, 'mmm(20)');
     assertHasResult(SearchResultKind.INVOCATION, 'mmm(30)');
   }
 
+  test_hierarchy_method_static() async {
+    addTestFile('''
+class A {
+  static void mmm(_) {} // in A
+}
+class B extends A {
+  static void mmm(_) {} // in B
+}
+class C extends B {
+  static void mmm(_) {} // in C
+}
+main() {
+  A.mmm(10);
+  B.mmm(20);
+  C.mmm(30);
+}
+''');
+    await findElementReferences('mmm(_) {} // in B', false);
+    expect(searchElement.kind, ElementKind.METHOD);
+    expect(results, hasLength(1));
+    assertHasResult(SearchResultKind.INVOCATION, 'mmm(20)');
+  }
+
   test_label() async {
     addTestFile('''
 main() {
diff --git a/pkg/analysis_server/test/search/top_level_declarations_test.dart b/pkg/analysis_server/test/search/top_level_declarations_test.dart
index 81fa08b..8b1829c 100644
--- a/pkg/analysis_server/test/search/top_level_declarations_test.dart
+++ b/pkg/analysis_server/test/search/top_level_declarations_test.dart
@@ -39,6 +39,9 @@
     Request request =
         new SearchFindTopLevelDeclarationsParams(pattern).toRequest('0');
     Response response = await waitResponse(request);
+    if (response.error != null) {
+      return response.error;
+    }
     searchId =
         new SearchFindTopLevelDeclarationsResult.fromResponse(response).id;
     return waitForSearchResults();
@@ -71,4 +74,9 @@
     assertHasDeclaration(ElementKind.TOP_LEVEL_VARIABLE, 'E');
     assertNoDeclaration(ElementKind.CLASS, 'ABC');
   }
+
+  test_invalidRegex() async {
+    var result = await findTopLevelDeclarations('[A');
+    expect(result, new isInstanceOf<RequestError>());
+  }
 }
diff --git a/pkg/analysis_server/test/services/completion/completion_target_test.dart b/pkg/analysis_server/test/services/completion/completion_target_test.dart
index 569610c..f7cca21 100644
--- a/pkg/analysis_server/test/services/completion/completion_target_test.dart
+++ b/pkg/analysis_server/test/services/completion/completion_target_test.dart
@@ -61,6 +61,16 @@
     assertTarget(')', '()', argIndex: 0);
   }
 
+  test_ArgumentList_InstanceCreationExpression2() {
+    // ArgumentList  InstanceCreationExpression  Block
+    addTestSource('main() {new Foo(a,^)}');
+    if (context.analysisOptions.enableTrailingCommas) {
+      assertTarget(')', '(a)', argIndex: 1);
+    } else {
+      assertTarget('', '(a, )', argIndex: 1);
+    }
+  }
+
   test_ArgumentList_InstanceCreationExpression_functionArg2() {
     // ArgumentList  InstanceCreationExpression  Block
     addTestSource('main() {new B(^)} class B{B(f()){}}');
@@ -85,10 +95,20 @@
     assertTarget('n', '(n)', argIndex: 0);
   }
 
+  test_ArgumentList_MethodInvocation3a() {
+    // ArgumentList  MethodInvocation  Block
+    addTestSource('main() {foo((n)^)}');
+    assertTarget(')', '((n))', argIndex: 0);
+  }
+
   test_ArgumentList_MethodInvocation4() {
     // ArgumentList  MethodInvocation  Block
     addTestSource('main() {foo(n,^)}');
-    assertTarget('', '(n, )', argIndex: 1);
+    if (context.analysisOptions.enableTrailingCommas) {
+      assertTarget(')', '(n)', argIndex: 1);
+    } else {
+      assertTarget('', '(n, )', argIndex: 1);
+    }
   }
 
   test_ArgumentList_MethodInvocation_functionArg() {
diff --git a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
index db17859..44ddc2a 100644
--- a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
@@ -81,10 +81,11 @@
    * the only suggestions.
    */
   void assertSuggestArgumentsAndTypes(
-      {Map<String, String> namedArgumentsWithTypes}) {
+      {Map<String, String> namedArgumentsWithTypes, bool includeColon: true}) {
     List<CompletionSuggestion> expected = new List<CompletionSuggestion>();
     namedArgumentsWithTypes.forEach((String name, String type) {
-      expected.add(assertSuggest('$name: ',
+      String completion = includeColon ? '$name: ' : name;
+      expected.add(assertSuggest(completion,
           csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
           relevance: DART_RELEVANCE_NAMED_PARAMETER,
           paramName: name,
@@ -432,7 +433,8 @@
     addTestSource('main() { int.parse("16", r^: 16);}');
     await computeSuggestions();
     assertSuggestArgumentsAndTypes(
-        namedArgumentsWithTypes: {'radix': 'int', 'onError': '(String) → int'});
+        namedArgumentsWithTypes: {'radix': 'int', 'onError': '(String) → int'},
+        includeColon: false);
   }
 
   test_ArgumentList_imported_function_named_param_label2() async {
diff --git a/pkg/analysis_server/test/services/correction/assist_test.dart b/pkg/analysis_server/test/services/correction/assist_test.dart
index 5c84d35..4188664 100644
--- a/pkg/analysis_server/test/services/correction/assist_test.dart
+++ b/pkg/analysis_server/test/services/correction/assist_test.dart
@@ -326,8 +326,8 @@
         'future in',
         DartAssistKind.ADD_TYPE_ANNOTATION,
         '''
-import 'my_lib.dart';
 import 'dart:async';
+import 'my_lib.dart';
 main() {
   for (Future<int> future in getFutures()) {
   }
@@ -466,8 +466,8 @@
         'v =',
         DartAssistKind.ADD_TYPE_ANNOTATION,
         '''
-import 'my_lib.dart';
 import 'dart:async';
+import 'my_lib.dart';
 main() {
   Future<int> v = getFutureInt();
 }
@@ -515,8 +515,8 @@
           resultCode,
           '''
 library my_app;
-import 'my_lib.dart';
 import 'dart:async';
+import 'my_lib.dart';
 part 'test.dart';
 ''');
     }
@@ -556,8 +556,8 @@
         'v =',
         DartAssistKind.ADD_TYPE_ANNOTATION,
         '''
-import 'ccc/lib_b.dart';
 import 'aa/bbb/lib_a.dart';
+import 'ccc/lib_b.dart';
 main() {
   MyClass v = newMyClass();
 }
@@ -1432,6 +1432,177 @@
 ''');
   }
 
+  test_convertToFinalField_BAD_hasSetter_inThisClass() async {
+    resolveTestUnit('''
+class A {
+  int get foo => null;
+  void set foo(_) {}
+}
+''');
+    await assertNoAssistAt('get foo', DartAssistKind.CONVERT_INTO_FINAL_FIELD);
+  }
+
+  test_convertToFinalField_BAD_notExpressionBody() async {
+    resolveTestUnit('''
+class A {
+  int get foo {
+    int v = 1 + 2;
+    return v + 3;
+  }
+}
+''');
+    await assertNoAssistAt('get foo', DartAssistKind.CONVERT_INTO_FINAL_FIELD);
+  }
+
+  test_convertToFinalField_BAD_notGetter() async {
+    resolveTestUnit('''
+class A {
+  int foo() => 42;
+}
+''');
+    await assertNoAssistAt('foo', DartAssistKind.CONVERT_INTO_FINAL_FIELD);
+  }
+
+  test_convertToFinalField_OK_blockBody_onlyReturnStatement() async {
+    resolveTestUnit('''
+class A {
+  int get foo {
+    return 1 + 2;
+  }
+}
+''');
+    await assertHasAssistAt(
+        'get foo',
+        DartAssistKind.CONVERT_INTO_FINAL_FIELD,
+        '''
+class A {
+  final int foo = 1 + 2;
+}
+''');
+  }
+
+  test_convertToFinalField_OK_hasOverride() async {
+    resolveTestUnit('''
+const myAnnotation = const Object();
+class A {
+  @myAnnotation
+  int get foo => 42;
+}
+''');
+    await assertHasAssistAt(
+        'get foo',
+        DartAssistKind.CONVERT_INTO_FINAL_FIELD,
+        '''
+const myAnnotation = const Object();
+class A {
+  @myAnnotation
+  final int foo = 42;
+}
+''');
+  }
+
+  test_convertToFinalField_OK_hasSetter_inSuper() async {
+    resolveTestUnit('''
+class A {
+  void set foo(_) {}
+}
+class B extends A {
+  int get foo => null;
+}
+''');
+    await assertHasAssistAt(
+        'get foo',
+        DartAssistKind.CONVERT_INTO_FINAL_FIELD,
+        '''
+class A {
+  void set foo(_) {}
+}
+class B extends A {
+  final int foo;
+}
+''');
+  }
+
+  test_convertToFinalField_OK_notNull() async {
+    resolveTestUnit('''
+class A {
+  int get foo => 1 + 2;
+}
+''');
+    await assertHasAssistAt(
+        'get foo',
+        DartAssistKind.CONVERT_INTO_FINAL_FIELD,
+        '''
+class A {
+  final int foo = 1 + 2;
+}
+''');
+  }
+
+  test_convertToFinalField_OK_null() async {
+    resolveTestUnit('''
+class A {
+  int get foo => null;
+}
+''');
+    await assertHasAssistAt(
+        'get foo',
+        DartAssistKind.CONVERT_INTO_FINAL_FIELD,
+        '''
+class A {
+  final int foo;
+}
+''');
+  }
+
+  test_convertToFinalField_OK_onName() async {
+    resolveTestUnit('''
+class A {
+  int get foo => 42;
+}
+''');
+    await assertHasAssistAt(
+        'foo',
+        DartAssistKind.CONVERT_INTO_FINAL_FIELD,
+        '''
+class A {
+  final int foo = 42;
+}
+''');
+  }
+
+  test_convertToFinalField_OK_onReturnType_parameterized() async {
+    resolveTestUnit('''
+class A {
+  List<int> get foo => null;
+}
+''');
+    await assertHasAssistAt(
+        'nt> get',
+        DartAssistKind.CONVERT_INTO_FINAL_FIELD,
+        '''
+class A {
+  final List<int> foo;
+}
+''');
+  }
+
+  test_convertToFinalField_OK_onReturnType_simple() async {
+    resolveTestUnit('''
+class A {
+  int get foo => 42;
+}
+''');
+    await assertHasAssistAt(
+        'int get',
+        DartAssistKind.CONVERT_INTO_FINAL_FIELD,
+        '''
+class A {
+  final int foo = 42;
+}
+''');
+  }
+
   test_convertToForIndex_BAD_bodyNotBlock() async {
     resolveTestUnit('''
 main(List<String> items) {
@@ -1598,6 +1769,69 @@
 ''');
   }
 
+  test_convertToGetter_BAD_noInitializer() async {
+    resolveTestUnit('''
+class A {
+  final int foo;
+}
+''');
+    await assertNoAssistAt('foo', DartAssistKind.CONVERT_INTO_GETTER);
+  }
+
+  test_convertToGetter_BAD_notFinal() async {
+    resolveTestUnit('''
+class A {
+  int foo = 1;
+}
+''');
+    await assertNoAssistAt('foo', DartAssistKind.CONVERT_INTO_GETTER);
+  }
+
+  test_convertToGetter_BAD_notSingleField() async {
+    resolveTestUnit('''
+class A {
+  final int foo = 1, bar = 2;
+}
+''');
+    await assertNoAssistAt('foo', DartAssistKind.CONVERT_INTO_GETTER);
+  }
+
+  test_convertToGetter_OK() async {
+    resolveTestUnit('''
+const myAnnotation = const Object();
+class A {
+  @myAnnotation
+  final int foo = 1 + 2;
+}
+''');
+    await assertHasAssistAt(
+        'foo =',
+        DartAssistKind.CONVERT_INTO_GETTER,
+        '''
+const myAnnotation = const Object();
+class A {
+  @myAnnotation
+  int get foo => 1 + 2;
+}
+''');
+  }
+
+  test_convertToGetter_OK_noType() async {
+    resolveTestUnit('''
+class A {
+  final foo = 42;
+}
+''');
+    await assertHasAssistAt(
+        'foo =',
+        DartAssistKind.CONVERT_INTO_GETTER,
+        '''
+class A {
+  get foo => 42;
+}
+''');
+  }
+
   test_convertToIsNot_BAD_is_alreadyIsNot() async {
     resolveTestUnit('''
 main(p) {
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart
index 4ec437f..5244097 100644
--- a/pkg/analysis_server/test/services/correction/fix_test.dart
+++ b/pkg/analysis_server/test/services/correction/fix_test.dart
@@ -463,40 +463,42 @@
 ''');
     List<AnalysisError> errors = context.computeErrors(testSource);
     expect(errors, hasLength(2));
-    String message1 = "Expected to find ';'";
-    String message2 = "Undefined name 'await'";
-    expect(errors.map((e) => e.message), unorderedEquals([message1, message2]));
-    for (AnalysisError error in errors) {
-      if (error.message == message1) {
-        List<Fix> fixes = await _computeFixes(error);
-        expect(fixes, isEmpty);
-      }
-      if (error.message == message2) {
-        List<Fix> fixes = await _computeFixes(error);
-        // has exactly one fix
-        expect(fixes, hasLength(1));
-        Fix fix = fixes[0];
-        expect(fix.kind, DartFixKind.ADD_ASYNC);
-        // apply to "file"
-        List<SourceFileEdit> fileEdits = fix.change.edits;
-        expect(fileEdits, hasLength(1));
-        resultCode = SourceEdit.applySequence(testCode, fileEdits[0].edits);
-        // verify
-        expect(
-            resultCode,
-            '''
+    errors.sort((a, b) => a.message.compareTo(b.message));
+    // No fix for ";".
+    {
+      AnalysisError error = errors[0];
+      expect(error.message, "Expected to find ';'");
+      List<Fix> fixes = await _computeFixes(error);
+      expect(fixes, isEmpty);
+    }
+    // Has fix for "await".
+    {
+      AnalysisError error = errors[1];
+      expect(error.message, startsWith("Undefined name 'await';"));
+      List<Fix> fixes = await _computeFixes(error);
+      // has exactly one fix
+      expect(fixes, hasLength(1));
+      Fix fix = fixes[0];
+      expect(fix.kind, DartFixKind.ADD_ASYNC);
+      // apply to "file"
+      List<SourceFileEdit> fileEdits = fix.change.edits;
+      expect(fileEdits, hasLength(1));
+      resultCode = SourceEdit.applySequence(testCode, fileEdits[0].edits);
+      // verify
+      expect(
+          resultCode,
+          '''
 foo() {}
 main() async {
   await foo();
 }
 ''');
-      }
     }
   }
 
   test_addSync_expressionFunctionBody() async {
     errorFilter = (AnalysisError error) {
-      return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER;
+      return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT;
     };
     resolveTestUnit('''
 foo() {}
@@ -512,7 +514,7 @@
 
   test_addSync_returnFuture() async {
     errorFilter = (AnalysisError error) {
-      return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER;
+      return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT;
     };
     resolveTestUnit('''
 foo() {}
@@ -536,7 +538,7 @@
 
   test_addSync_returnFuture_alreadyFuture() async {
     errorFilter = (AnalysisError error) {
-      return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER;
+      return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT;
     };
     resolveTestUnit('''
 import 'dart:async';
@@ -560,7 +562,7 @@
 
   test_addSync_returnFuture_dynamic() async {
     errorFilter = (AnalysisError error) {
-      return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER;
+      return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT;
     };
     resolveTestUnit('''
 foo() {}
@@ -582,7 +584,7 @@
 
   test_addSync_returnFuture_noType() async {
     errorFilter = (AnalysisError error) {
-      return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER;
+      return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT;
     };
     resolveTestUnit('''
 foo() {}
@@ -708,8 +710,8 @@
     await assertHasFix(
         DartFixKind.CHANGE_TO_STATIC_ACCESS,
         '''
-import 'libB.dart';
 import 'libA.dart';
+import 'libB.dart';
 main(B b) {
   A.foo();
 }
@@ -779,8 +781,8 @@
     await assertHasFix(
         DartFixKind.CHANGE_TO_STATIC_ACCESS,
         '''
-import 'libB.dart';
 import 'libA.dart';
+import 'libB.dart';
 main(B b) {
   A.foo;
 }
@@ -1239,8 +1241,8 @@
     await assertHasFix(
         DartFixKind.CREATE_CONSTRUCTOR_SUPER,
         '''
-import 'libB.dart';
 import 'libA.dart';
+import 'libB.dart';
 class C extends B {
   C(A a) : super(a);
 }
@@ -1563,8 +1565,8 @@
     await assertHasFix(
         DartFixKind.CREATE_FIELD,
         '''
-import 'libB.dart';
 import 'libA.dart';
+import 'libB.dart';
 class C {
   A test;
 }
@@ -2631,7 +2633,7 @@
   }
 
   @override
-  void set s3(String x) {
+  set s3(String x) {
     // TODO: implement s3
   }
 }
@@ -2802,8 +2804,8 @@
     await assertHasFix(
         DartFixKind.CREATE_FUNCTION,
         '''
-import 'libB.dart';
 import 'libA.dart';
+import 'libB.dart';
 main() {
   useFunction(test);
 }
@@ -2976,6 +2978,7 @@
         DartFixKind.REPLACE_RETURN_TYPE_FUTURE,
         '''
 library main;
+
 import 'dart:async';
 Future<int> main() async {
 }
@@ -3111,8 +3114,8 @@
     await assertHasFix(
         DartFixKind.IMPORT_LIBRARY_PROJECT,
         '''
-import 'b.dart' show Two;
 import 'a.dart';
+import 'b.dart' show Two;
 main () {
   new Two();
   new One();
@@ -4131,8 +4134,8 @@
     await assertHasFix(
         DartFixKind.CREATE_FUNCTION,
         '''
-import 'lib.dart';
 import 'dart:async';
+import 'lib.dart';
 main() {
   test(getFuture());
 }
diff --git a/pkg/analysis_server/test/services/correction/test_all.dart b/pkg/analysis_server/test/services/correction/test_all.dart
index d1a6bb5..f00f310 100644
--- a/pkg/analysis_server/test/services/correction/test_all.dart
+++ b/pkg/analysis_server/test/services/correction/test_all.dart
@@ -17,6 +17,7 @@
 import 'source_range_test.dart' as source_range_test;
 import 'status_test.dart' as status_test;
 import 'strings_test.dart' as strings_test;
+import 'util_test.dart' as util_test;
 
 /// Utility for manually running all tests.
 main() {
@@ -32,5 +33,6 @@
     source_range_test.main();
     status_test.main();
     strings_test.main();
+    util_test.main();
   });
 }
diff --git a/pkg/analysis_server/test/services/correction/util_test.dart b/pkg/analysis_server/test/services/correction/util_test.dart
new file mode 100644
index 0000000..a435b1c
--- /dev/null
+++ b/pkg/analysis_server/test/services/correction/util_test.dart
@@ -0,0 +1,293 @@
+// 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 test.services.correction.util;
+
+import 'package:analysis_server/plugin/protocol/protocol.dart';
+import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analysis_server/src/services/correction/util.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../abstract_single_unit.dart';
+import '../../utils.dart';
+
+main() {
+  initializeTestEnvironment();
+  defineReflectiveTests(UtilTest);
+}
+
+@reflectiveTest
+class UtilTest extends AbstractSingleUnitTest {
+  test_addLibraryImports_dart_hasImports_between() {
+    resolveTestUnit('''
+import 'dart:async';
+import 'dart:math';
+''');
+    LibraryElement newLibrary = _getDartLibrary('dart:collection');
+    _assertAddLibraryImport(
+        <LibraryElement>[newLibrary],
+        '''
+import 'dart:async';
+import 'dart:collection';
+import 'dart:math';
+''');
+  }
+
+  test_addLibraryImports_dart_hasImports_first() {
+    resolveTestUnit('''
+import 'dart:collection';
+import 'dart:math';
+''');
+    LibraryElement newLibrary = _getDartLibrary('dart:async');
+    _assertAddLibraryImport(
+        <LibraryElement>[newLibrary],
+        '''
+import 'dart:async';
+import 'dart:collection';
+import 'dart:math';
+''');
+  }
+
+  test_addLibraryImports_dart_hasImports_last() {
+    resolveTestUnit('''
+import 'dart:async';
+import 'dart:collection';
+''');
+    LibraryElement newLibrary = _getDartLibrary('dart:math');
+    _assertAddLibraryImport(
+        <LibraryElement>[newLibrary],
+        '''
+import 'dart:async';
+import 'dart:collection';
+import 'dart:math';
+''');
+  }
+
+  test_addLibraryImports_dart_hasImports_multiple() {
+    resolveTestUnit('''
+import 'dart:collection';
+import 'dart:math';
+''');
+    LibraryElement newLibrary1 = _getDartLibrary('dart:async');
+    LibraryElement newLibrary2 = _getDartLibrary('dart:html');
+    _assertAddLibraryImport(
+        <LibraryElement>[newLibrary1, newLibrary2],
+        '''
+import 'dart:async';
+import 'dart:collection';
+import 'dart:html';
+import 'dart:math';
+''');
+  }
+
+  test_addLibraryImports_dart_hasImports_multiple_first() {
+    resolveTestUnit('''
+import 'dart:html';
+import 'dart:math';
+''');
+    LibraryElement newLibrary1 = _getDartLibrary('dart:async');
+    LibraryElement newLibrary2 = _getDartLibrary('dart:collection');
+    _assertAddLibraryImport(
+        <LibraryElement>[newLibrary1, newLibrary2],
+        '''
+import 'dart:async';
+import 'dart:collection';
+import 'dart:html';
+import 'dart:math';
+''');
+  }
+
+  test_addLibraryImports_dart_hasImports_multiple_last() {
+    resolveTestUnit('''
+import 'dart:async';
+import 'dart:collection';
+''');
+    LibraryElement newLibrary1 = _getDartLibrary('dart:html');
+    LibraryElement newLibrary2 = _getDartLibrary('dart:math');
+    _assertAddLibraryImport(
+        <LibraryElement>[newLibrary1, newLibrary2],
+        '''
+import 'dart:async';
+import 'dart:collection';
+import 'dart:html';
+import 'dart:math';
+''');
+  }
+
+  test_addLibraryImports_dart_hasLibraryDirective() {
+    resolveTestUnit('''
+library test;
+
+class A {}
+''');
+    LibraryElement newLibrary1 = _getDartLibrary('dart:math');
+    LibraryElement newLibrary2 = _getDartLibrary('dart:async');
+    _assertAddLibraryImport(
+        <LibraryElement>[newLibrary1, newLibrary2],
+        '''
+library test;
+
+import 'dart:async';
+import 'dart:math';
+
+class A {}
+''');
+  }
+
+  test_addLibraryImports_dart_noDirectives_hasComment() {
+    resolveTestUnit('''
+/// Comment.
+
+class A {}
+''');
+    LibraryElement newLibrary1 = _getDartLibrary('dart:math');
+    LibraryElement newLibrary2 = _getDartLibrary('dart:async');
+    _assertAddLibraryImport(
+        <LibraryElement>[newLibrary1, newLibrary2],
+        '''
+/// Comment.
+
+import 'dart:async';
+import 'dart:math';
+
+class A {}
+''');
+  }
+
+  test_addLibraryImports_dart_noDirectives_hasShebang() {
+    resolveTestUnit('''
+#!/bin/dart
+
+class A {}
+''');
+    LibraryElement newLibrary1 = _getDartLibrary('dart:math');
+    LibraryElement newLibrary2 = _getDartLibrary('dart:async');
+    _assertAddLibraryImport(
+        <LibraryElement>[newLibrary1, newLibrary2],
+        '''
+#!/bin/dart
+
+import 'dart:async';
+import 'dart:math';
+
+class A {}
+''');
+  }
+
+  test_addLibraryImports_dart_noDirectives_noShebang() {
+    resolveTestUnit('''
+class A {}
+''');
+    LibraryElement newLibrary1 = _getDartLibrary('dart:math');
+    LibraryElement newLibrary2 = _getDartLibrary('dart:async');
+    _assertAddLibraryImport(
+        <LibraryElement>[newLibrary1, newLibrary2],
+        '''
+import 'dart:async';
+import 'dart:math';
+
+class A {}
+''');
+  }
+
+  test_addLibraryImports_package_hasDart_hasPackages_insertAfter() {
+    resolveTestUnit('''
+import 'dart:async';
+
+import 'package:aaa/aaa.dart';
+''');
+    LibraryElement newLibrary =
+        _mockLibraryElement('/lib/bbb.dart', 'package:bbb/bbb.dart');
+    _assertAddLibraryImport(
+        <LibraryElement>[newLibrary],
+        '''
+import 'dart:async';
+
+import 'package:aaa/aaa.dart';
+import 'package:bbb/bbb.dart';
+''');
+  }
+
+  test_addLibraryImports_package_hasDart_hasPackages_insertBefore() {
+    resolveTestUnit('''
+import 'dart:async';
+
+import 'package:bbb/bbb.dart';
+''');
+    LibraryElement newLibrary =
+        _mockLibraryElement('/lib/aaa.dart', 'package:aaa/aaa.dart');
+    _assertAddLibraryImport(
+        <LibraryElement>[newLibrary],
+        '''
+import 'dart:async';
+
+import 'package:aaa/aaa.dart';
+import 'package:bbb/bbb.dart';
+''');
+  }
+
+  test_addLibraryImports_package_hasImports_between() {
+    resolveTestUnit('''
+import 'package:aaa/aaa.dart';
+import 'package:ddd/ddd.dart';
+''');
+    LibraryElement newLibrary1 =
+        _mockLibraryElement('/lib/bbb.dart', 'package:bbb/bbb.dart');
+    LibraryElement newLibrary2 =
+        _mockLibraryElement('/lib/ccc.dart', 'package:ccc/ccc.dart');
+    _assertAddLibraryImport(
+        <LibraryElement>[newLibrary1, newLibrary2],
+        '''
+import 'package:aaa/aaa.dart';
+import 'package:bbb/bbb.dart';
+import 'package:ccc/ccc.dart';
+import 'package:ddd/ddd.dart';
+''');
+  }
+
+  void _assertAddLibraryImport(
+      List<LibraryElement> newLibraries, String expectedCode) {
+    SourceChange change = new SourceChange('');
+    addLibraryImports(change, testLibraryElement, newLibraries.toSet());
+    SourceFileEdit testEdit = change.getFileEdit(testFile);
+    expect(testEdit, isNotNull);
+    String resultCode = SourceEdit.applySequence(testCode, testEdit.edits);
+    expect(resultCode, expectedCode);
+  }
+
+  LibraryElement _getDartLibrary(String uri) {
+    String path = removeStart(uri, 'dart:');
+    Source newSource = new _SourceMock('/sdk/lib/$path.dart', Uri.parse(uri));
+    return new _LibraryElementMock(newSource);
+  }
+
+  LibraryElement _mockLibraryElement(String path, String uri) {
+    Source newSource = new _SourceMock(path, Uri.parse(uri));
+    return new _LibraryElementMock(newSource);
+  }
+}
+
+class _LibraryElementMock implements LibraryElement {
+  @override
+  final Source source;
+
+  _LibraryElementMock(this.source);
+
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+class _SourceMock implements Source {
+  @override
+  final String fullName;
+
+  @override
+  final Uri uri;
+
+  _SourceMock(this.fullName, this.uri);
+
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
diff --git a/pkg/analysis_server/test/services/refactoring/rename_class_member_test.dart b/pkg/analysis_server/test/services/refactoring/rename_class_member_test.dart
index 46ed173..cc09692 100644
--- a/pkg/analysis_server/test/services/refactoring/rename_class_member_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/rename_class_member_test.dart
@@ -90,6 +90,22 @@
         expectedContextSearch: 'newName() {} // existing');
   }
 
+  test_checkFinalConditions_OK_dropSuffix() async {
+    indexTestUnit(r'''
+abstract class A {
+  void testOld();
+}
+class B implements A {
+  void testOld() {}
+}
+''');
+    createRenameRefactoringAtString('testOld() {}');
+    // check status
+    refactoring.newName = 'test';
+    RefactoringStatus status = await refactoring.checkFinalConditions();
+    assertRefactoringStatusOK(status);
+  }
+
   test_checkFinalConditions_OK_noShadow() async {
     indexTestUnit('''
 class A {
diff --git a/pkg/analysis_server/test/services/search/hierarchy_test.dart b/pkg/analysis_server/test/services/search/hierarchy_test.dart
index 027c237..802f351 100644
--- a/pkg/analysis_server/test/services/search/hierarchy_test.dart
+++ b/pkg/analysis_server/test/services/search/hierarchy_test.dart
@@ -118,6 +118,41 @@
     return Future.wait([futureA, futureB, futureC, futureD]);
   }
 
+  Future test_getHierarchyMembers_fields_static() async {
+    _indexTestUnit('''
+class A {
+  static int foo;
+}
+class B extends A {
+  static get foo => null;
+}
+class C extends B {
+  static set foo(x) {}
+}
+''');
+    ClassElement classA = findElement('A');
+    ClassElement classB = findElement('B');
+    ClassElement classC = findElement('C');
+    ClassMemberElement memberA = classA.fields[0];
+    ClassMemberElement memberB = classB.fields[0];
+    ClassMemberElement memberC = classC.fields[0];
+    {
+      Set<ClassMemberElement> members =
+          await getHierarchyMembers(searchEngine, memberA);
+      expect(members, unorderedEquals([memberA]));
+    }
+    {
+      Set<ClassMemberElement> members =
+          await getHierarchyMembers(searchEngine, memberB);
+      expect(members, unorderedEquals([memberB]));
+    }
+    {
+      Set<ClassMemberElement> members =
+          await getHierarchyMembers(searchEngine, memberC);
+      expect(members, unorderedEquals([memberC]));
+    }
+  }
+
   Future test_getHierarchyMembers_methods() {
     _indexTestUnit('''
 class A {
@@ -164,6 +199,31 @@
     return Future.wait([futureA, futureB, futureC, futureD, futureE]);
   }
 
+  Future test_getHierarchyMembers_methods_static() async {
+    _indexTestUnit('''
+class A {
+  static foo() {}
+}
+class B extends A {
+  static foo() {}
+}
+''');
+    ClassElement classA = findElement('A');
+    ClassElement classB = findElement('B');
+    ClassMemberElement memberA = classA.methods[0];
+    ClassMemberElement memberB = classB.methods[0];
+    {
+      Set<ClassMemberElement> members =
+          await getHierarchyMembers(searchEngine, memberA);
+      expect(members, unorderedEquals([memberA]));
+    }
+    {
+      Set<ClassMemberElement> members =
+          await getHierarchyMembers(searchEngine, memberB);
+      expect(members, unorderedEquals([memberB]));
+    }
+  }
+
   Future test_getHierarchyMembers_withInterfaces() {
     _indexTestUnit('''
 class A {
diff --git a/pkg/analysis_server/test/services/search/search_engine_test.dart b/pkg/analysis_server/test/services/search/search_engine_test.dart
index 4bf728d..cea1817 100644
--- a/pkg/analysis_server/test/services/search/search_engine_test.dart
+++ b/pkg/analysis_server/test/services/search/search_engine_test.dart
@@ -101,8 +101,9 @@
 }
 class B {
   int test = 1;
+  int testTwo = 2;
   main() {
-    int test = 2;
+    int test = 3;
   }
 }
 ''');
diff --git a/pkg/analysis_server/test/stress/replay/replay.dart b/pkg/analysis_server/test/stress/replay/replay.dart
index 6c56047..dd9016d 100644
--- a/pkg/analysis_server/test/stress/replay/replay.dart
+++ b/pkg/analysis_server/test/stress/replay/replay.dart
@@ -9,6 +9,7 @@
 
 import 'dart:async';
 import 'dart:io';
+import 'dart:math' as math;
 
 import 'package:analysis_server/plugin/protocol/protocol.dart';
 import 'package:analyzer/dart/ast/token.dart';
@@ -168,7 +169,8 @@
     LineInfo info = fileEdit.lineInfo;
     for (DiffHunk hunk in blobDiff.hunks) {
       int srcStart = info.getOffsetOfLine(hunk.srcLine);
-      int srcEnd = info.getOffsetOfLine(hunk.srcLine + hunk.removeLines.length);
+      int srcEnd = info.getOffsetOfLine(
+          math.min(hunk.srcLine + hunk.removeLines.length, info.lineCount - 1));
       String addedText = _join(hunk.addLines);
       //
       // Create the source edits.
@@ -320,6 +322,7 @@
     //
     // Iterate over the history, applying changes.
     //
+    int dotCount = 0;
     bool firstCheckout = true;
     ErrorMap expectedErrors = null;
     Iterable<String> changedPubspecs;
@@ -363,6 +366,10 @@
       }
       changedPubspecs = commitDelta.filesMatching(PUBSPEC_FILE_NAME);
       stdout.write('.');
+      if (dotCount++ > 100) {
+        stdout.writeln();
+        dotCount = 0;
+      }
     }
     server.removeAllOverlays();
     stdout.writeln();
@@ -632,10 +639,8 @@
     if (hours > 0) {
       return '$hours:$minutes:$seconds.$milliseconds';
     } else if (minutes > 0) {
-      return '$minutes:$seconds.$milliseconds m';
-    } else if (seconds > 0) {
-      return '$seconds.$milliseconds s';
+      return '$minutes:$seconds.$milliseconds';
     }
-    return '$milliseconds ms';
+    return '$seconds.$milliseconds';
   }
 }
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 07f8a30..4be083e 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,16 @@
+## 0.27.4-alpha.19
+* Added support for running the dev compiler in the browser.
+
+## 0.27.4-alpha.18
+* Support for references to operators in doc comments (#26929).
+
+## 0.27.4-alpha.17
+* Support for trailing commas in parameter and argument lists (#26647).
+* Strong mode breaking change: can now infer generic type arguments from the constructor invocation arguments (#25220).
+
+## 0.27.4-alpha.16
+* (Internal) Corresponds with the analyzer/server in the `1.18.0-dev.4.0` SDK.
+
 ## 0.27.4-alpha.9
 * Restore EmbedderUriResolver API.
 
diff --git a/pkg/analyzer/doc/tasks.html b/pkg/analyzer/doc/tasks.html
index eb19b8b..b5a88d0 100644
--- a/pkg/analyzer/doc/tasks.html
+++ b/pkg/analyzer/doc/tasks.html
@@ -30,7 +30,6 @@
   BuildLibraryElementTask -> BUILD_LIBRARY_ERRORS
   BuildLibraryElementTask -> IS_LAUNCHABLE
   BuildLibraryElementTask -> LIBRARY_ELEMENT1
-  BuildLibraryElementTask -> REFERENCED_NAMES
   BuildPublicNamespaceTask -> LIBRARY_ELEMENT3
   BuildSourceExportClosureTask -> EXPORT_SOURCE_CLOSURE
   BuildTypeProviderTask -> TYPE_PROVIDER
@@ -96,6 +95,7 @@
   EXPORTED_LIBRARIES -> ResolveTopLevelLibraryTypeBoundsTask
   EXPORTED_LIBRARIES [shape=box]
   EXPORT_SOURCE_CLOSURE -> BuildExportNamespaceTask
+  EXPORT_SOURCE_CLOSURE -> ResolveTopLevelUnitTypeBoundsTask
   EXPORT_SOURCE_CLOSURE [shape=box]
   EvaluateUnitConstantsTask -> CREATED_RESOLVED_UNIT13
   EvaluateUnitConstantsTask -> RESOLVED_UNIT13
@@ -216,6 +216,7 @@
   ParseDartTask -> LIBRARY_SPECIFIC_UNITS
   ParseDartTask -> PARSED_UNIT
   ParseDartTask -> PARSE_ERRORS
+  ParseDartTask -> REFERENCED_NAMES
   ParseDartTask -> REFERENCED_SOURCES
   ParseDartTask -> SOURCE_KIND
   ParseDartTask -> UNITS
diff --git a/pkg/analyzer/lib/context/declared_variables.dart b/pkg/analyzer/lib/context/declared_variables.dart
index 9a0322c..86d6234 100644
--- a/pkg/analyzer/lib/context/declared_variables.dart
+++ b/pkg/analyzer/lib/context/declared_variables.dart
@@ -23,6 +23,11 @@
   HashMap<String, String> _declaredVariables = new HashMap<String, String>();
 
   /**
+   * Return the names of the variables for which a value has been defined.
+   */
+  Iterable<String> get variableNames => _declaredVariables.keys;
+
+  /**
    * Define a variable with the given [name] to have the given [value].
    */
   void define(String name, String value) {
diff --git a/pkg/analyzer/lib/file_system/file_system.dart b/pkg/analyzer/lib/file_system/file_system.dart
index 7a12c6f1c..41d6f84 100644
--- a/pkg/analyzer/lib/file_system/file_system.dart
+++ b/pkg/analyzer/lib/file_system/file_system.dart
@@ -166,6 +166,11 @@
    * this folder.
    */
   bool isOrContains(String path);
+
+  /**
+   * Return a Uri representing this resource.
+   */
+  Uri toUri();
 }
 
 /**
@@ -198,6 +203,14 @@
   Folder getFolder(String path);
 
   /**
+   * Complete with a list of modification times for the given [sources].
+   *
+   * If the file of a source is not managed by this provider, return `null`.
+   * If the file a source does not exist, return `-1`.
+   */
+  Future<List<int>> getModificationTimes(List<Source> sources);
+
+  /**
    * Return the [Resource] that corresponds to the given [path].
    */
   Resource getResource(String path);
@@ -225,6 +238,8 @@
 
   ResourceUriResolver(this._provider);
 
+  ResourceProvider get provider => _provider;
+
   @override
   Source resolveAbsolute(Uri uri, [Uri actualUri]) {
     if (!isFileUri(uri)) {
@@ -242,8 +257,6 @@
   Uri restoreAbsolute(Source source) =>
       _provider.pathContext.toUri(source.fullName);
 
-  ResourceProvider get provider => _provider;
-
   /**
    * Return `true` if the given [uri] is a `file` URI.
    */
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index 3391433..cd8e149 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -80,6 +80,14 @@
   Folder getFolder(String path) => newFolder(path);
 
   @override
+  Future<List<int>> getModificationTimes(List<Source> sources) async {
+    return sources.map((source) {
+      String path = source.fullName;
+      return _pathToTimestamp[path] ?? -1;
+    }).toList();
+  }
+
+  @override
   Resource getResource(String path) {
     path = pathContext.normalize(path);
     Resource resource = _pathToResource[path];
@@ -306,6 +314,9 @@
   }
 
   @override
+  Uri toUri() => new Uri.file(path, windows: _provider.pathContext == windows);
+
+  @override
   void writeAsBytesSync(List<int> bytes) {
     throw new FileSystemException(path, 'File could not be written');
   }
@@ -380,6 +391,9 @@
   }
 
   @override
+  Uri toUri() => new Uri.file(path, windows: _provider.pathContext == windows);
+
+  @override
   void writeAsBytesSync(List<int> bytes) {
     _provider._setFileBytes(this, bytes);
   }
@@ -553,6 +567,10 @@
     }
     return contains(path);
   }
+
+  @override
+  Uri toUri() =>
+      new Uri.directory(path, windows: _provider.pathContext == windows);
 }
 
 /**
diff --git a/pkg/analyzer/lib/file_system/physical_file_system.dart b/pkg/analyzer/lib/file_system/physical_file_system.dart
index 9cd62b6..8b8618e 100644
--- a/pkg/analyzer/lib/file_system/physical_file_system.dart
+++ b/pkg/analyzer/lib/file_system/physical_file_system.dart
@@ -12,10 +12,34 @@
 import 'package:analyzer/src/generated/java_io.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/util/absolute_path.dart';
+import 'package:isolate/isolate_runner.dart';
 import 'package:path/path.dart';
 import 'package:watcher/watcher.dart';
 
 /**
+ * Return modification times for every file path in [paths].
+ *
+ * If a path is `null`, the modification time is also `null`.
+ *
+ * If any exception happens, the file is considered as a not existing and
+ * `-1` is its modification time.
+ */
+List<int> _pathsToTimes(List<String> paths) {
+  return paths.map((path) {
+    if (path != null) {
+      try {
+        io.File file = new io.File(path);
+        return file.lastModifiedSync().millisecondsSinceEpoch;
+      } catch (_) {
+        return -1;
+      }
+    } else {
+      return null;
+    }
+  }).toList();
+}
+
+/**
  * A `dart:io` based implementation of [ResourceProvider].
  */
 class PhysicalResourceProvider implements ResourceProvider {
@@ -31,6 +55,9 @@
    */
   static final String SERVER_DIR = ".dartServer";
 
+  static _SingleIsolateRunnerProvider pathsToTimesIsolateProvider =
+      new _SingleIsolateRunnerProvider();
+
   @override
   final AbsolutePathContext absolutePathContext =
       new AbsolutePathContext(io.Platform.isWindows);
@@ -51,6 +78,15 @@
   Folder getFolder(String path) => new _PhysicalFolder(new io.Directory(path));
 
   @override
+  Future<List<int>> getModificationTimes(List<Source> sources) async {
+    List<String> paths = sources
+        .map((source) => source is FileBasedSource ? source.fullName : null)
+        .toList();
+    IsolateRunner runner = await pathsToTimesIsolateProvider.get();
+    return runner.run(_pathsToTimes, paths);
+  }
+
+  @override
   Resource getResource(String path) {
     if (io.FileSystemEntity.isDirectorySync(path)) {
       return getFolder(path);
@@ -143,6 +179,9 @@
   }
 
   @override
+  Uri toUri() => new Uri.file(path);
+
+  @override
   void writeAsBytesSync(List<int> bytes) {
     try {
       io.File file = _entry as io.File;
@@ -220,6 +259,9 @@
     }
     return contains(path);
   }
+
+  @override
+  Uri toUri() => new Uri.directory(path);
 }
 
 /**
@@ -274,3 +316,33 @@
   @override
   String toString() => path;
 }
+
+/**
+ * This class encapsulates logic for creating a single [IsolateRunner].
+ */
+class _SingleIsolateRunnerProvider {
+  bool _isSpawning = false;
+  IsolateRunner _runner;
+
+  /**
+   * Complete with the only [IsolateRunner] instance.
+   */
+  Future<IsolateRunner> get() async {
+    if (_runner != null) {
+      return _runner;
+    }
+    if (_isSpawning) {
+      Completer<IsolateRunner> completer = new Completer<IsolateRunner>();
+      new Timer.periodic(new Duration(milliseconds: 10), (Timer timer) {
+        if (_runner != null) {
+          completer.complete(_runner);
+          timer.cancel();
+        }
+      });
+      return completer.future;
+    }
+    _isSpawning = true;
+    _runner = await IsolateRunner.spawn();
+    return _runner;
+  }
+}
diff --git a/pkg/analyzer/lib/source/config.dart b/pkg/analyzer/lib/source/config.dart
index 0ca954a..db44b4e 100644
--- a/pkg/analyzer/lib/source/config.dart
+++ b/pkg/analyzer/lib/source/config.dart
@@ -91,7 +91,8 @@
               Uri pragma = new Uri.file('config/${descriptor.pragma}.yaml',
                   windows: false);
               Uri optionsUri = uri.resolveUri(pragma);
-              File file = resourceProvider.getFile(optionsUri.toFilePath());
+              String path = resourceProvider.pathContext.fromUri(optionsUri);
+              File file = resourceProvider.getFile(path);
               if (file.exists) {
                 return optionsProvider.getOptionsFromFile(file);
               }
diff --git a/pkg/analyzer/lib/source/sdk_ext.dart b/pkg/analyzer/lib/source/sdk_ext.dart
index 3e833df..f25d65e 100644
--- a/pkg/analyzer/lib/source/sdk_ext.dart
+++ b/pkg/analyzer/lib/source/sdk_ext.dart
@@ -31,6 +31,12 @@
 
   final Map<String, String> _urlMappings = <String, String>{};
 
+  /**
+   * The absolute paths of the extension files that contributed to the
+   * [_urlMappings].
+   */
+  final List<String> extensionFilePaths = <String>[];
+
   /// Construct a [SdkExtUriResolver] from a package map
   /// (see [PackageMapProvider]).
   SdkExtUriResolver(Map<String, List<Folder>> packageMap) {
@@ -147,18 +153,27 @@
     if ((sdkExt == null) || (sdkExt is! Map)) {
       return;
     }
-    sdkExt.forEach((k, v) => _processSdkExtension(k, v, libDir));
+    bool contributed = false;
+    sdkExt.forEach((k, v) {
+      if (_processSdkExtension(k, v, libDir)) {
+        contributed = true;
+      }
+    });
+    if (contributed) {
+      extensionFilePaths.add(libDir.getChild(SDK_EXT_NAME).path);
+    }
   }
 
   /// Install the mapping from [name] to [libDir]/[file].
-  void _processSdkExtension(String name, String file, Folder libDir) {
+  bool _processSdkExtension(String name, String file, Folder libDir) {
     if (!name.startsWith(DART_COLON_PREFIX)) {
       // SDK extensions must begin with 'dart:'.
-      return;
+      return false;
     }
     var key = name;
     var value = libDir.canonicalizePath(file);
     _urlMappings[key] = value;
+    return true;
   }
 
   /// Read the contents of [libDir]/[SDK_EXT_NAME] as a string.
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index 6abd7bd..3755353 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -8,6 +8,7 @@
 import 'dart:core' hide Resource;
 import 'dart:io' as io;
 
+import 'package:analyzer/context/declared_variables.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:analyzer/source/analysis_options_provider.dart';
@@ -25,7 +26,6 @@
 import 'package:package_config/packages.dart';
 import 'package:package_config/packages_file.dart';
 import 'package:package_config/src/packages_impl.dart';
-import 'package:path/path.dart' as path;
 import 'package:yaml/yaml.dart';
 
 /**
@@ -75,48 +75,83 @@
   ResolverProvider packageResolverProvider;
 
   /**
+   * The resolver provider used to create a file: URI resolver, or `null` if
+   * the normal file URI resolver is to be used.
+   */
+  ResolverProvider fileResolverProvider;
+
+  /**
    * The file path of the .packages file that should be used in place of any
-   * file found using the normal (Package Specification DEP) lookup mechanism.
+   * file found using the normal (Package Specification DEP) lookup mechanism,
+   * or `null` if the normal lookup mechanism should be used.
    */
   String defaultPackageFilePath;
 
   /**
    * The file path of the packages directory that should be used in place of any
-   * file found using the normal (Package Specification DEP) lookup mechanism.
+   * file found using the normal (Package Specification DEP) lookup mechanism,
+   * or `null` if the normal lookup mechanism should be used.
    */
   String defaultPackagesDirectoryPath;
 
   /**
    * The file path of the analysis options file that should be used in place of
-   * any file in the root directory.
+   * any file in the root directory or a parent of the root directory, or `null`
+   * if the normal lookup mechanism should be used.
    */
   String defaultAnalysisOptionsFilePath;
 
   /**
    * The default analysis options that should be used unless some or all of them
-   * are overridden in the analysis options file.
+   * are overridden in the analysis options file, or `null` if the default
+   * defaults should be used.
    */
   AnalysisOptions defaultOptions;
 
   /**
+   * A table mapping variable names to values for the declared variables, or
+   * `null` if no additional variables should be declared.
+   */
+  Map<String, String> declaredVariables;
+
+  /**
    * Initialize a newly created builder to be ready to build a context rooted in
    * the directory with the given [rootDirectoryPath].
    */
   ContextBuilder(this.resourceProvider, this.sdkManager, this.contentCache);
 
-  AnalysisContext buildContext(String rootDirectoryPath) {
+  /**
+   * Return an analysis context that is configured correctly to analyze code in
+   * the directory with the given [path].
+   *
+   * *Note:* This method is not yet fully implemented and should not be used.
+   */
+  AnalysisContext buildContext(String path) {
     // TODO(brianwilkerson) Split getAnalysisOptions so we can capture the
     // option map and use it to run the options processors.
-    AnalysisOptions options = getAnalysisOptions(rootDirectoryPath);
+    AnalysisOptions options = getAnalysisOptions(path);
     InternalAnalysisContext context =
         AnalysisEngine.instance.createAnalysisContext();
     context.contentCache = contentCache;
-    context.sourceFactory = createSourceFactory(rootDirectoryPath, options);
+    context.sourceFactory = createSourceFactory(path, options);
     context.analysisOptions = options;
     //_processAnalysisOptions(context, optionMap);
+    declareVariables(context);
     return context;
   }
 
+  Map<String, List<Folder>> convertPackagesToMap(Packages packages) {
+    if (packages == null || packages == Packages.noPackages) {
+      return null;
+    }
+    Map<String, List<Folder>> folderMap = new HashMap<String, List<Folder>>();
+    packages.asMap().forEach((String packagePath, Uri uri) {
+      String path = resourceProvider.pathContext.fromUri(uri);
+      folderMap[packagePath] = [resourceProvider.getFolder(path)];
+    });
+    return folderMap;
+  }
+
 //  void _processAnalysisOptions(
 //      AnalysisContext context, Map<String, YamlNode> optionMap) {
 //    List<OptionsProcessor> optionsProcessors =
@@ -140,15 +175,14 @@
 //    }
 //  }
 
-  Map<String, List<Folder>> convertPackagesToMap(Packages packages) {
-    if (packages == null || packages == Packages.noPackages) {
-      return null;
+  /**
+   * Return an analysis options object containing the default option values.
+   */
+  AnalysisOptions createDefaultOptions() {
+    if (defaultOptions == null) {
+      return new AnalysisOptionsImpl();
     }
-    Map<String, List<Folder>> folderMap = new HashMap<String, List<Folder>>();
-    packages.asMap().forEach((String packagePath, Uri uri) {
-      folderMap[packagePath] = [resourceProvider.getFolder(path.fromUri(uri))];
-    });
-    return folderMap;
+    return new AnalysisOptionsImpl.from(defaultOptions);
   }
 
   Packages createPackageMap(String rootDirectoryPath) {
@@ -169,17 +203,23 @@
 
   SourceFactory createSourceFactory(
       String rootDirectoryPath, AnalysisOptions options) {
+    Folder _folder = null;
+    Folder folder() {
+      return _folder ??= resourceProvider.getResource('.');
+    }
+    UriResolver fileResolver = fileResolverProvider == null
+        ? new ResourceUriResolver(resourceProvider)
+        : fileResolverProvider(folder());
     if (packageResolverProvider != null) {
-      Folder folder = resourceProvider.getResource('.');
-      UriResolver resolver = packageResolverProvider(folder);
-      if (resolver != null) {
+      UriResolver packageResolver = packageResolverProvider(folder());
+      if (packageResolver != null) {
         // TODO(brianwilkerson) This doesn't support either embedder files or
         // sdk extensions because we don't have a way to get the package map
         // from the resolver.
         List<UriResolver> resolvers = <UriResolver>[
           new DartUriResolver(findSdk(null, options)),
-          resolver,
-          new ResourceUriResolver(resourceProvider)
+          packageResolver,
+          fileResolver
         ];
         return new SourceFactory(resolvers);
       }
@@ -189,36 +229,79 @@
     List<UriResolver> resolvers = <UriResolver>[];
     resolvers.add(new DartUriResolver(findSdk(packageMap, options)));
     if (packageMap != null) {
-      resolvers.add(new SdkExtUriResolver(packageMap));
       resolvers.add(new PackageMapUriResolver(resourceProvider, packageMap));
     }
-    resolvers.add(new ResourceUriResolver(resourceProvider));
+    resolvers.add(fileResolver);
     return new SourceFactory(resolvers);
   }
 
   /**
-   * Use the given [packageMap] and [options] to locate the SDK.
+   * Add any [declaredVariables] to the list of declared variables used by the
+   * given [context].
+   */
+  void declareVariables(InternalAnalysisContext context) {
+    if (declaredVariables != null && declaredVariables.isNotEmpty) {
+      DeclaredVariables contextVariables = context.declaredVariables;
+      declaredVariables.forEach((String variableName, String value) {
+        contextVariables.define(variableName, value);
+      });
+    }
+  }
+
+  /**
+   * Return the SDK that should be used to analyze code. Use the given
+   * [packageMap] and [options] to locate the SDK.
    */
   DartSdk findSdk(
       Map<String, List<Folder>> packageMap, AnalysisOptions options) {
     if (packageMap != null) {
+      // TODO(brianwilkerson) Fix it so that we don't have to create a resolver
+      // to figure out what the extensions are.
+      SdkExtUriResolver extResolver = new SdkExtUriResolver(packageMap);
+      List<String> extFilePaths = extResolver.extensionFilePaths;
       EmbedderYamlLocator locator = new EmbedderYamlLocator(packageMap);
       Map<Folder, YamlMap> embedderYamls = locator.embedderYamls;
       EmbedderSdk embedderSdk = new EmbedderSdk(embedderYamls);
       if (embedderSdk.sdkLibraries.length > 0) {
+        //
+        // There is an embedder file that defines the content of the SDK and
+        // there might be an extension file that extends it.
+        //
         List<String> paths = <String>[];
         for (Folder folder in embedderYamls.keys) {
           paths.add(folder
               .getChildAssumingFile(EmbedderYamlLocator.EMBEDDER_FILE_NAME)
               .path);
         }
+        paths.addAll(extFilePaths);
         SdkDescription description = new SdkDescription(paths, options);
         DartSdk dartSdk = sdkManager.getSdk(description, () {
+          if (extFilePaths.isNotEmpty) {
+            embedderSdk.addExtensions(extResolver.urlMappings);
+          }
           embedderSdk.analysisOptions = options;
           embedderSdk.useSummary = sdkManager.canUseSummaries;
           return embedderSdk;
         });
         return dartSdk;
+      } else if (extFilePaths != null) {
+        //
+        // We have an extension file, but no embedder file.
+        //
+        String sdkPath = sdkManager.defaultSdkDirectory;
+        List<String> paths = <String>[sdkPath];
+        paths.addAll(extFilePaths);
+        SdkDescription description = new SdkDescription(paths, options);
+        return sdkManager.getSdk(description, () {
+          DirectoryBasedDartSdk sdk =
+              new DirectoryBasedDartSdk(new JavaFile(sdkPath));
+          if (extFilePaths.isNotEmpty) {
+            embedderSdk.addExtensions(extResolver.urlMappings);
+          }
+          sdk.analysisOptions = options;
+          sdk.useSummary = sdkManager.canUseSummaries;
+          return sdk;
+        });
       }
     }
     String sdkPath = sdkManager.defaultSdkDirectory;
@@ -232,9 +315,13 @@
     });
   }
 
-  AnalysisOptions getAnalysisOptions(String rootDirectoryPath) {
-    AnalysisOptionsImpl options = new AnalysisOptionsImpl.from(defaultOptions);
-    File optionsFile = getOptionsFile(rootDirectoryPath);
+  /**
+   * Return the analysis options that should be used when analyzing code in the
+   * directory with the given [path].
+   */
+  AnalysisOptions getAnalysisOptions(String path) {
+    AnalysisOptionsImpl options = createDefaultOptions();
+    File optionsFile = getOptionsFile(path);
     if (optionsFile != null) {
       Map<String, YamlNode> fileOptions =
           new AnalysisOptionsProvider().getOptionsFromFile(optionsFile);
@@ -243,11 +330,15 @@
     return options;
   }
 
-  File getOptionsFile(String rootDirectoryPath) {
+  /**
+   * Return the analysis options file that should be used when analyzing code in
+   * the directory with the given [path].
+   */
+  File getOptionsFile(String path) {
     if (defaultAnalysisOptionsFilePath != null) {
       return resourceProvider.getFile(defaultAnalysisOptionsFilePath);
     }
-    Folder root = resourceProvider.getFolder(rootDirectoryPath);
+    Folder root = resourceProvider.getFolder(path);
     for (Folder folder = root; folder != null; folder = folder.parent) {
       File file =
           folder.getChildAssumingFile(AnalysisEngine.ANALYSIS_OPTIONS_FILE);
diff --git a/pkg/analyzer/lib/src/context/cache.dart b/pkg/analyzer/lib/src/context/cache.dart
index 1f0f42c..50207ac 100644
--- a/pkg/analyzer/lib/src/context/cache.dart
+++ b/pkg/analyzer/lib/src/context/cache.dart
@@ -7,6 +7,7 @@
 import 'dart:async';
 import 'dart:collection';
 
+import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/element/element.dart'
     show ElementImpl, Modifier;
 import 'package:analyzer/src/generated/engine.dart';
@@ -17,6 +18,11 @@
 import 'package:analyzer/task/model.dart';
 
 /**
+ * The cache results visiting function type.
+ */
+typedef void CacheResultVisitor(AnalysisTarget target, ResultData data);
+
+/**
  * Return `true` if the [result] of the [target] should be flushed.
  */
 typedef bool FlushResultFilter<V>(
@@ -296,9 +302,9 @@
   static int _EXPLICITLY_ADDED_FLAG = 0;
 
   /**
-   * The next invalidation process identifier.
+   * The next visit process identifier.
    */
-  static int nextInvalidateId = 0;
+  static int nextVisitId = 0;
 
   /**
    * A table containing the number of times the value of a result descriptor was
@@ -340,9 +346,7 @@
   Map<ResultDescriptor, ResultData> _resultMap =
       new HashMap<ResultDescriptor, ResultData>();
 
-  CacheEntry(this.target) {
-    _markAsCacheKey(target);
-  }
+  CacheEntry(this.target);
 
   /**
    * The exception that caused one or more values to have a state of
@@ -391,10 +395,6 @@
       }
     });
     _resultMap.clear();
-    AnalysisTarget oldTarget = target;
-    if (oldTarget is ElementImpl) {
-      oldTarget.setModifier(Modifier.CACHE_KEY, false);
-    }
   }
 
   /**
@@ -526,7 +526,12 @@
     if (state == CacheState.INVALID) {
       ResultData data = _resultMap[descriptor];
       if (data != null) {
-        _invalidate(nextInvalidateId++, descriptor, delta, 0);
+        bool canUseDelta =
+            _gatherResultsInvalidatedByDelta(descriptor, delta, 0);
+        if (!canUseDelta) {
+          delta = null;
+        }
+        _invalidate(nextVisitId++, descriptor, delta, 0);
       }
     } else {
       ResultData data = getResultData(descriptor);
@@ -583,7 +588,7 @@
       data.value = value;
     }
     if (invalidateDependent) {
-      _invalidateDependentResults(nextInvalidateId++, data, null, 0);
+      _invalidateDependentResults(nextVisitId++, data, null, 0);
     }
   }
 
@@ -595,6 +600,35 @@
   }
 
   /**
+   * Visit the given [result] and all results that depend on it, and
+   * ask [delta] to gather changes. Return `true` if the [delta] can be used
+   * to perform limited invalidation, or `false` if the changes collection
+   * process does not stop (should not happen).
+   */
+  bool _gatherResultsInvalidatedByDelta(
+      ResultDescriptor result, Delta delta, int level) {
+    if (delta == null) {
+      return false;
+    }
+    for (int i = 0; i < 64; i++) {
+      bool hasVisitChanges = false;
+      _visitResults(nextVisitId++, result,
+          (AnalysisTarget target, ResultData data) {
+        bool hasDeltaChanges = delta.gatherChanges(
+            _partition.context, target, data.descriptor, data.value);
+        if (hasDeltaChanges) {
+          hasVisitChanges = true;
+        }
+      });
+      delta.gatherEnd();
+      if (!hasVisitChanges) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
    * Return the value of the flag with the given [index].
    */
   bool _getFlag(int index) => BooleanArray.get(_flags, index);
@@ -611,10 +645,10 @@
     }
     // Stop if already validated.
     if (delta != null) {
-      if (thisData.invalidateId == id) {
+      if (thisData.visitId == id) {
         return;
       }
-      thisData.invalidateId = id;
+      thisData.visitId = id;
     }
     // Ask the delta to validate.
     DeltaResult deltaResult = null;
@@ -687,7 +721,7 @@
     int length = results.length;
     for (int i = 0; i < length; i++) {
       ResultDescriptor result = results[i];
-      _invalidate(nextInvalidateId++, result, null, 0);
+      _invalidate(nextVisitId++, result, null, 0);
     }
   }
 
@@ -715,15 +749,6 @@
   }
 
   /**
-   * If the given `target` is an element, mark it as being a cache key.
-   */
-  void _markAsCacheKey(AnalysisTarget target) {
-    if (target is ElementImpl) {
-      target.setModifier(Modifier.CACHE_KEY, true);
-    }
-  }
-
-  /**
    * Set the [dependedOn] on which this result depends.
    */
   void _setDependedOnResults(ResultData thisData, TargetedResult thisResult,
@@ -754,10 +779,8 @@
         AnalysisCache cache = caches[j];
         CacheEntry entry = cache.get(dependedOnResult.target);
         if (entry != null) {
-          ResultData data = entry.getResultDataOrNull(dependedOnResult.result);
-          if (data != null) {
-            data.dependentResults.add(thisResult);
-          }
+          ResultData data = entry.getResultData(dependedOnResult.result);
+          data.dependentResults.add(thisResult);
         }
       }
     }
@@ -818,6 +841,41 @@
   }
 
   /**
+   * Call [visitor] for the result described by the given [descriptor] and all
+   * results that depend on directly or indirectly. Each result is visited
+   * only once.
+   */
+  void _visitResults(
+      int id, ResultDescriptor descriptor, CacheResultVisitor visitor) {
+    ResultData thisData = _resultMap[descriptor];
+    if (thisData == null) {
+      return;
+    }
+    // Stop if already visited.
+    if (thisData.visitId == id) {
+      return;
+    }
+    thisData.visitId = id;
+    // Visit this result.
+    visitor(target, thisData);
+    // Visit results that depend on this result.
+    List<AnalysisCache> caches = _partition.containingCaches;
+    int cacheLength = caches.length;
+    List<TargetedResult> dependentResults = thisData.dependentResults.toList();
+    int resultLength = dependentResults.length;
+    for (int i = 0; i < resultLength; i++) {
+      TargetedResult dependentResult = dependentResults[i];
+      for (int j = 0; j < cacheLength; j++) {
+        AnalysisCache cache = caches[j];
+        CacheEntry entry = cache.get(dependentResult.target);
+        if (entry != null) {
+          entry._visitResults(id, dependentResult.result, visitor);
+        }
+      }
+    }
+  }
+
+  /**
    * Write a textual representation of this entry to the given [buffer]. The
    * result should only be used for debugging purposes.
    */
@@ -1185,6 +1243,16 @@
 
   Delta(this.source);
 
+  bool gatherChanges(InternalAnalysisContext context, AnalysisTarget target,
+      ResultDescriptor descriptor, Object value) {
+    return false;
+  }
+
+  /**
+   * The current cache results visit is done.
+   */
+  void gatherEnd() {}
+
   /**
    * Check whether this delta affects the result described by the given
    * [descriptor] and [target]. The current [value] of the result is provided.
@@ -1250,6 +1318,29 @@
 }
 
 /**
+ * A cache partition that contains all of the targets in a single package.
+ */
+class PackageCachePartition extends CachePartition {
+  /**
+   * The root of the directory representing the package.
+   */
+  final Folder packageRoot;
+
+  /**
+   * Initialize a newly created cache partition, belonging to the given
+   * [context].
+   */
+  PackageCachePartition(InternalAnalysisContext context, this.packageRoot)
+      : super(context);
+
+  @override
+  bool isResponsibleFor(AnalysisTarget target) {
+    Source source = target.source;
+    return source != null && packageRoot.contains(source.fullName);
+  }
+}
+
+/**
  * A Stream-like interface, which broadcasts events synchronously.
  * If a second event is fired while delivering a first event, then the second
  * event will be delivered first, and then delivering of the first will be
@@ -1320,11 +1411,10 @@
   Object value;
 
   /**
-   * The identifier of the invalidation process that most recently checked
-   * this value. If it is the same as the current invalidation identifier,
-   * then there is no reason to check it (and its subtree again).
+   * The identifier of the most recent visiting process. We use it to visit
+   * every result only once.
    */
-  int invalidateId = -1;
+  int visitId = -1;
 
   /**
    * A list of the results on which this result depends.
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index 27098db..7ef0108 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -34,6 +34,7 @@
 import 'package:analyzer/src/task/driver.dart';
 import 'package:analyzer/src/task/incremental_element_builder.dart';
 import 'package:analyzer/src/task/manager.dart';
+import 'package:analyzer/src/task/model.dart';
 import 'package:analyzer/task/dart.dart';
 import 'package:analyzer/task/general.dart';
 import 'package:analyzer/task/html.dart';
@@ -41,6 +42,13 @@
 import 'package:html/dom.dart' show Document;
 
 /**
+ * The descriptor used to associate exclude patterns with an analysis context in
+ * configuration data.
+ */
+final ListResultDescriptor<String> CONTEXT_EXCLUDES =
+    new ListResultDescriptorImpl('CONTEXT_EXCLUDES', const <String>[]);
+
+/**
  * Type of callback functions used by PendingFuture. Functions of this type
  * should perform a computation based on the data in [entry] and return it. If
  * the computation can't be performed yet because more analysis is needed,
@@ -158,6 +166,8 @@
    */
   List<Source> _priorityOrder = <Source>[];
 
+  CacheConsistencyValidatorImpl _cacheConsistencyValidator;
+
   /**
    * A map from all sources for which there are futures pending to a list of
    * the corresponding PendingFuture objects.  These sources will be analyzed
@@ -347,6 +357,9 @@
     driver.reset();
   }
 
+  CacheConsistencyValidator get cacheConsistencyValidator =>
+      _cacheConsistencyValidator ??= new CacheConsistencyValidatorImpl(this);
+
   @override
   set contentCache(ContentCache value) {
     _contentCache = value;
@@ -1375,57 +1388,6 @@
   }
 
   @override
-  bool validateCacheConsistency() {
-    int consistencyCheckStart = JavaSystem.nanoTime();
-    HashSet<Source> changedSources = new HashSet<Source>();
-    HashSet<Source> missingSources = new HashSet<Source>();
-    for (Source source in _cache.sources) {
-      CacheEntry entry = _cache.get(source);
-      int sourceTime = getModificationStamp(source);
-      if (sourceTime != entry.modificationTime) {
-        changedSources.add(source);
-      }
-      if (entry.exception != null) {
-        if (!exists(source)) {
-          missingSources.add(source);
-        }
-      }
-    }
-    for (Source source in changedSources) {
-      _sourceChanged(source);
-    }
-    int removalCount = 0;
-    for (Source source in missingSources) {
-      if (getLibrariesContaining(source).isEmpty &&
-          getLibrariesDependingOn(source).isEmpty) {
-        _removeFromCache(source);
-        removalCount++;
-      }
-    }
-    int consistencyCheckEnd = JavaSystem.nanoTime();
-    if (changedSources.length > 0 || missingSources.length > 0) {
-      StringBuffer buffer = new StringBuffer();
-      buffer.write("Consistency check took ");
-      buffer.write((consistencyCheckEnd - consistencyCheckStart) / 1000000.0);
-      buffer.writeln(" ms and found");
-      buffer.write("  ");
-      buffer.write(changedSources.length);
-      buffer.writeln(" inconsistent entries");
-      buffer.write("  ");
-      buffer.write(missingSources.length);
-      buffer.write(" missing sources (");
-      buffer.write(removalCount);
-      buffer.writeln(" removed");
-      for (Source source in missingSources) {
-        buffer.write("    ");
-        buffer.writeln(source.fullName);
-      }
-      _logInformation(buffer.toString());
-    }
-    return changedSources.length > 0;
-  }
-
-  @override
   void visitContentCache(ContentCacheVisitor visitor) {
     _contentCache.accept(visitor);
   }
@@ -1871,21 +1833,25 @@
     // (For example, in getLibrariesContaining.)
     entry.setState(CONTENT, CacheState.FLUSHED);
 
-    if (oldContents != null) {
-      // Fast path if the content is the same as it was last time.
-      try {
-        TimestampedData<String> fileContents = getContents(source);
-        if (fileContents.data == oldContents) {
-          int time = fileContents.modificationTime;
-          for (CacheEntry entry in _entriesFor(source)) {
-            entry.modificationTime = time;
-          }
-          return;
-        }
-      } catch (e) {
-        entry.modificationTime = -1;
+    // Prepare the new contents.
+    TimestampedData<String> fileContents;
+    try {
+      fileContents = getContents(source);
+    } catch (e) {}
+
+    // Update 'modificationTime' - we are going to update the entry.
+    {
+      int time = fileContents?.modificationTime ?? -1;
+      for (CacheEntry entry in _entriesFor(source)) {
+        entry.modificationTime = time;
       }
     }
+
+    // Fast path if the contents is the same as it was last time.
+    if (oldContents != null && fileContents?.data == oldContents) {
+      return;
+    }
+
     // We need to invalidate the cache.
     {
       if (analysisOptions.finerGrainedInvalidation &&
@@ -1910,18 +1876,12 @@
             builder.build();
             CompilationUnitElementDelta unitDelta = builder.unitDelta;
             if (!unitDelta.hasDirectiveChange) {
+              unitEntry.setValueIncremental(
+                  COMPILATION_UNIT_CONSTANTS, builder.unitConstants, false);
               DartDelta dartDelta = new DartDelta(source);
-              dartDelta.hasDirectiveChange = unitDelta.hasDirectiveChange;
               unitDelta.addedDeclarations.forEach(dartDelta.elementChanged);
               unitDelta.removedDeclarations.forEach(dartDelta.elementChanged);
               unitDelta.classDeltas.values.forEach(dartDelta.classChanged);
-              // Add other names in the library that are changed transitively.
-              {
-                ReferencedNames referencedNames = new ReferencedNames(source);
-                new ReferencedNamesBuilder(referencedNames).build(oldUnit);
-                dartDelta.addChangedElements(referencedNames);
-              }
-              // Invalidate using the prepared DartDelta.
               entry.setState(CONTENT, CacheState.INVALID, delta: dartDelta);
               return;
             }
@@ -2097,6 +2057,86 @@
   }
 }
 
+class CacheConsistencyValidatorImpl implements CacheConsistencyValidator {
+  final AnalysisContextImpl context;
+
+  CacheConsistencyValidatorImpl(this.context);
+
+  @override
+  List<Source> getSourcesToComputeModificationTimes() {
+    return context._privatePartition.sources.toList();
+  }
+
+  @override
+  bool sourceModificationTimesComputed(List<Source> sources, List<int> times) {
+    int consistencyCheckStart = JavaSystem.nanoTime();
+    HashSet<Source> changedSources = new HashSet<Source>();
+    HashSet<Source> missingSources = new HashSet<Source>();
+    for (int i = 0; i < sources.length; i++) {
+      Source source = sources[i];
+      // When a source is in the content cache,
+      // its modification time in the file system does not matter.
+      if (context._contentCache.getModificationStamp(source) != null) {
+        continue;
+      }
+      // When we were not able to compute the modification time in the
+      // file system, there is nothing to compare with, so skip the source.
+      int sourceTime = times[i];
+      if (sourceTime == null) {
+        continue;
+      }
+      // Compare with the modification time in the cache entry.
+      CacheEntry entry = context._privatePartition.get(source);
+      if (entry != null) {
+        if (sourceTime != entry.modificationTime) {
+          changedSources.add(source);
+          PerformanceStatistics
+              .cacheConsistencyValidationStatistics.numOfModified++;
+        }
+        if (entry.exception != null) {
+          if (sourceTime == -1) {
+            missingSources.add(source);
+            PerformanceStatistics
+                .cacheConsistencyValidationStatistics.numOfModified++;
+          }
+        }
+      }
+    }
+    for (Source source in changedSources) {
+      context._sourceChanged(source);
+    }
+    int removalCount = 0;
+    for (Source source in missingSources) {
+      if (context.getLibrariesContaining(source).isEmpty &&
+          context.getLibrariesDependingOn(source).isEmpty) {
+        context._removeFromCache(source);
+        removalCount++;
+      }
+    }
+    int consistencyCheckEnd = JavaSystem.nanoTime();
+    if (changedSources.length > 0 || missingSources.length > 0) {
+      StringBuffer buffer = new StringBuffer();
+      buffer.write("Consistency check took ");
+      buffer.write((consistencyCheckEnd - consistencyCheckStart) / 1000000.0);
+      buffer.writeln(" ms and found");
+      buffer.write("  ");
+      buffer.write(changedSources.length);
+      buffer.writeln(" inconsistent entries");
+      buffer.write("  ");
+      buffer.write(missingSources.length);
+      buffer.write(" missing sources (");
+      buffer.write(removalCount);
+      buffer.writeln(" removed");
+      for (Source source in missingSources) {
+        buffer.write("    ");
+        buffer.writeln(source.fullName);
+      }
+      context._logInformation(buffer.toString());
+    }
+    return changedSources.length > 0;
+  }
+}
+
 /**
  * An object that manages the partitions that can be shared between analysis
  * contexts.
diff --git a/pkg/analyzer/lib/src/context/context_factory.dart b/pkg/analyzer/lib/src/context/context_factory.dart
deleted file mode 100644
index b96100d..0000000
--- a/pkg/analyzer/lib/src/context/context_factory.dart
+++ /dev/null
@@ -1,136 +0,0 @@
-// 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.context_factory;
-
-import 'dart:convert';
-import 'dart:core' hide Resource;
-
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:yaml/yaml.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'dart:io' as io;
-
-/// (Placeholder)
-abstract class ContextFactory {
-  /// Create an analysis context for the given [source] directory or file, with
-  /// the given [defaultOptions].
-  AnalysisContext createContext(
-      io.FileSystemEntity source, AnalysisOptions defaultOptions);
-}
-
-/// Processes package maps, extracting SDK embedders and extenders, creating a
-/// consolidated [libraryMap].
-class PackageMapProcessor {
-  static const String _EMBEDDED_LIB_MAP_KEY = 'embedded_libs';
-  static const String _EMBEDDER_FILE_NAME = '_embedder.yaml';
-  static const String _SDK_EXT_NAME = '_sdkext';
-
-  /// Map of processed embedder libraries.
-  final LibraryMap embeddedLibraries = new LibraryMap();
-
-  /// Map of processed SDK extension libraries.
-  final LibraryMap extendedLibraries = new LibraryMap();
-
-  /// Combined map of processed libraries.
-  LibraryMap get libraryMap {
-    LibraryMap libraryMap = new LibraryMap();
-
-    // Add extenders first, allowing for overwrite by embedders who take precedence.
-    for (String uri in extendedLibraries.uris) {
-      libraryMap.setLibrary(uri, extendedLibraries.getLibrary(uri));
-    }
-    for (String uri in embeddedLibraries.uris) {
-      libraryMap.setLibrary(uri, embeddedLibraries.getLibrary(uri));
-    }
-    return libraryMap;
-  }
-
-  /// Create a processor for the given [packageMap].
-  PackageMapProcessor(Map<String, List<Folder>> packageMap) {
-    packageMap?.forEach(_processPackage);
-  }
-
-  /// Whether the package map contains an SDK embedder.
-  bool get hasEmbedder => embeddedLibraries.size() > 0;
-
-  /// Whether the package map contains an SDK extension.
-  bool get hasSdkExtension => extendedLibraries.size() > 0;
-
-  void _processEmbedderYaml(String embedderYaml, Folder libDir) {
-    try {
-      YamlNode map = loadYaml(embedderYaml);
-      if (map is YamlMap) {
-        YamlNode embedded_libs = map[_EMBEDDED_LIB_MAP_KEY];
-        if (embedded_libs is YamlMap) {
-          embedded_libs.forEach(
-              (k, v) => _processMapping(embeddedLibraries, k, v, libDir));
-        }
-      }
-    } catch (_) {
-      // Ignored.
-    }
-  }
-
-  void _processMapping(
-      LibraryMap libraryMap, String name, String file, Folder libDir) {
-    if (!_hasDartPrefix(name)) {
-      // SDK libraries must begin with 'dart:'.
-      return;
-    }
-    if (libraryMap.getLibrary(name) != null) {
-      // Libraries can't be redefined.
-      return;
-    }
-    String libPath = libDir.canonicalizePath(file);
-    SdkLibraryImpl library = new SdkLibraryImpl(name)..path = libPath;
-    libraryMap.setLibrary(name, library);
-  }
-
-  void _processPackage(String name, List<Folder> libDirs) {
-    for (Folder libDir in libDirs) {
-      String embedderYaml = _readEmbedderYaml(libDir);
-      if (embedderYaml != null) {
-        _processEmbedderYaml(embedderYaml, libDir);
-      }
-      String sdkExt = _readDotSdkExt(libDir);
-      if (sdkExt != null) {
-        _processSdkExt(sdkExt, libDir);
-      }
-    }
-  }
-
-  void _processSdkExt(String sdkExtJSON, Folder libDir) {
-    try {
-      var sdkExt = JSON.decode(sdkExtJSON);
-      if (sdkExt is Map) {
-        sdkExt.forEach(
-            (k, v) => _processMapping(extendedLibraries, k, v, libDir));
-      }
-    } catch (_) {
-      // Ignored.
-    }
-  }
-
-  static bool _hasDartPrefix(String uri) =>
-      uri.startsWith(DartSdk.DART_LIBRARY_PREFIX);
-
-  static String _readDotSdkExt(Folder libDir) =>
-      _safeRead(libDir.getChild(_SDK_EXT_NAME));
-
-  static String _readEmbedderYaml(Folder libDir) =>
-      _safeRead(libDir.getChild(_EMBEDDER_FILE_NAME));
-
-  static String _safeRead(Resource file) {
-    try {
-      if (file is File) {
-        return file.readAsStringSync();
-      }
-    } on FileSystemException {
-      // File can't be read.
-    }
-    return null;
-  }
-}
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 0c8288a..57eee89 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -23,7 +23,6 @@
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
-import 'package:analyzer/src/generated/source.dart' show Source;
 import 'package:analyzer/src/generated/type_system.dart'
     show TypeSystem, TypeSystemImpl;
 import 'package:analyzer/src/generated/utilities_collection.dart';
@@ -930,15 +929,13 @@
    */
   final ConstantEvaluationEngine evaluationEngine;
 
-  final AnalysisContext _context;
-
   /**
    * Initialize a newly created constant value computer. The [typeProvider] is
    * the type provider used to access known types. The [declaredVariables] is
    * the set of variables declared on the command line using '-D'.
    */
-  ConstantValueComputer(this._context, TypeProvider typeProvider,
-      DeclaredVariables declaredVariables,
+  ConstantValueComputer(
+      TypeProvider typeProvider, DeclaredVariables declaredVariables,
       [ConstantEvaluationValidator validator, TypeSystem typeSystem])
       : evaluationEngine = new ConstantEvaluationEngine(
             typeProvider, declaredVariables,
@@ -948,9 +945,8 @@
    * Add the constants in the given compilation [unit] to the list of constants
    * whose value needs to be computed.
    */
-  void add(CompilationUnit unit, Source source, Source librarySource) {
-    ConstantFinder constantFinder =
-        new ConstantFinder(_context, source, librarySource);
+  void add(CompilationUnit unit) {
+    ConstantFinder constantFinder = new ConstantFinder();
     unit.accept(constantFinder);
     _constantsToCompute.addAll(constantFinder.constantsToCompute);
   }
diff --git a/pkg/analyzer/lib/src/dart/constant/utilities.dart b/pkg/analyzer/lib/src/dart/constant/utilities.dart
index 62b3ec8..90c8a38 100644
--- a/pkg/analyzer/lib/src/dart/constant/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/constant/utilities.dart
@@ -14,8 +14,6 @@
 import 'package:analyzer/src/dart/element/handle.dart'
     show ConstructorElementHandle;
 import 'package:analyzer/src/dart/element/member.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/source.dart' show Source;
 import 'package:analyzer/src/task/dart.dart';
 
 ConstructorElementImpl getConstructorImpl(ConstructorElement constructor) {
@@ -156,10 +154,6 @@
  * those compilation units.
  */
 class ConstantFinder extends RecursiveAstVisitor<Object> {
-  final AnalysisContext context;
-  final Source source;
-  final Source librarySource;
-
   /**
    * The elements and AST nodes whose constant values need to be computed.
    */
@@ -172,8 +166,6 @@
    */
   bool treatFinalInstanceVarAsConst = false;
 
-  ConstantFinder(this.context, this.source, this.librarySource);
-
   @override
   Object visitAnnotation(Annotation node) {
     super.visitAnnotation(node);
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 4619738..7743244 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -474,6 +474,13 @@
   bool _hasBeenInferred = false;
 
   /**
+   * The version of this element. The version is changed when the element is
+   * incrementally updated, so that its lists of constructors, accessors and
+   * methods might be different.
+   */
+  int version = 0;
+
+  /**
    * Initialize a newly created class element to have the given [name] at the
    * given [offset] in the file that contains the declaration of this element.
    */
@@ -2526,7 +2533,7 @@
   /**
    * The compilation unit in which this annotation appears.
    */
-  final CompilationUnitElementImpl compilationUnit;
+  CompilationUnitElementImpl compilationUnit;
 
   /**
    * The AST of the annotation itself, cloned from the resolved AST for the
@@ -2777,7 +2784,6 @@
    */
   void set enclosingElement(Element element) {
     _enclosingElement = element as ElementImpl;
-    _updateCaches();
   }
 
   /**
@@ -2921,7 +2927,6 @@
    */
   void set name(String name) {
     this._name = name;
-    _updateCaches();
   }
 
   @override
@@ -2938,7 +2943,6 @@
    */
   void set nameOffset(int offset) {
     _nameOffset = offset;
-    _updateCaches();
   }
 
   @override
@@ -3150,33 +3154,14 @@
     }
   }
 
-  /**
-   *  Updates cached values after an input changed.
-   *
-   *  Throws [FrozenHashCodeException] if not allowed.
-   */
-  void _updateCaches() {
-    if (!hasModifier(Modifier.CACHE_KEY)) {
-      // Fast path.
-      _cachedLocation = null;
-      _cachedHashCode = null;
-      return;
+  static int _findElementIndexUsingIdentical(List items, Object item) {
+    int length = items.length;
+    for (int i = 0; i < length; i++) {
+      if (identical(items[i], item)) {
+        return i;
+      }
     }
-
-    // Save originals.
-    ElementLocation oldLocation = _cachedLocation;
-    int oldHashCode = _cachedHashCode;
-
-    _cachedLocation = null;
-    _cachedHashCode = null;
-
-    if (oldHashCode != hashCode) {
-      // Prevent cache corruption by restoring originals.
-      _cachedLocation = oldLocation;
-      _cachedHashCode = oldHashCode;
-      throw new FrozenHashCodeException(
-          "can't update hashCode for a cache key: $this ($runtimeType)");
-    }
+    throw new StateError('Unable to find $item in $items');
   }
 }
 
@@ -4343,18 +4328,6 @@
 }
 
 /**
- * Indicates that an ElementImpl's hashCode cannot currently be changed.
- */
-class FrozenHashCodeException implements Exception {
-  final String _message;
-
-  FrozenHashCodeException(this._message);
-
-  @override
-  String toString() => "FrozenHashCodeException($_message)";
-}
-
-/**
  * A concrete implementation of a [FunctionElement].
  */
 class FunctionElementImpl extends ExecutableElementImpl
@@ -4416,8 +4389,11 @@
   @override
   String get identifier {
     String identifier = super.identifier;
-    if (!isStatic) {
-      identifier += "@$nameOffset";
+    Element enclosing = this.enclosingElement;
+    if (enclosing is ExecutableElement) {
+      int id = ElementImpl._findElementIndexUsingIdentical(
+          enclosing.functions, this);
+      identifier += "@$id";
     }
     return identifier;
   }
@@ -6159,10 +6135,14 @@
 
   @override
   String get identifier {
-    int enclosingOffset =
-        enclosingElement != null ? enclosingElement.nameOffset : 0;
-    int delta = nameOffset - enclosingOffset;
-    return '${super.identifier}@$delta';
+    String identifier = super.identifier;
+    Element enclosing = this.enclosingElement;
+    if (enclosing is ExecutableElement) {
+      int id = ElementImpl._findElementIndexUsingIdentical(
+          enclosing.localVariables, this);
+      identifier += "@$id";
+    }
+    return identifier;
   }
 
   @override
@@ -6426,12 +6406,7 @@
    */
   static const Modifier SYNTHETIC = const Modifier('SYNTHETIC', 16);
 
-  /**
-   * Indicates that this element is being used as an analyzer cache key.
-   */
-  static const Modifier CACHE_KEY = const Modifier('CACHE_KEY', 17);
-
-  static const List<Modifier> persistedValues = const [
+  static const List<Modifier> values = const [
     ABSTRACT,
     ASYNCHRONOUS,
     CONST,
@@ -6451,11 +6426,6 @@
     SYNTHETIC
   ];
 
-  static const List<Modifier> transientValues = const [CACHE_KEY];
-
-  static final values = new List.unmodifiable(
-      []..addAll(persistedValues)..addAll(transientValues));
-
   const Modifier(String name, int ordinal) : super(name, ordinal);
 }
 
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 22a247a..df19008 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -1176,6 +1176,11 @@
   final List<FunctionTypeAliasElement> prunedTypedefs;
 
   /**
+   * The version of [element] for which members are cached.
+   */
+  int _versionOfCachedMembers = null;
+
+  /**
    * Cached [ConstructorElement]s - members or raw elements.
    */
   List<ConstructorElement> _constructors;
@@ -1223,6 +1228,7 @@
 
   @override
   List<PropertyAccessorElement> get accessors {
+    _flushCachedMembersIfStale();
     if (_accessors == null) {
       List<PropertyAccessorElement> accessors = element.accessors;
       List<PropertyAccessorElement> members =
@@ -1237,6 +1243,7 @@
 
   @override
   List<ConstructorElement> get constructors {
+    _flushCachedMembersIfStale();
     if (_constructors == null) {
       List<ConstructorElement> constructors = element.constructors;
       List<ConstructorElement> members =
@@ -1331,6 +1338,7 @@
 
   @override
   List<MethodElement> get methods {
+    _flushCachedMembersIfStale();
     if (_methods == null) {
       List<MethodElement> methods = element.methods;
       List<MethodElement> members = new List<MethodElement>(methods.length);
@@ -1891,6 +1899,23 @@
       instantiate(argumentTypes);
 
   /**
+   * Flush cache members if the version of [element] for which members are
+   * cached and the current version of the [element].
+   */
+  void _flushCachedMembersIfStale() {
+    ClassElement element = this.element;
+    if (element is ClassElementImpl) {
+      int currentVersion = element.version;
+      if (_versionOfCachedMembers != currentVersion) {
+        _constructors = null;
+        _accessors = null;
+        _methods = null;
+      }
+      _versionOfCachedMembers = currentVersion;
+    }
+  }
+
+  /**
    * Starting from this type, search its class hierarchy for types of the form
    * Future<R>, and return a list of the resulting R's.
    */
diff --git a/pkg/analyzer/lib/src/dart/resolver/scope.dart b/pkg/analyzer/lib/src/dart/resolver/scope.dart
index 04da23d..9211f8a 100644
--- a/pkg/analyzer/lib/src/dart/resolver/scope.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/scope.dart
@@ -125,7 +125,7 @@
             getSource(identifier),
             identifier.offset,
             identifier.length,
-            CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, []));
+            CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, [name]));
         return hiddenElement;
       }
     }
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index dcb40d6..6c2cd97 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -1100,19 +1100,23 @@
       if (_isConstructorReturnType(node)) {
         _resolver.errorReporter.reportErrorForNode(
             CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node);
+      } else if (parent is Annotation) {
+        _resolver.errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.INVALID_ANNOTATION, parent);
+      } else if (element != null) {
+        _resolver.errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
+            node,
+            [element.name]);
+      } else if (node.name == "await" && _resolver.enclosingFunction != null) {
+        _recordUndefinedNode(
+            _resolver.enclosingClass,
+            StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT,
+            node,
+            [_resolver.enclosingFunction.displayName]);
       } else {
-        if (parent is Annotation) {
-          _resolver.errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.INVALID_ANNOTATION, parent);
-        } else if (element != null) {
-          _resolver.errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
-              node,
-              [element.name]);
-        } else {
-          _recordUndefinedNode(_resolver.enclosingClass,
-              StaticWarningCode.UNDEFINED_IDENTIFIER, node, [node.name]);
-        }
+        _recordUndefinedNode(_resolver.enclosingClass,
+            StaticWarningCode.UNDEFINED_IDENTIFIER, node, [node.name]);
       }
     }
     node.staticElement = element;
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 67a931c7..9cd12c7 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -629,14 +629,6 @@
    * so that the default contents will be returned.
    */
   void setContents(Source source, String contents);
-
-  /**
-   * Check the cache for any invalid entries (entries whose modification time
-   * does not match the modification time of the source associated with the
-   * entry). Invalid entries will be marked as invalid so that the source will
-   * be re-analyzed. Return `true` if at least one entry was invalid.
-   */
-  bool validateCacheConsistency();
 }
 
 /**
@@ -1249,7 +1241,7 @@
   bool enableTiming = false;
 
   @override
-  bool enableTrailingCommas = false;
+  bool enableTrailingCommas = true;
 
   /**
    * A flag indicating whether errors, warnings and hints should be generated
@@ -1553,6 +1545,50 @@
 }
 
 /**
+ * Statistics about cache consistency validation.
+ */
+class CacheConsistencyValidationStatistics {
+  /**
+   * Number of sources which were modified, but the context was not notified
+   * about it, so this fact was detected only during cache consistency
+   * validation.
+   */
+  int numOfModified = 0;
+
+  /**
+   * Number of sources which were deleted, but the context was not notified
+   * about it, so this fact was detected only during cache consistency
+   * validation.
+   */
+  int numOfDeleted = 0;
+}
+
+/**
+ * Interface for cache consistency validation in an [InternalAnalysisContext].
+ */
+abstract class CacheConsistencyValidator {
+  /**
+   * Return sources for which the contexts needs to know modification times.
+   */
+  List<Source> getSourcesToComputeModificationTimes();
+
+  /**
+   * Notify the validator that modification [times] were computed for [sources].
+   * If a source does not exist, its modification time is `-1`.
+   *
+   * It's up to the validator and the context how to use this information,
+   * the list of sources the context has might have been changed since the
+   * previous invocation of [getSourcesToComputeModificationTimes].
+   *
+   * Check the cache for any invalid entries (entries whose modification time
+   * does not match the modification time of the source associated with the
+   * entry). Invalid entries will be marked as invalid so that the source will
+   * be re-analyzed. Return `true` if at least one entry was invalid.
+   */
+  bool sourceModificationTimesComputed(List<Source> sources, List<int> times);
+}
+
+/**
  * The possible states of cached data.
  */
 class CacheState extends Enum<CacheState> {
@@ -2037,6 +2073,11 @@
   AnalysisCache get analysisCache;
 
   /**
+   * The cache consistency validator for this context.
+   */
+  CacheConsistencyValidator get cacheConsistencyValidator;
+
+  /**
    * Allow the client to supply its own content cache.  This will take the
    * place of the content cache created by default, allowing clients to share
    * the content cache between contexts.
@@ -2332,6 +2373,13 @@
    * The [PerformanceTag] for time spent in summaries support.
    */
   static PerformanceTag summary = new PerformanceTag('summary');
+
+  /**
+   * Statistics about cache consistency validation.
+   */
+  static final CacheConsistencyValidationStatistics
+      cacheConsistencyValidationStatistics =
+      new CacheConsistencyValidationStatistics();
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/generated/error.dart b/pkg/analyzer/lib/src/generated/error.dart
index f8b369c..728435f 100644
--- a/pkg/analyzer/lib/src/generated/error.dart
+++ b/pkg/analyzer/lib/src/generated/error.dart
@@ -2223,7 +2223,7 @@
    */
   static const CompileTimeErrorCode REFERENCED_BEFORE_DECLARATION =
       const CompileTimeErrorCode('REFERENCED_BEFORE_DECLARATION',
-          "Local variables cannot be referenced before they are declared");
+          "Local variable '{0}' cannot be referenced before it is declared");
 
   /**
    * 12.8.1 Rethrow: It is a compile-time error if an expression of the form
@@ -2698,6 +2698,7 @@
     HintCode.MISSING_RETURN,
     HintCode.NULL_AWARE_IN_CONDITION,
     HintCode.OVERRIDE_ON_NON_OVERRIDING_GETTER,
+    HintCode.OVERRIDE_ON_NON_OVERRIDING_FIELD,
     HintCode.OVERRIDE_ON_NON_OVERRIDING_METHOD,
     HintCode.OVERRIDE_ON_NON_OVERRIDING_SETTER,
     HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE,
@@ -2881,6 +2882,7 @@
     StrongModeCode.INVALID_SUPER_INVOCATION,
     StrongModeCode.NON_GROUND_TYPE_CHECK_INFO,
     StrongModeCode.STATIC_TYPE_ERROR,
+    StrongModeCode.UNSAFE_BLOCK_CLOSURE_INFERENCE,
 
     TodoCode.TODO,
 
@@ -2894,10 +2896,6 @@
     ParserErrorCode.ABSTRACT_TOP_LEVEL_VARIABLE,
     ParserErrorCode.ABSTRACT_TYPEDEF,
     ParserErrorCode.ANNOTATION_ON_ENUM_CONSTANT,
-    ParserErrorCode.ASSERT_DOES_NOT_TAKE_ASSIGNMENT,
-    ParserErrorCode.ASSERT_DOES_NOT_TAKE_CASCADE,
-    ParserErrorCode.ASSERT_DOES_NOT_TAKE_THROW,
-    ParserErrorCode.ASSERT_DOES_NOT_TAKE_RETHROW,
     ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER,
     ParserErrorCode.ASYNC_NOT_SUPPORTED,
     ParserErrorCode.BREAK_OUTSIDE_OF_LOOP,
@@ -3734,6 +3732,13 @@
       "Getter does not override an inherited getter");
 
   /**
+   * A field with the override annotation does not override a getter or setter.
+   */
+  static const HintCode OVERRIDE_ON_NON_OVERRIDING_FIELD = const HintCode(
+      'OVERRIDE_ON_NON_OVERRIDING_FIELD',
+      "Field does not override an inherited getter or setter");
+
+  /**
    * A method with the override annotation does not override an existing method.
    */
   static const HintCode OVERRIDE_ON_NON_OVERRIDING_METHOD = const HintCode(
@@ -5760,6 +5765,13 @@
       const StaticWarningCode('UNDEFINED_IDENTIFIER', "Undefined name '{0}'");
 
   /**
+   * If the identifier is 'await', be helpful about it.
+   */
+  static const StaticWarningCode UNDEFINED_IDENTIFIER_AWAIT =
+      const StaticWarningCode('UNDEFINED_IDENTIFIER_AWAIT',
+          "Undefined name 'await'; did you mean to add the 'async' marker to '{0}'?");
+
+  /**
    * 12.14.2 Binding Actuals to Formals: Furthermore, each <i>q<sub>i</sub></i>,
    * <i>1<=i<=l</i>, must have a corresponding named parameter in the set
    * {<i>p<sub>n+1</sub></i> &hellip; <i>p<sub>n+k</sub></i>} or a static
@@ -5894,6 +5906,11 @@
   static const String _implicitCastMessage =
       'Unsound implicit cast from {0} to {1}';
 
+  static const String _unsafeBlockClosureInferenceMessage =
+      'Unsafe use of block closure in a type-inferred variable outside a '
+      'function body.  Workaround: add a type annotation for `{0}`.  See '
+      'dartbug.com/26947';
+
   static const String _typeCheckMessage =
       'Type check failed: {0} is not of type {1}';
 
@@ -6041,6 +6058,12 @@
       "Missing type arguments for calling generic function type '{0}'"
       "$_implicitDynamicTip");
 
+  static const StrongModeCode UNSAFE_BLOCK_CLOSURE_INFERENCE =
+      const StrongModeCode(
+          ErrorType.STATIC_WARNING,
+          'UNSAFE_BLOCK_CLOSURE_INFERENCE',
+          _unsafeBlockClosureInferenceMessage);
+
   @override
   final ErrorType type;
 
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 6d4177b..0a54caa 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -3399,29 +3399,34 @@
    */
   void _checkForFieldInitializingFormalRedirectingConstructor(
       FieldFormalParameter parameter) {
-    ConstructorDeclaration constructor =
-        parameter.getAncestor((node) => node is ConstructorDeclaration);
-    if (constructor == null) {
-      _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR,
-          parameter);
-      return;
+    // prepare the node that should be a ConstructorDeclaration
+    AstNode formalParameterList = parameter.parent;
+    if (formalParameterList is! FormalParameterList) {
+      formalParameterList = formalParameterList?.parent;
     }
-    // constructor cannot be a factory
-    if (constructor.factoryKeyword != null) {
-      _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.FIELD_INITIALIZER_FACTORY_CONSTRUCTOR,
-          parameter);
-      return;
-    }
-    // constructor cannot have a redirection
-    for (ConstructorInitializer initializer in constructor.initializers) {
-      if (initializer is RedirectingConstructorInvocation) {
+    AstNode constructor = formalParameterList?.parent;
+    // now check whether the node is actually a ConstructorDeclaration
+    if (constructor is ConstructorDeclaration) {
+      // constructor cannot be a factory
+      if (constructor.factoryKeyword != null) {
         _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR,
+            CompileTimeErrorCode.FIELD_INITIALIZER_FACTORY_CONSTRUCTOR,
             parameter);
         return;
       }
+      // constructor cannot have a redirection
+      for (ConstructorInitializer initializer in constructor.initializers) {
+        if (initializer is RedirectingConstructorInvocation) {
+          _errorReporter.reportErrorForNode(
+              CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR,
+              parameter);
+          return;
+        }
+      }
+    } else {
+      _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR,
+          parameter);
     }
   }
 
@@ -4065,18 +4070,8 @@
     if (lhs == null) {
       return;
     }
-    VariableElement leftVariableElement = getVariableElement(lhs);
-    DartType leftType = (leftVariableElement == null)
-        ? getStaticType(lhs)
-        : leftVariableElement.type;
-    MethodElement invokedMethod = assignment.staticElement;
-    if (invokedMethod == null) {
-      return;
-    }
-    DartType rightType = invokedMethod.type.returnType;
-    if (leftType == null || rightType == null) {
-      return;
-    }
+    DartType leftType = getStaticType(lhs);
+    DartType rightType = getStaticType(assignment);
     if (!_typeSystem.isAssignableTo(rightType, leftType)) {
       _errorReporter.reportTypeErrorForNode(
           StaticTypeWarningCode.INVALID_ASSIGNMENT, rhs, [rightType, leftType]);
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index 77907db..1194f5f 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -95,6 +95,7 @@
         isByTask(BuildSourceExportClosureTask.DESCRIPTOR) ||
         isByTask(ComputeConstantDependenciesTask.DESCRIPTOR) ||
         isByTask(ComputeConstantValueTask.DESCRIPTOR) ||
+        isByTask(ComputeInferableStaticVariableDependenciesTask.DESCRIPTOR) ||
         isByTask(ComputeLibraryCycleTask.DESCRIPTOR) ||
         isByTask(ComputePropagableVariableDependenciesTask.DESCRIPTOR) ||
         isByTask(DartErrorsTask.DESCRIPTOR) ||
@@ -106,6 +107,7 @@
         isByTask(GenerateHintsTask.DESCRIPTOR) ||
         isByTask(InferInstanceMembersInUnitTask.DESCRIPTOR) ||
         isByTask(InferStaticVariableTypesInUnitTask.DESCRIPTOR) ||
+        isByTask(InferStaticVariableTypeTask.DESCRIPTOR) ||
         isByTask(LibraryErrorsReadyTask.DESCRIPTOR) ||
         isByTask(LibraryUnitErrorsTask.DESCRIPTOR) ||
         isByTask(ParseDartTask.DESCRIPTOR) ||
@@ -295,9 +297,9 @@
     // compute values
     {
       CompilationUnit unit = node.getAncestor((n) => n is CompilationUnit);
-      ConstantValueComputer computer = new ConstantValueComputer(_context,
+      ConstantValueComputer computer = new ConstantValueComputer(
           _typeProvider, _context.declaredVariables, null, _typeSystem);
-      computer.add(unit, _source, _librarySource);
+      computer.add(unit);
       computer.computeValues();
     }
     // validate
@@ -740,6 +742,7 @@
       RecordingErrorListener errorListener = new RecordingErrorListener();
       Parser parser = new Parser(_unitSource, errorListener);
       AnalysisOptions options = _unitElement.context.analysisOptions;
+      parser.parseGenericMethodComments = options.strongMode;
       parser.parseGenericMethods = options.enableGenericMethods;
       CompilationUnit unit = parser.parseCompilationUnit(token);
       _newParseErrors = errorListener.errors;
@@ -819,6 +822,8 @@
     RecordingErrorListener errorListener = new RecordingErrorListener();
     CharSequenceReader reader = new CharSequenceReader(code);
     Scanner scanner = new Scanner(_unitSource, reader, errorListener);
+    AnalysisOptions options = _unitElement.context.analysisOptions;
+    scanner.scanGenericMethodComments = options.strongMode;
     Token token = scanner.tokenize();
     _newLineInfo = new LineInfo(scanner.lineStarts);
     _newScanErrors = errorListener.errors;
@@ -870,6 +875,10 @@
     // parse results
     _sourceEntry.setValueIncremental(PARSE_ERRORS, _newParseErrors, true);
     _sourceEntry.setValueIncremental(PARSED_UNIT, _oldUnit, false);
+    // referenced names
+    ReferencedNames referencedNames = new ReferencedNames(_unitSource);
+    new ReferencedNamesBuilder(referencedNames).build(_oldUnit);
+    _sourceEntry.setValueIncremental(REFERENCED_NAMES, referencedNames, false);
   }
 
   /**
@@ -1196,19 +1205,13 @@
     // name offset
     int nameOffset = element.nameOffset;
     if (nameOffset > updateOffset) {
-      // TODO(scheglov) make sure that we don't put local variables
-      // and functions into the cache at all.
-      try {
-        (element as ElementImpl).nameOffset = nameOffset + updateDelta;
-      } on FrozenHashCodeException {
-        cache.remove(element);
-        (element as ElementImpl).nameOffset = nameOffset + updateDelta;
-      }
+      (element as ElementImpl).nameOffset = nameOffset + updateDelta;
       if (element is ConstVariableElement) {
         Expression initializer = element.constantInitializer;
         if (initializer != null) {
           _shiftTokens(initializer.beginToken);
         }
+        _shiftErrors(element.evaluationResult?.errors);
       }
     }
     // code range
@@ -1251,6 +1254,17 @@
     super.visitElement(element);
   }
 
+  void _shiftErrors(List<AnalysisError> errors) {
+    if (errors != null) {
+      for (AnalysisError error in errors) {
+        int errorOffset = error.offset;
+        if (errorOffset > updateOffset) {
+          error.offset += updateDelta;
+        }
+      }
+    }
+  }
+
   void _shiftTokens(Token token) {
     while (token != null) {
       if (token.offset > updateOffset) {
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index ab3b05e..f63bb70 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -4357,25 +4357,12 @@
    * This method assumes that the current token matches `Keyword.ASSERT`.
    *
    *     assertStatement ::=
-   *         'assert' '(' conditionalExpression ')' ';'
+   *         'assert' '(' expression [',' expression] ')' ';'
    */
   AssertStatement _parseAssertStatement() {
     Token keyword = getAndAdvance();
     Token leftParen = _expect(TokenType.OPEN_PAREN);
     Expression expression = parseExpression2();
-    if (expression is AssignmentExpression) {
-      _reportErrorForNode(
-          ParserErrorCode.ASSERT_DOES_NOT_TAKE_ASSIGNMENT, expression);
-    } else if (expression is CascadeExpression) {
-      _reportErrorForNode(
-          ParserErrorCode.ASSERT_DOES_NOT_TAKE_CASCADE, expression);
-    } else if (expression is ThrowExpression) {
-      _reportErrorForNode(
-          ParserErrorCode.ASSERT_DOES_NOT_TAKE_THROW, expression);
-    } else if (expression is RethrowExpression) {
-      _reportErrorForNode(
-          ParserErrorCode.ASSERT_DOES_NOT_TAKE_RETHROW, expression);
-    }
     Token comma;
     Expression message;
     if (_matches(TokenType.COMMA)) {
@@ -5062,16 +5049,52 @@
         newKeyword = firstToken;
         firstToken = firstToken.next;
       }
-      if (_tokenMatchesIdentifier(firstToken)) {
+      if (firstToken.isUserDefinableOperator) {
+        if (firstToken.next.type != TokenType.EOF) {
+          return null;
+        }
+        Identifier identifier = new SimpleIdentifier(firstToken);
+        return new CommentReference(null, identifier);
+      } else if (_tokenMatchesKeyword(firstToken, Keyword.OPERATOR)) {
+        Token secondToken = firstToken.next;
+        if (secondToken.isUserDefinableOperator) {
+          if (secondToken.next.type != TokenType.EOF) {
+            return null;
+          }
+          Identifier identifier = new SimpleIdentifier(secondToken);
+          return new CommentReference(null, identifier);
+        }
+        return null;
+      } else if (_tokenMatchesIdentifier(firstToken)) {
         Token secondToken = firstToken.next;
         Token thirdToken = secondToken.next;
         Token nextToken;
         Identifier identifier;
-        if (_tokenMatches(secondToken, TokenType.PERIOD) &&
-            _tokenMatchesIdentifier(thirdToken)) {
-          identifier = new PrefixedIdentifier(new SimpleIdentifier(firstToken),
-              secondToken, new SimpleIdentifier(thirdToken));
-          nextToken = thirdToken.next;
+        if (_tokenMatches(secondToken, TokenType.PERIOD)) {
+          if (thirdToken.isUserDefinableOperator) {
+            identifier = new PrefixedIdentifier(
+                new SimpleIdentifier(firstToken),
+                secondToken,
+                new SimpleIdentifier(thirdToken));
+            nextToken = thirdToken.next;
+          } else if (_tokenMatchesKeyword(thirdToken, Keyword.OPERATOR)) {
+            Token fourthToken = thirdToken.next;
+            if (fourthToken.isUserDefinableOperator) {
+              identifier = new PrefixedIdentifier(
+                  new SimpleIdentifier(firstToken),
+                  secondToken,
+                  new SimpleIdentifier(fourthToken));
+              nextToken = fourthToken.next;
+            } else {
+              return null;
+            }
+          } else if (_tokenMatchesIdentifier(thirdToken)) {
+            identifier = new PrefixedIdentifier(
+                new SimpleIdentifier(firstToken),
+                secondToken,
+                new SimpleIdentifier(thirdToken));
+            nextToken = thirdToken.next;
+          }
         } else {
           identifier = new SimpleIdentifier(firstToken);
           nextToken = firstToken.next;
@@ -9896,22 +9919,6 @@
       const ParserErrorCode('ANNOTATION_ON_ENUM_CONSTANT',
           "Enum constants cannot have annotations");
 
-  static const ParserErrorCode ASSERT_DOES_NOT_TAKE_ASSIGNMENT =
-      const ParserErrorCode('ASSERT_DOES_NOT_TAKE_ASSIGNMENT',
-          "Assert cannot be called on an assignment");
-
-  static const ParserErrorCode ASSERT_DOES_NOT_TAKE_CASCADE =
-      const ParserErrorCode(
-          'ASSERT_DOES_NOT_TAKE_CASCADE', "Assert cannot be called on cascade");
-
-  static const ParserErrorCode ASSERT_DOES_NOT_TAKE_THROW =
-      const ParserErrorCode(
-          'ASSERT_DOES_NOT_TAKE_THROW', "Assert cannot be called on throws");
-
-  static const ParserErrorCode ASSERT_DOES_NOT_TAKE_RETHROW =
-      const ParserErrorCode('ASSERT_DOES_NOT_TAKE_RETHROW',
-          "Assert cannot be called on rethrows");
-
   /**
    * 16.32 Identifier Reference: It is a compile-time error if any of the
    * identifiers async, await, or yield is used as an identifier in a function
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 15c41d6..b662891 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -4655,7 +4655,9 @@
     for (Combinator combinator in importDirective.combinators) {
       if (combinator is ShowCombinator) {
         for (SimpleIdentifier name in combinator.shownNames) {
-          identifiers.add(name);
+          if (name.staticElement != null) {
+            identifiers.add(name);
+          }
         }
       }
     }
@@ -5141,7 +5143,7 @@
  * Instances of the class `OverrideVerifier` visit all of the declarations in a compilation
  * unit to verify that if they have an override annotation it is being used correctly.
  */
-class OverrideVerifier extends RecursiveAstVisitor<Object> {
+class OverrideVerifier extends RecursiveAstVisitor {
   /**
    * The error reporter used to report errors.
    */
@@ -5161,7 +5163,23 @@
   OverrideVerifier(this._errorReporter, this._manager);
 
   @override
-  Object visitMethodDeclaration(MethodDeclaration node) {
+  visitFieldDeclaration(FieldDeclaration node) {
+    for (VariableDeclaration field in node.fields.variables) {
+      VariableElement fieldElement = field.element;
+      if (fieldElement is FieldElement && _isOverride(fieldElement)) {
+        PropertyAccessorElement getter = fieldElement.getter;
+        PropertyAccessorElement setter = fieldElement.setter;
+        if (!(getter != null && _getOverriddenMember(getter) != null ||
+            setter != null && _getOverriddenMember(setter) != null)) {
+          _errorReporter.reportErrorForNode(
+              HintCode.OVERRIDE_ON_NON_OVERRIDING_FIELD, field.name);
+        }
+      }
+    }
+  }
+
+  @override
+  visitMethodDeclaration(MethodDeclaration node) {
     ExecutableElement element = node.element;
     if (_isOverride(element)) {
       if (_getOverriddenMember(element) == null) {
@@ -5179,7 +5197,6 @@
         }
       }
     }
-    return super.visitMethodDeclaration(node);
   }
 
   /**
@@ -5658,6 +5675,11 @@
   FunctionBody _currentFunctionBody;
 
   /**
+   * Are we running in strong mode or not.
+   */
+  bool strongMode;
+
+  /**
    * Initialize a newly created visitor to resolve the nodes in an AST node.
    *
    * The [definingLibrary] is the element for the library containing the node
@@ -5679,10 +5701,11 @@
       {Scope nameScope})
       : super(definingLibrary, source, typeProvider, errorListener,
             nameScope: nameScope) {
+    AnalysisOptions options = definingLibrary.context.analysisOptions;
+    this.strongMode = options.strongMode;
     this.elementResolver = new ElementResolver(this);
     this.typeSystem = definingLibrary.context.typeSystem;
     bool strongModeHints = false;
-    AnalysisOptions options = definingLibrary.context.analysisOptions;
     if (options is AnalysisOptionsImpl) {
       strongModeHints = options.strongModeHints;
     }
@@ -6621,7 +6644,6 @@
   Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
     node.function?.accept(this);
     node.accept(elementResolver);
-    _inferFunctionExpressionsParametersTypes(node.argumentList);
     _inferArgumentTypesFromContext(node);
     node.argumentList?.accept(this);
     node.accept(typeAnalyzer);
@@ -6723,6 +6745,16 @@
       if (contextType is InterfaceType &&
           contextType.typeArguments != null &&
           contextType.typeArguments.length > 0) {
+        // TODO(jmesserly): for generic methods we use the
+        // StrongTypeSystemImpl.inferGenericFunctionCall, which appears to
+        // be a tad more powerful than matchTypes.
+        //
+        // For example it can infer this case:
+        //
+        //     class E<S, T> extends A<C<S>, T> { ... }
+        //     A<C<int>, String> a0 = /*infer<int, String>*/new E("hello");
+        //
+        // See _inferArgumentTypesFromContext in this file for use of it.
         List<DartType> targs =
             inferenceContext.matchTypes(classTypeName.type, contextType);
         if (targs != null && targs.any((t) => !t.isDynamic)) {
@@ -6838,7 +6870,6 @@
     node.target?.accept(this);
     node.typeArguments?.accept(this);
     node.accept(elementResolver);
-    _inferFunctionExpressionsParametersTypes(node.argumentList);
     _inferArgumentTypesFromContext(node);
     node.argumentList?.accept(this);
     node.accept(typeAnalyzer);
@@ -7201,6 +7232,12 @@
   }
 
   void _inferArgumentTypesFromContext(InvocationExpression node) {
+    if (!strongMode) {
+      // Use propagated type inference for lambdas if not in strong mode.
+      _inferFunctionExpressionsParametersTypes(node.argumentList);
+      return;
+    }
+
     DartType contextType = node.staticInvokeType;
     if (contextType is FunctionType) {
       DartType originalType = node.function.staticType;
@@ -10144,6 +10181,20 @@
   }
 
   @override
+  Object visitFunctionExpression(FunctionExpression node) {
+    // Clear the static element return type of closures.
+    // We need this to restore the state when closure parameter types can
+    // be propagated from invocation parameter types.
+    if (node is! FunctionDeclaration) {
+      ExecutableElement element = node.element;
+      if (element is FunctionElementImpl) {
+        element.returnType = null;
+      }
+    }
+    return super.visitFunctionExpression(node);
+  }
+
+  @override
   Object visitFunctionTypeAlias(FunctionTypeAlias node) {
     FunctionTypeAliasElementImpl element =
         node.element as FunctionTypeAliasElementImpl;
diff --git a/pkg/analyzer/lib/src/generated/sdk_io.dart b/pkg/analyzer/lib/src/generated/sdk_io.dart
index be7c27a..50cb9d0 100644
--- a/pkg/analyzer/lib/src/generated/sdk_io.dart
+++ b/pkg/analyzer/lib/src/generated/sdk_io.dart
@@ -108,6 +108,20 @@
     _useSummary = use;
   }
 
+  /**
+   * Add the extensions from one or more sdk extension files to this sdk. The
+   * [extensions] should be a table mapping the names of extensions to the paths
+   * where those extensions can be found.
+   */
+  void addExtensions(Map<String, String> extensions) {
+    extensions.forEach((String uri, String path) {
+      String shortName = uri.substring(uri.indexOf(':') + 1);
+      SdkLibraryImpl library = new SdkLibraryImpl(shortName);
+      library.path = path;
+      libraryMap.setLibrary(uri, library);
+    });
+  }
+
   @override
   Source fromFileUri(Uri uri) {
     JavaFile file = new JavaFile.fromUri(uri);
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index 6412de3..bdaf9d9 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -265,7 +265,8 @@
    */
   int getOffsetOfLine(int lineNumber) {
     if (lineNumber < 0 || lineNumber >= lineCount) {
-      throw new ArgumentError('Invalid line number: $lineNumber');
+      throw new ArgumentError(
+          'Invalid line number: $lineNumber; must be between 0 and ${lineCount - 1}');
     }
     return _lineStarts[lineNumber];
   }
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 5c57bb8..19019da 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -12,6 +12,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/member.dart' show ConstructorMember;
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -92,7 +93,7 @@
     _dynamicType = _typeProvider.dynamicType;
     _overrideManager = _resolver.overrideManager;
     _promoteManager = _resolver.promoteManager;
-    _strongMode = _resolver.definingLibrary.context.analysisOptions.strongMode;
+    _strongMode = _resolver.strongMode;
   }
 
   /**
@@ -257,13 +258,23 @@
     } else {
       ExecutableElement staticMethodElement = node.staticElement;
       DartType staticType = _computeStaticReturnType(staticMethodElement);
-      staticType =
-          _refineAssignmentExpressionType(node, staticType, _getStaticType);
+      staticType = _typeSystem.refineBinaryExpressionType(
+          _typeProvider,
+          node.leftHandSide.staticType,
+          operator,
+          node.rightHandSide.staticType,
+          staticType);
       _recordStaticType(node, staticType);
       MethodElement propagatedMethodElement = node.propagatedElement;
       if (!identical(propagatedMethodElement, staticMethodElement)) {
         DartType propagatedType =
             _computeStaticReturnType(propagatedMethodElement);
+        propagatedType = _typeSystem.refineBinaryExpressionType(
+            _typeProvider,
+            node.leftHandSide.propagatedType,
+            operator,
+            node.rightHandSide.propagatedType,
+            propagatedType);
         _resolver.recordPropagatedTypeIfBetter(node, propagatedType);
       }
     }
@@ -521,7 +532,7 @@
   @override
   Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
     if (_strongMode) {
-      _inferGenericInvoke(node);
+      _inferGenericInvocationExpression(node);
     }
     DartType staticType = _computeInvokeReturnType(node.staticInvokeType);
     _recordStaticType(node, staticType);
@@ -574,6 +585,10 @@
    */
   @override
   Object visitInstanceCreationExpression(InstanceCreationExpression node) {
+    if (_strongMode) {
+      _inferInstanceCreationExpression(node);
+    }
+
     _recordStaticType(node, node.constructorName.type.type);
     ConstructorElement element = node.staticElement;
     if (element != null && "Element" == element.enclosingElement.name) {
@@ -812,7 +827,7 @@
     SimpleIdentifier methodNameNode = node.methodName;
     Element staticMethodElement = methodNameNode.staticElement;
     if (_strongMode) {
-      _inferGenericInvoke(node);
+      _inferGenericInvocationExpression(node);
     }
     // Record types of the variable invoked as a function.
     if (staticMethodElement is VariableElement) {
@@ -1605,6 +1620,33 @@
     return returnType.type;
   }
 
+  /**
+   * Given a constructor for a generic type, returns the equivalent generic
+   * function type that we could use to forward to the constructor, or for a
+   * non-generic type simply returns the constructor type.
+   *
+   * For example given the type `class C<T> { C(T arg); }`, the generic function
+   * type is `<T>(T) -> C<T>`.
+   */
+  FunctionType _constructorToGenericFunctionType(
+      ConstructorElement constructor) {
+    // TODO(jmesserly): it may be worth making this available from the
+    // constructor. It's nice if our inference code can operate uniformly on
+    // function types.
+    ClassElement cls = constructor.enclosingElement;
+    FunctionType type = constructor.type;
+    if (cls.typeParameters.isEmpty) {
+      return type;
+    }
+
+    FunctionElementImpl function = new FunctionElementImpl("", -1);
+    function.synthetic = true;
+    function.returnType = type.returnType;
+    function.shareTypeParameters(cls.typeParameters);
+    function.shareParameters(type.parameters);
+    return function.type = new FunctionTypeImpl(function);
+  }
+
   DartType _findIteratedType(DartType type, DartType targetType) {
     // TODO(vsm): Use leafp's matchType here?
     // Set by _find if match is found
@@ -1864,8 +1906,8 @@
   }
 
   /**
-   * Given an uninstantiated generic type, try to infer the instantiated generic
-   * type from the surrounding context.
+   * Given an uninstantiated generic function type, try to infer the
+   * instantiated generic function type from the surrounding context.
    */
   DartType _inferGenericInstantiationFromContext(
       DartType context, DartType type) {
@@ -1878,14 +1920,40 @@
     return type;
   }
 
-  bool _inferGenericInvoke(InvocationExpression node) {
+  /**
+   * Given a possibly generic invocation like `o.m(args)` or `(f)(args)` try to
+   * infer the instantiated generic function type.
+   *
+   * This takes into account both the context type, as well as information from
+   * the argument types.
+   */
+  void _inferGenericInvocationExpression(InvocationExpression node) {
+    ArgumentList arguments = node.argumentList;
+    FunctionType inferred = _inferGenericInvoke(
+        node, node.function.staticType, node.typeArguments, arguments);
+    if (inferred != null && inferred != node.staticInvokeType) {
+      // Fix up the parameter elements based on inferred method.
+      arguments.correspondingStaticParameters = ResolverVisitor
+          .resolveArgumentsToParameters(arguments, inferred.parameters, null);
+      node.staticInvokeType = inferred;
+    }
+  }
+
+  /**
+   * Given a possibly generic invocation or instance creation, such as
+   * `o.m(args)` or `(f)(args)` or `new T(args)` try to infer the instantiated
+   * generic function type.
+   *
+   * This takes into account both the context type, as well as information from
+   * the argument types.
+   */
+  FunctionType _inferGenericInvoke(Expression node, DartType fnType,
+      TypeArgumentList typeArguments, ArgumentList argumentList) {
     TypeSystem ts = _typeSystem;
-    DartType fnType = node.function.staticType;
-    if (node.typeArguments == null &&
+    if (typeArguments == null &&
         fnType is FunctionType &&
         fnType.typeFormals.isNotEmpty &&
         ts is StrongTypeSystemImpl) {
-      ArgumentList argumentList = node.argumentList;
       // Get the parameters that correspond to the uninstantiated generic.
       List<ParameterElement> rawParameters = ResolverVisitor
           .resolveArgumentsToParameters(argumentList, fnType.parameters, null);
@@ -1900,20 +1968,48 @@
         }
       }
 
-      FunctionType inferred = ts.inferGenericFunctionCall(_typeProvider, fnType,
-          paramTypes, argTypes, InferenceContext.getType(node));
-
-      if (inferred != node.staticInvokeType) {
-        // Fix up the parameter elements based on inferred method.
-        List<ParameterElement> inferredParameters =
-            ResolverVisitor.resolveArgumentsToParameters(
-                argumentList, inferred.parameters, null);
-        argumentList.correspondingStaticParameters = inferredParameters;
-        node.staticInvokeType = inferred;
-        return true;
-      }
+      return ts.inferGenericFunctionCall(_typeProvider, fnType, paramTypes,
+          argTypes, InferenceContext.getType(node));
     }
-    return false;
+    return null;
+  }
+
+  /**
+   * Given an instance creation of a possibly generic type, infer the type
+   * arguments using the current context type as well as the argument types.
+   */
+  void _inferInstanceCreationExpression(InstanceCreationExpression node) {
+    ConstructorName constructor = node.constructorName;
+    ConstructorElement originalElement = constructor.staticElement;
+    // If the constructor is generic, we'll have a ConstructorMember that
+    // substitutes in type arguments (possibly `dynamic`) from earlier in
+    // resolution.
+    //
+    // Otherwise we'll have a ConstructorElement, and we can skip inference
+    // because there's nothing to infer in a non-generic type.
+    if (originalElement is! ConstructorMember) {
+      return;
+    }
+
+    // Get back to the uninstantiated generic constructor.
+    // TODO(jmesserly): should we store this earlier in resolution?
+    // Or look it up, instead of jumping backwards through the Member?
+    var rawElement = (originalElement as ConstructorMember).baseElement;
+
+    FunctionType constructorType =
+        _constructorToGenericFunctionType(rawElement);
+
+    ArgumentList arguments = node.argumentList;
+    FunctionType inferred = _inferGenericInvoke(
+        node, constructorType, constructor.type.typeArguments, arguments);
+
+    if (inferred != null && inferred != originalElement.type) {
+      // Fix up the parameter elements based on inferred method.
+      arguments.correspondingStaticParameters = ResolverVisitor
+          .resolveArgumentsToParameters(arguments, inferred.parameters, null);
+      inferConstructorName(constructor, inferred.returnType);
+      // TODO(jmesserly): should we fix up the staticElement as well?
+    }
   }
 
   /**
@@ -2146,44 +2242,6 @@
   }
 
   /**
-   * Attempts to make a better guess for the type of the given assignment
-   * [expression], given that resolution has so far produced the [currentType].
-   * The [typeAccessor] is used to access the corresponding type of the left
-   * and right operands.
-   */
-  DartType _refineAssignmentExpressionType(AssignmentExpression expression,
-      DartType currentType, DartType typeAccessor(Expression node)) {
-    Expression leftHandSize = expression.leftHandSide;
-    Expression rightHandSide = expression.rightHandSide;
-    TokenType operator = expression.operator.type;
-    DartType intType = _typeProvider.intType;
-    if (typeAccessor(leftHandSize) == intType) {
-      // int op= double
-      if (operator == TokenType.MINUS_EQ ||
-          operator == TokenType.PERCENT_EQ ||
-          operator == TokenType.PLUS_EQ ||
-          operator == TokenType.STAR_EQ) {
-        DartType doubleType = _typeProvider.doubleType;
-        if (typeAccessor(rightHandSide) == doubleType) {
-          return doubleType;
-        }
-      }
-      // int op= int
-      if (operator == TokenType.MINUS_EQ ||
-          operator == TokenType.PERCENT_EQ ||
-          operator == TokenType.PLUS_EQ ||
-          operator == TokenType.STAR_EQ ||
-          operator == TokenType.TILDE_SLASH_EQ) {
-        if (typeAccessor(rightHandSide) == intType) {
-          return intType;
-        }
-      }
-    }
-    // default
-    return currentType;
-  }
-
-  /**
    * Create a table mapping HTML tag names to the names of the classes (in 'dart:html') that
    * implement those tags.
    *
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 74e3fd2..f7efd79 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -167,8 +167,7 @@
     }
 
     // Try to infer and instantiate the resulting type.
-    var resultType =
-        inferringTypeSystem._infer(fnType, allowPartialSolution: false);
+    var resultType = inferringTypeSystem._infer(fnType);
 
     // If the instantiation failed (because some type variable constraints
     // could not be solved, in other words, we could not find a valid subtype),
@@ -240,14 +239,7 @@
           argumentTypes[i], correspondingParameterTypes[i]);
     }
 
-    // We are okay inferring some type variables and not others.
-    //
-    // This lets our return type be as precise as possible, which will help
-    // make any type information resulting from it more precise.
-    //
-    // This is simply a heuristic: the code is incorrect, and we'll issue an
-    // error on this call, to indicate that types don't match.
-    return inferringTypeSystem._infer(fnType, allowPartialSolution: true);
+    return inferringTypeSystem._infer(fnType);
   }
 
   /**
@@ -1282,7 +1274,7 @@
 
   /// Given the constraints that were given by calling [isSubtypeOf], find the
   /// instantiation of the generic function that satisfies these constraints.
-  FunctionType _infer(FunctionType fnType, {bool allowPartialSolution: false}) {
+  FunctionType _infer(FunctionType fnType) {
     List<TypeParameterType> fnTypeParams =
         TypeParameterTypeImpl.getTypes(fnType.typeFormals);
 
@@ -1335,16 +1327,8 @@
               bound.upper.substitute2(inferredTypes, fnTypeParams)) ||
           !isSubtypeOf(bound.lower.substitute2(inferredTypes, fnTypeParams),
               inferredTypes[i])) {
-        // Unless a partial solution was requested, bail.
-        if (!allowPartialSolution) {
-          return null;
-        }
-
-        inferredTypes[i] = DynamicTypeImpl.instance;
-        if (typeParam.element.bound != null) {
-          inferredTypes[i] =
-              typeParam.element.bound.substitute2(inferredTypes, fnTypeParams);
-        }
+        // Inference failed. Bail.
+        return null;
       }
     }
 
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index 57dccf1..08cbde1 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -593,6 +593,9 @@
   }
 
   @override
+  int get version => 0;
+
+  @override
   DartType buildType(
       DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) {
     int numTypeParameters = _unlinkedClass.typeParameters.length;
diff --git a/pkg/analyzer/lib/src/summary/summary_sdk.dart b/pkg/analyzer/lib/src/summary/summary_sdk.dart
index 987a187..1ac305e 100644
--- a/pkg/analyzer/lib/src/summary/summary_sdk.dart
+++ b/pkg/analyzer/lib/src/summary/summary_sdk.dart
@@ -20,6 +20,7 @@
 import 'package:analyzer/src/summary/resynthesize.dart';
 import 'package:analyzer/src/task/dart.dart';
 import 'package:analyzer/task/model.dart' show ResultDescriptor, TargetedResult;
+import 'package:analyzer/file_system/file_system.dart' show ResourceProvider;
 
 class SdkSummaryResultProvider extends ResynthesizerResultProvider {
   final SummaryTypeProvider typeProvider = new SummaryTypeProvider();
@@ -106,6 +107,7 @@
   SummaryDataStore _dataStore;
   InSummaryPackageUriResolver _uriResolver;
   PackageBundle _bundle;
+  ResourceProvider resourceProvider;
 
   /**
    * The [AnalysisContext] which is used for all of the sources in this sdk.
@@ -118,6 +120,14 @@
     _bundle = _dataStore.bundles.single;
   }
 
+  SummaryBasedDartSdk.fromBundle(
+      this.strongMode, PackageBundle bundle, this.resourceProvider) {
+    _dataStore = new SummaryDataStore([]);
+    _dataStore.addBundle('dart_sdk.sum', bundle);
+    _uriResolver = new InSummaryPackageUriResolver(_dataStore);
+    _bundle = bundle;
+  }
+
   /**
    * Return the [PackageBundle] for this SDK, not `null`.
    */
@@ -129,7 +139,8 @@
       AnalysisOptionsImpl analysisOptions = new AnalysisOptionsImpl()
         ..strongMode = strongMode;
       _analysisContext = new SdkAnalysisContext(analysisOptions);
-      SourceFactory factory = new SourceFactory([new DartUriResolver(this)]);
+      SourceFactory factory = new SourceFactory(
+          [new DartUriResolver(this)], null, resourceProvider);
       _analysisContext.sourceFactory = factory;
       _analysisContext.resultProvider =
           new SdkSummaryResultProvider(_analysisContext, _bundle, strongMode);
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index 25e74ec..6860903 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -327,6 +327,33 @@
     new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT9', false);
 
 /**
+ * All [AnalysisError]s results for [Source]s.
+ */
+final List<ListResultDescriptor<AnalysisError>> ERROR_SOURCE_RESULTS =
+    <ListResultDescriptor<AnalysisError>>[
+  BUILD_DIRECTIVES_ERRORS,
+  BUILD_LIBRARY_ERRORS,
+  PARSE_ERRORS,
+  SCAN_ERRORS,
+];
+
+/**
+ * All [AnalysisError]s results in for [LibrarySpecificUnit]s.
+ */
+final List<ListResultDescriptor<AnalysisError>> ERROR_UNIT_RESULTS =
+    <ListResultDescriptor<AnalysisError>>[
+  HINTS,
+  LIBRARY_UNIT_ERRORS,
+  LINTS,
+  RESOLVE_TYPE_BOUNDS_ERRORS,
+  RESOLVE_TYPE_NAMES_ERRORS,
+  RESOLVE_UNIT_ERRORS,
+  STRONG_MODE_ERRORS,
+  VARIABLE_REFERENCE_ERRORS,
+  VERIFY_ERRORS
+];
+
+/**
  * The sources representing the export closure of a library.
  * The [Source]s include only library sources, not their units.
  *
@@ -1075,12 +1102,10 @@
     //
     // Prepare constants.
     //
-    ConstantFinder constantFinder =
-        new ConstantFinder(context, source, librarySpecificUnit.library);
+    ConstantFinder constantFinder = new ConstantFinder();
     unit.accept(constantFinder);
     List<ConstantEvaluationTarget> constants =
-        new List<ConstantEvaluationTarget>.from(
-            constantFinder.constantsToCompute);
+        constantFinder.constantsToCompute.toList();
     //
     // Record outputs.
     //
@@ -1450,8 +1475,7 @@
       'BuildLibraryElementTask', createTask, buildInputs, <ResultDescriptor>[
     BUILD_LIBRARY_ERRORS,
     LIBRARY_ELEMENT1,
-    IS_LAUNCHABLE,
-    REFERENCED_NAMES
+    IS_LAUNCHABLE
   ]);
 
   /**
@@ -1623,19 +1647,12 @@
       Directive directive = directivesToResolve[i];
       directive.element = libraryElement;
     }
-    // Compute referenced names.
-    ReferencedNames referencedNames = new ReferencedNames(librarySource);
-    new ReferencedNamesBuilder(referencedNames).build(definingCompilationUnit);
-    for (CompilationUnit partUnit in partUnits) {
-      new ReferencedNamesBuilder(referencedNames).build(partUnit);
-    }
     //
     // Record outputs.
     //
     outputs[BUILD_LIBRARY_ERRORS] = errors;
     outputs[LIBRARY_ELEMENT1] = libraryElement;
     outputs[IS_LAUNCHABLE] = entryPoint != null;
-    outputs[REFERENCED_NAMES] = referencedNames;
   }
 
   /**
@@ -2484,8 +2501,6 @@
  * The description for a change in a Dart source.
  */
 class DartDelta extends Delta {
-  bool hasDirectiveChange = false;
-
   final Set<String> changedNames = new Set<String>();
   final Map<Source, Set<String>> changedPrivateNames = <Source, Set<String>>{};
 
@@ -2495,23 +2510,36 @@
   /**
    * The cache of libraries in which all results are invalid.
    */
-  final Set<Source> librariesWithInvalidResults = new Set<Source>();
+  final Set<Source> librariesWithAllInvalidResults = new Set<Source>();
 
   /**
    * The cache of libraries in which all results are valid.
    */
-  final Set<Source> librariesWithValidResults = new Set<Source>();
+  final Set<Source> librariesWithAllValidResults = new Set<Source>();
+
+  /**
+   * The cache of libraries with all, but [HINTS] and [VERIFY_ERRORS] results
+   * are valid.
+   */
+  final Set<Source> libraryWithInvalidErrors = new Set<Source>();
+
+  /**
+   * This set is cleared in every [gatherEnd], and [gatherChanges] uses it
+   * to find changes in every source only once per visit process.
+   */
+  final Set<Source> currentVisitUnits = new Set<Source>();
 
   DartDelta(Source source) : super(source);
 
   /**
    * Add names that are changed in the given [references].
+   * Return `true` if any change was added.
    */
-  void addChangedElements(ReferencedNames references) {
-    Source refLibrary = references.librarySource;
-    bool hasProgress = true;
-    while (hasProgress) {
-      hasProgress = false;
+  bool addChangedElements(ReferencedNames references, Source refLibrary) {
+    int numberOfChanges = 0;
+    int lastNumberOfChange = -1;
+    while (numberOfChanges != lastNumberOfChange) {
+      lastNumberOfChange = numberOfChanges;
       // Classes that extend changed classes are also changed.
       // If there is a delta for a superclass, use it for the subclass.
       // Otherwise mark the subclass as "general name change".
@@ -2524,13 +2552,13 @@
             _log(() => '$subName in $refLibrary has delta because of its '
                 'superclass $superName has delta');
             if (subDelta.superDeltas.add(superDelta)) {
-              hasProgress = true;
+              numberOfChanges++;
             }
           } else if (isChanged(refLibrary, superName)) {
             if (nameChanged(refLibrary, subName)) {
               _log(() => '$subName in $refLibrary is changed because its '
                   'superclass $superName is changed');
-              hasProgress = true;
+              numberOfChanges++;
             }
           }
         }
@@ -2545,12 +2573,13 @@
             if (nameChanged(refLibrary, user)) {
               _log(() => '$user in $refLibrary is changed because '
                   'of $dependency in $dependencies');
-              hasProgress = true;
+              numberOfChanges++;
             }
           }
         }
       });
     }
+    return numberOfChanges != 0;
   }
 
   void classChanged(ClassElementDelta classDelta) {
@@ -2562,23 +2591,52 @@
     nameChanged(librarySource, element.name);
   }
 
-  bool hasAffectedReferences(ReferencedNames references) {
-    Source refLibrary = references.librarySource;
-    // Verify errors must be recomputed when a superclass changes.
+  @override
+  bool gatherChanges(InternalAnalysisContext context, AnalysisTarget target,
+      ResultDescriptor descriptor, Object value) {
+    // Prepare target source.
+    Source targetUnit = target.source;
+    Source targetLibrary = target.librarySource;
+    if (target is Source) {
+      if (context.getKindOf(target) == SourceKind.LIBRARY) {
+        targetLibrary = target;
+      }
+    }
+    // We don't know what to do with the given target.
+    if (targetUnit == null || targetUnit != targetLibrary) {
+      return false;
+    }
+    // Attempt to find new changed names for the unit only once.
+    if (!currentVisitUnits.add(targetUnit)) {
+      return false;
+    }
+    // Add changes.
+    ReferencedNames referencedNames =
+        context.getResult(targetUnit, REFERENCED_NAMES);
+    if (referencedNames == null) {
+      return false;
+    }
+    return addChangedElements(referencedNames, targetLibrary);
+  }
+
+  @override
+  void gatherEnd() {
+    currentVisitUnits.clear();
+  }
+
+  bool hasAffectedHintsVerifyErrors(
+      ReferencedNames references, Source refLibrary) {
     for (String superName in references.superToSubs.keys) {
       if (isChangedOrClass(refLibrary, superName)) {
-        _log(() => '$refLibrary is affected because '
+        _log(() => '$refLibrary hints/verify errors are affected because '
             '${references.superToSubs[superName]} subclasses $superName');
         return true;
       }
     }
-    // Verify errors must be recomputed when an instantiated class changes.
-    for (String name in references.instantiatedNames) {
-      if (isChangedOrClass(refLibrary, name)) {
-        _log(() => '$refLibrary is affected because $name is instantiated');
-        return true;
-      }
-    }
+    return false;
+  }
+
+  bool hasAffectedReferences(ReferencedNames references, Source refLibrary) {
     // Resolution must be performed when a referenced element changes.
     for (String name in references.names) {
       if (isChangedOrClassMember(refLibrary, name)) {
@@ -2586,6 +2644,18 @@
         return true;
       }
     }
+    // Resolution must be performed when the unnamed constructor of
+    // an instantiated class is added/changed/removed.
+    // TODO(scheglov) Use only instantiations with default constructor.
+    for (String name in references.instantiatedNames) {
+      for (ClassElementDelta classDelta in changedClasses.values) {
+        if (classDelta.name == name && classDelta.hasUnnamedConstructorChange) {
+          _log(() =>
+              '$refLibrary is affected by the default constructor of $name');
+          return true;
+        }
+      }
+    }
     return false;
   }
 
@@ -2647,23 +2717,23 @@
   @override
   DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target,
       ResultDescriptor descriptor, Object value) {
-    if (hasDirectiveChange) {
-      return DeltaResult.INVALIDATE;
-    }
     // Prepare target source.
-    Source targetSource = target.source;
-    Source librarySource = target.librarySource;
+    Source targetUnit = target.source;
+    Source targetLibrary = target.librarySource;
     if (target is Source) {
       if (context.getKindOf(target) == SourceKind.LIBRARY) {
-        librarySource = target;
+        targetLibrary = target;
       }
     }
     // We don't know what to do with the given target, invalidate it.
-    if (targetSource == null) {
+    if (targetUnit == null || targetUnit != targetLibrary) {
       return DeltaResult.INVALIDATE;
     }
     // Keep results that don't change: any library.
-    if (_isTaskResult(BuildLibraryElementTask.DESCRIPTOR, descriptor) ||
+    if (_isTaskResult(ScanDartTask.DESCRIPTOR, descriptor) ||
+        _isTaskResult(ParseDartTask.DESCRIPTOR, descriptor) ||
+        _isTaskResult(BuildCompilationUnitElementTask.DESCRIPTOR, descriptor) ||
+        _isTaskResult(BuildLibraryElementTask.DESCRIPTOR, descriptor) ||
         _isTaskResult(BuildDirectiveElementsTask.DESCRIPTOR, descriptor) ||
         _isTaskResult(ResolveDirectiveElementsTask.DESCRIPTOR, descriptor) ||
         _isTaskResult(BuildEnumMemberElementsTask.DESCRIPTOR, descriptor) ||
@@ -2673,43 +2743,47 @@
       return DeltaResult.KEEP_CONTINUE;
     }
     // Keep results that don't change: changed library.
-    if (targetSource == source) {
-      if (_isTaskResult(ScanDartTask.DESCRIPTOR, descriptor) ||
-          _isTaskResult(ParseDartTask.DESCRIPTOR, descriptor) ||
-          _isTaskResult(
-              BuildCompilationUnitElementTask.DESCRIPTOR, descriptor) ||
-          _isTaskResult(BuildLibraryElementTask.DESCRIPTOR, descriptor)) {
-        return DeltaResult.KEEP_CONTINUE;
-      }
+    if (targetUnit == source) {
       return DeltaResult.INVALIDATE;
     }
     // Keep results that don't change: dependent library.
-    if (targetSource != source) {
+    if (targetUnit != source) {
       if (_isTaskResult(BuildPublicNamespaceTask.DESCRIPTOR, descriptor)) {
         return DeltaResult.KEEP_CONTINUE;
       }
     }
     // Handle in-library results only for now.
-    if (librarySource != null) {
+    if (targetLibrary != null) {
       // Use cached library results.
-      if (librariesWithInvalidResults.contains(librarySource)) {
+      if (librariesWithAllInvalidResults.contains(targetLibrary)) {
         return DeltaResult.INVALIDATE;
       }
-      if (librariesWithValidResults.contains(librarySource)) {
+      if (librariesWithAllValidResults.contains(targetLibrary)) {
         return DeltaResult.STOP;
       }
+      // The library is almost, but not completely valid.
+      // Some error results are invalid.
+      if (libraryWithInvalidErrors.contains(targetLibrary)) {
+        if (descriptor == HINTS || descriptor == VERIFY_ERRORS) {
+          return DeltaResult.INVALIDATE_NO_DELTA;
+        }
+        return DeltaResult.KEEP_CONTINUE;
+      }
       // Compute the library result.
       ReferencedNames referencedNames =
-          context.getResult(librarySource, REFERENCED_NAMES);
+          context.getResult(targetUnit, REFERENCED_NAMES);
       if (referencedNames == null) {
         return DeltaResult.INVALIDATE_NO_DELTA;
       }
-      addChangedElements(referencedNames);
-      if (hasAffectedReferences(referencedNames)) {
-        librariesWithInvalidResults.add(librarySource);
+      if (hasAffectedReferences(referencedNames, targetLibrary)) {
+        librariesWithAllInvalidResults.add(targetLibrary);
         return DeltaResult.INVALIDATE;
       }
-      librariesWithValidResults.add(librarySource);
+      if (hasAffectedHintsVerifyErrors(referencedNames, targetLibrary)) {
+        libraryWithInvalidErrors.add(targetLibrary);
+        return DeltaResult.KEEP_CONTINUE;
+      }
+      librariesWithAllValidResults.add(targetLibrary);
       return DeltaResult.STOP;
     }
     // We don't know what to do with the given target, invalidate it.
@@ -3943,9 +4017,10 @@
     LIBRARY_SPECIFIC_UNITS,
     PARSE_ERRORS,
     PARSED_UNIT,
+    REFERENCED_NAMES,
+    REFERENCED_SOURCES,
     SOURCE_KIND,
     UNITS,
-    REFERENCED_SOURCES
   ]);
 
   /**
@@ -4034,6 +4109,11 @@
       sourceKind = SourceKind.PART;
     }
     //
+    // Compute referenced names.
+    //
+    ReferencedNames referencedNames = new ReferencedNames(source);
+    new ReferencedNamesBuilder(referencedNames).build(unit);
+    //
     // Record outputs.
     //
     List<Source> explicitlyImportedSources =
@@ -4057,9 +4137,10 @@
     outputs[LIBRARY_SPECIFIC_UNITS] = librarySpecificUnits;
     outputs[PARSE_ERRORS] = parseErrors;
     outputs[PARSED_UNIT] = unit;
+    outputs[REFERENCED_NAMES] = referencedNames;
+    outputs[REFERENCED_SOURCES] = referencedSources;
     outputs[SOURCE_KIND] = sourceKind;
     outputs[UNITS] = unitSources;
-    outputs[REFERENCED_SOURCES] = referencedSources;
   }
 
   /**
@@ -4684,11 +4765,11 @@
 }
 
 /**
- * Information about a library - which names it uses, which names it defines
- * with their externally visible dependencies.
+ * Information about a Dart [source] - which names it uses, which names it
+ * defines with their externally visible dependencies.
  */
 class ReferencedNames {
-  final Source librarySource;
+  final Source source;
 
   /**
    * The mapping from the name of a class to the set of names of other classes
@@ -4723,7 +4804,7 @@
    */
   final Map<String, Set<String>> userToDependsOn = <String, Set<String>>{};
 
-  ReferencedNames(this.librarySource);
+  ReferencedNames(this.source);
 
   void addSubclass(String subName, String superName) {
     superToSubs.putIfAbsent(superName, () => new Set<String>()).add(subName);
@@ -5632,6 +5713,8 @@
     return <String, TaskInput>{
       'importsExportNamespace':
           IMPORTED_LIBRARIES.of(unit.library).toMapOf(LIBRARY_ELEMENT4),
+      'dependOnAllExportedSources':
+          IMPORTED_LIBRARIES.of(unit.library).toMapOf(EXPORT_SOURCE_CLOSURE),
       LIBRARY_INPUT: LIBRARY_ELEMENT4.of(unit.library),
       UNIT_INPUT: RESOLVED_UNIT3.of(unit),
       TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
diff --git a/pkg/analyzer/lib/src/task/dart_work_manager.dart b/pkg/analyzer/lib/src/task/dart_work_manager.dart
index 3d6dc33..6b2a96e 100644
--- a/pkg/analyzer/lib/src/task/dart_work_manager.dart
+++ b/pkg/analyzer/lib/src/task/dart_work_manager.dart
@@ -117,7 +117,10 @@
   void applyChange(List<Source> addedSources, List<Source> changedSources,
       List<Source> removedSources) {
     addedSources = addedSources.where(_isDartSource).toList();
-    changedSources = changedSources.where(_isDartSource).toList();
+    changedSources = changedSources
+        .where(_isDartSource)
+        .where((source) => _needsComputing(source, SOURCE_KIND))
+        .toList();
     removedSources = removedSources.where(_isDartSource).toList();
     // unknown queue
     unknownSourceQueue.addAll(addedSources);
diff --git a/pkg/analyzer/lib/src/task/incremental_element_builder.dart b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
index 9bc30f8..7e5444d 100644
--- a/pkg/analyzer/lib/src/task/incremental_element_builder.dart
+++ b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
@@ -12,10 +12,12 @@
 import 'package:analyzer/dart/element/visitor.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/constant/utilities.dart';
 import 'package:analyzer/src/dart/element/builder.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/task/dart.dart';
 
 /**
  * The change of a single [ClassElement].
@@ -34,6 +36,7 @@
 
   final List<ConstructorElement> addedConstructors = <ConstructorElement>[];
   final List<ConstructorElement> removedConstructors = <ConstructorElement>[];
+  bool hasUnnamedConstructorChange = false;
 
   final List<MethodElement> addedMethods = <MethodElement>[];
   final List<MethodElement> removedMethods = <MethodElement>[];
@@ -99,6 +102,9 @@
   final CompilationUnit newUnit;
   final ElementHolder unitElementHolder = new ElementHolder();
 
+  final List<ConstantEvaluationTarget> unitConstants =
+      <ConstantEvaluationTarget>[];
+
   /**
    * The change between element models of [oldUnit] and [newUnit].
    */
@@ -124,11 +130,14 @@
    * Fills [unitDelta] with added/remove elements.
    */
   void build() {
+    _materializeLazyElements();
     new CompilationUnitBuilder()
         .buildCompilationUnit(unitSource, newUnit, librarySource);
+    newUnit.accept(new EnumMemberBuilder(unitElement.context.typeProvider));
     _processDirectives();
     _processUnitMembers();
     _replaceUnitContents(oldUnit, newUnit);
+    _findConstants();
     newUnit.element = unitElement;
     unitElement.setCodeRange(0, newUnit.endToken.end);
   }
@@ -151,11 +160,29 @@
     }
   }
 
+  void _findConstants() {
+    ConstantFinder finder = new ConstantFinder();
+    oldUnit.accept(finder);
+    unitConstants.addAll(finder.constantsToCompute);
+    // Update annotation constants to using the old unit element.
+    for (ConstantEvaluationTarget constant in unitConstants) {
+      if (constant is ElementAnnotationImpl) {
+        constant.compilationUnit = unitElement;
+      }
+    }
+  }
+
+  void _materializeLazyElements() {
+    unitElement.accept(new RecursiveElementVisitor());
+  }
+
   ClassElementDelta _processClassMembers(
       ClassDeclaration oldClass, ClassDeclaration newClass) {
     // If the class hierarchy or type parameters are changed,
     // then the class changed too much - don't compute the delta.
-    if (TokenUtils.getFullCode(newClass.typeParameters) !=
+    if (newClass.abstractKeyword != null && oldClass.abstractKeyword == null ||
+        newClass.abstractKeyword == null && oldClass.abstractKeyword != null ||
+        TokenUtils.getFullCode(newClass.typeParameters) !=
             TokenUtils.getFullCode(oldClass.typeParameters) ||
         TokenUtils.getFullCode(newClass.extendsClause) !=
             TokenUtils.getFullCode(oldClass.extendsClause) ||
@@ -334,6 +361,7 @@
     classElement.constructors = classElementHolder.constructors;
     classElement.fields = newFields.values.toList();
     classElement.methods = classElementHolder.methods;
+    classElement.version++;
     classElementHolder.validate();
     // Ensure at least a default synthetic constructor.
     if (classElement.constructors.isEmpty) {
@@ -341,7 +369,11 @@
           new ConstructorElementImpl.forNode(null);
       constructor.synthetic = true;
       classElement.constructors = <ConstructorElement>[constructor];
+      classDelta.addedConstructors.add(constructor);
     }
+    classDelta.hasUnnamedConstructorChange =
+        classDelta.addedConstructors.any((c) => c.name == '') ||
+            classDelta.removedConstructors.any((c) => c.name == '');
     // OK
     return classDelta;
   }
@@ -538,22 +570,35 @@
   static void copyTokenOffsets(Map<int, int> offsetMap, Token oldToken,
       Token newToken, Token oldEndToken, Token newEndToken) {
     if (oldToken is CommentToken && newToken is CommentToken) {
-      // 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;
+        // 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++) {
+            Token oldToken = oldReferences[i];
+            Token newToken = newReferences[i];
+            // For [new Name] the 'Name' token is the reference.
+            // But we need to process all tokens, including 'new'.
+            while (oldToken.previous != null &&
+                oldToken.previous.type != TokenType.EOF) {
+              oldToken = oldToken.previous;
+            }
+            while (newToken.previous != null &&
+                newToken.previous.type != TokenType.EOF) {
+              newToken = newToken.previous;
+            }
+            copyTokenOffsets(
+                offsetMap, oldToken, newToken, oldEndToken, newEndToken);
+          }
+        }
+        // Next tokens.
         oldToken = oldToken.next;
         newToken = newToken.next;
       }
@@ -644,15 +689,18 @@
     if (element is LibraryElement) {
       return;
     }
-    if (element.isSynthetic && !_isVariableInitializer(element)) {
-      return;
-    }
     if (element is ElementImpl) {
       // name offset
       {
         int oldOffset = element.nameOffset;
         int newOffset = map[oldOffset];
-        assert(newOffset != null);
+        // Some synthetic elements have new offsets, e.g. synthetic accessors
+        // of property inducing elements.  But some are purely synthetic, e.g.
+        // synthetic enum fields and their accessors.
+        if (newOffset == null) {
+          assert(element.isSynthetic);
+          return;
+        }
         element.nameOffset = newOffset;
       }
       // code range
@@ -694,9 +742,4 @@
     }
     super.visitElement(element);
   }
-
-  static bool _isVariableInitializer(Element element) {
-    return element is FunctionElement &&
-        element.enclosingElement is VariableElement;
-  }
 }
diff --git a/pkg/analyzer/lib/src/task/options.dart b/pkg/analyzer/lib/src/task/options.dart
index a25d146..a101147 100644
--- a/pkg/analyzer/lib/src/task/options.dart
+++ b/pkg/analyzer/lib/src/task/options.dart
@@ -10,11 +10,13 @@
 import 'package:analyzer/plugin/options.dart';
 import 'package:analyzer/source/analysis_options_provider.dart';
 import 'package:analyzer/source/error_processor.dart';
+import 'package:analyzer/src/context/context.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
 import 'package:analyzer/src/task/general.dart';
+import 'package:analyzer/src/util/yaml.dart';
 import 'package:analyzer/task/general.dart';
 import 'package:analyzer/task/model.dart';
 import 'package:source_span/source_span.dart';
@@ -49,15 +51,16 @@
   static const String enableSuperMixins = 'enableSuperMixins';
   static const String enableTrailingCommas = 'enableTrailingCommas';
 
-  /// This option is deprecated.
-  static const String enableConditionalDirectives =
-      "enableConditionalDirectives";
   static const String errors = 'errors';
   static const String exclude = 'exclude';
   static const String language = 'language';
   static const String plugins = 'plugins';
   static const String strong_mode = 'strong-mode';
 
+  // Strong mode options, see AnalysisOptionsImpl for documentation.
+  static const String implicitCasts = 'implicit-casts';
+  static const String implicitDynamic = 'implicit-dynamic';
+
   /// Ways to say `ignore`.
   static const List<String> ignoreSynonyms = const ['ignore', 'false'];
 
@@ -83,10 +86,10 @@
   /// Supported `analyzer` language configuration options.
   static const List<String> languageOptions = const [
     enableAsync,
-    enableConditionalDirectives,
     enableGenericMethods,
     enableStrictCallChecks,
-    enableSuperMixins
+    enableSuperMixins,
+    enableTrailingCommas
   ];
 }
 
@@ -431,9 +434,8 @@
     if (analyzer is Map) {
       // Process strong mode option.
       var strongMode = analyzer[AnalyzerOptions.strong_mode];
-      if (strongMode is bool) {
-        options.strongMode = strongMode;
-      }
+      _applyStrongOptions(options, strongMode);
+
       // Process language options.
       var language = analyzer[AnalyzerOptions.language];
       _applyLanguageOptions(options, language);
@@ -460,6 +462,19 @@
       // Process language options.
       var language = analyzer[AnalyzerOptions.language];
       setLanguageOptions(context, language);
+
+      // Process excludes.
+      var excludes = analyzer[AnalyzerOptions.exclude];
+      setExcludes(context, excludes);
+    }
+  }
+
+  void setExcludes(AnalysisContext context, Object excludes) {
+    if (excludes is YamlList) {
+      List<String> excludeList = toStringList(excludes);
+      if (excludeList != null) {
+        context.setConfigurationData(CONTEXT_EXCLUDES, excludeList);
+      }
     }
   }
 
@@ -527,12 +542,19 @@
   }
 
   void setStrongMode(AnalysisContext context, Object strongMode) {
-    bool strong = strongMode is bool ? strongMode : false;
-    if (context.analysisOptions.strongMode != strong) {
+    if (strongMode is Map) {
       AnalysisOptionsImpl options =
           new AnalysisOptionsImpl.from(context.analysisOptions);
-      options.strongMode = strong;
+      _applyStrongOptions(options, strongMode);
       context.analysisOptions = options;
+    } else {
+      strongMode = strongMode is bool ? strongMode : false;
+      if (context.analysisOptions.strongMode != strongMode) {
+        AnalysisOptionsImpl options =
+            new AnalysisOptionsImpl.from(context.analysisOptions);
+        options.strongMode = strongMode;
+        context.analysisOptions = options;
+      }
     }
   }
 
@@ -565,4 +587,33 @@
           .forEach((key, value) => _applyLanguageOption(options, key, value));
     }
   }
+
+  void _applyStrongModeOption(
+      AnalysisOptionsImpl options, Object feature, Object value) {
+    bool boolValue = toBool(value);
+    if (boolValue != null) {
+      if (feature == AnalyzerOptions.implicitCasts) {
+        options.implicitCasts = boolValue;
+      }
+      if (feature == AnalyzerOptions.implicitDynamic) {
+        options.implicitDynamic = boolValue;
+      }
+    }
+  }
+
+  void _applyStrongOptions(AnalysisOptionsImpl options, Object config) {
+    if (config is YamlMap) {
+      options.strongMode = true;
+      config.nodes.forEach((k, v) {
+        if (k is YamlScalar && v is YamlScalar) {
+          _applyStrongModeOption(options, k.value?.toString(), v.value);
+        }
+      });
+    } else if (config is Map) {
+      options.strongMode = true;
+      config.forEach((k, v) => _applyStrongModeOption(options, k, v));
+    } else {
+      options.strongMode = config is bool ? config : false;
+    }
+  }
 }
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 783cdf0..98c4aa6 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -380,6 +380,12 @@
   }
 
   @override
+  void visitFunctionExpression(FunctionExpression node) {
+    _checkForUnsafeBlockClosureInference(node);
+    super.visitFunctionExpression(node);
+  }
+
+  @override
   void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
     checkFunctionApplication(node, node.function, node.argumentList);
     node.visitChildren(this);
@@ -633,6 +639,7 @@
 
       if (!rules.isSubtypeOf(returnType, lhsType)) {
         final numType = typeProvider.numType;
+        // TODO(jmesserly): this seems to duplicate logic in StaticTypeAnalyzer.
         // Try to fix up the numerical case if possible.
         if (rules.isSubtypeOf(lhsType, numType) &&
             rules.isSubtypeOf(lhsType, rhsType)) {
@@ -640,6 +647,8 @@
           // compound operators in the int += num and num += dynamic cases.
           _recordImplicitCast(expr.rightHandSide, rhsType, lhsType);
         } else {
+          // TODO(jmesserly): this results in a duplicate error, because
+          // ErrorVerifier also reports it.
           _recordMessage(expr, StrongModeCode.STATIC_TYPE_ERROR,
               [expr, returnType, lhsType]);
         }
@@ -710,6 +719,105 @@
     node.visitChildren(this);
   }
 
+  /**
+   * Check if the closure [node] is unsafe due to dartbug.com/26947.  If so,
+   * issue a warning.
+   *
+   * TODO(paulberry): eliminate this once dartbug.com/26947 is fixed.
+   */
+  void _checkForUnsafeBlockClosureInference(FunctionExpression node) {
+    if (node.body is! BlockFunctionBody) {
+      return;
+    }
+    if (node.element.returnType.isDynamic) {
+      return;
+    }
+    // Find the enclosing variable declaration whose inferred type might depend
+    // on the inferred return type of the block closure (if any).
+    AstNode prevAncestor = node;
+    AstNode ancestor = node.parent;
+    while (ancestor != null && ancestor is! VariableDeclaration) {
+      if (ancestor is BlockFunctionBody) {
+        // node is inside another block function body; if that block
+        // function body is unsafe, we've already warned about it.
+        return;
+      }
+      if (ancestor is InstanceCreationExpression) {
+        // node appears inside an instance creation expression; we may be safe
+        // if the type of the instance creation expression requires no
+        // inference.
+        TypeName typeName = ancestor.constructorName.type;
+        if (typeName.typeArguments != null) {
+          // Type arguments were explicitly specified.  We are safe.
+          return;
+        }
+        DartType type = typeName.type;
+        if (!(type is ParameterizedType && type.typeParameters.isNotEmpty)) {
+          // Type is not generic.  We are safe.
+          return;
+        }
+      }
+      if (ancestor is MethodInvocation) {
+        // node appears inside a method or function invocation; we may be safe
+        // if the type of the method or function requires no inference.
+        if (ancestor.typeArguments != null) {
+          // Type arguments were explicitly specified.  We are safe.
+          return;
+        }
+        Element methodElement = ancestor.methodName.staticElement;
+        if (!(methodElement is ExecutableElement &&
+            methodElement.typeParameters.isNotEmpty)) {
+          // Method is not generic.  We are safe.
+          return;
+        }
+      }
+      if (ancestor is FunctionExpressionInvocation &&
+          !identical(prevAncestor, ancestor.function)) {
+        // node appears inside an argument to a function expression invocation;
+        // we may be safe if the type of the function expression requires no
+        // inference.
+        if (ancestor.typeArguments != null) {
+          // Type arguments were explicitly specified.  We are safe.
+          return;
+        }
+        DartType type = ancestor.function.staticType;
+        if (!(type is FunctionTypeImpl && type.typeFormals.isNotEmpty)) {
+          // Type is not generic or has had its type parameters instantiated.
+          // We are safe.
+          return;
+        }
+      }
+      if ((ancestor is ListLiteral && ancestor.typeArguments != null) ||
+          (ancestor is MapLiteral && ancestor.typeArguments != null)) {
+        // node appears inside a list or map literal with an explicit type.  We
+        // are safe because no type inference is required.
+        return;
+      }
+      prevAncestor = ancestor;
+      ancestor = ancestor.parent;
+    }
+    if (ancestor == null) {
+      // node is not inside a variable declaration, so it is safe.
+      return;
+    }
+    VariableDeclaration decl = ancestor;
+    VariableElement declElement = decl.element;
+    if (!declElement.hasImplicitType) {
+      // Variable declaration has an explicit type, so it's safe.
+      return;
+    }
+    if (declElement.type.isDynamic) {
+      // No type was successfully inferred for this variable, so it's safe.
+      return;
+    }
+    if (declElement.enclosingElement is ExecutableElement) {
+      // Variable declaration is inside a function or method, so it's safe.
+      return;
+    }
+    _recordMessage(node, StrongModeCode.UNSAFE_BLOCK_CLOSURE_INFERENCE,
+        [declElement.name]);
+  }
+
   void _checkReturnOrYield(Expression expression, AstNode node,
       {bool yieldStar: false}) {
     FunctionBody body = node.getAncestor((n) => n is FunctionBody);
@@ -720,14 +828,6 @@
       // analyzer error in this case.
       return;
     }
-    InterfaceType futureType = typeProvider.futureType;
-    DartType actualType = expression?.staticType;
-    if (body.isAsynchronous &&
-        !body.isGenerator &&
-        actualType is InterfaceType &&
-        actualType.element == futureType.element) {
-      type = futureType.instantiate([type]);
-    }
     // TODO(vsm): Enforce void or dynamic (to void?) when expression is null.
     if (expression != null) checkAssignment(expression, type);
   }
@@ -858,9 +958,9 @@
         // Stream<T> -> T
         expectedType = typeProvider.streamType;
       } else {
-        // Future<T> -> T
-        // TODO(vsm): Revisit with issue #228.
-        expectedType = typeProvider.futureType;
+        // Don't validate return type of async methods.
+        // They're handled by the runtime implementation.
+        return null;
       }
     } else {
       if (body.isGenerator) {
diff --git a/pkg/analyzer/lib/src/util/yaml.dart b/pkg/analyzer/lib/src/util/yaml.dart
index 4f71bd7..aa988e6 100644
--- a/pkg/analyzer/lib/src/util/yaml.dart
+++ b/pkg/analyzer/lib/src/util/yaml.dart
@@ -6,9 +6,28 @@
 
 import 'dart:collection';
 
+import 'package:yaml/yaml.dart';
+
+/// If all of the elements of [list] are strings, return a list of strings
+/// containing the same elements. Otherwise, return `null`.
+List<String> toStringList(YamlList list) {
+  if (list == null) {
+    return null;
+  }
+  List<String> stringList = <String>[];
+  for (var element in list) {
+    if (element is String) {
+      stringList.add(element);
+    } else {
+      return null;
+    }
+  }
+  return stringList;
+}
+
 /// Merges two maps (of yaml) with simple override semantics, suitable for
 /// merging two maps where one map defines default values that are added to
-/// (and possibly overriden) by an overriding map.
+/// (and possibly overridden) by an overriding map.
 class Merger {
   /// Merges a default [o1] with an overriding object [o2].
   ///
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 42066a8..1eccd93 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.27.4-alpha.15
+version: 0.27.4-alpha.19
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
@@ -9,6 +9,7 @@
   args: '>=0.12.1 <0.14.0'
   crypto: '>=1.1.1 <3.0.0'
   glob: ^1.0.3
+  isolate: ^0.2.2
   html: ^0.12.0
   package_config: ^0.1.5
   path: '>=0.9.0 <2.0.0'
diff --git a/pkg/analyzer/test/file_system/memory_file_system_test.dart b/pkg/analyzer/test/file_system/memory_file_system_test.dart
index a6adddd..5c931b1 100644
--- a/pkg/analyzer/test/file_system/memory_file_system_test.dart
+++ b/pkg/analyzer/test/file_system/memory_file_system_test.dart
@@ -204,6 +204,12 @@
     expect(file.toString(), '/foo/bar/file.txt');
   }
 
+  void test_toUri() {
+    String path = '/foo/file.txt';
+    File file = provider.newFile(path, '');
+    expect(file.toUri(), new Uri.file(path, windows: false));
+  }
+
   void test_writeAsBytesSync_existing() {
     File file = provider.newFileWithBytes('/foo/file.bin', <int>[1, 2]);
     expect(file.readAsBytesSync(), <int>[1, 2]);
@@ -387,6 +393,12 @@
     expect(parent2.path, equals('/'));
     expect(parent2.parent, isNull);
   }
+
+  void test_toUri() {
+    String path = '/foo/directory';
+    Folder folder = provider.newFolder(path);
+    expect(folder.toUri(), new Uri.directory(path, windows: false));
+  }
 }
 
 @reflectiveTest
@@ -539,6 +551,13 @@
     expect(file.exists, isFalse);
   }
 
+  test_getModificationTimes() async {
+    File file = provider.newFile('/test.dart', '');
+    Source source = file.createSource();
+    List<int> times = await provider.getModificationTimes([source]);
+    expect(times, [source.modificationStamp]);
+  }
+
   void test_getStateLocation_uniqueness() {
     String idOne = 'one';
     Folder folderOne = provider.getStateLocation(idOne);
diff --git a/pkg/analyzer/test/file_system/physical_resource_provider_test.dart b/pkg/analyzer/test/file_system/physical_resource_provider_test.dart
index 790eff7..e1f4a00 100644
--- a/pkg/analyzer/test/file_system/physical_resource_provider_test.dart
+++ b/pkg/analyzer/test/file_system/physical_resource_provider_test.dart
@@ -180,6 +180,12 @@
     expect(file.exists, isTrue);
   }
 
+  void test_toUri() {
+    String path = '/foo/file.txt';
+    File file = PhysicalResourceProvider.INSTANCE.getFile(path);
+    expect(file.toUri(), new Uri.file(path));
+  }
+
   void test_shortName() {
     expect(file.shortName, 'file.txt');
   }
@@ -373,10 +379,25 @@
       parent = grandParent;
     }
   }
+
+  void test_toUri() {
+    String path = '/foo/directory';
+    Folder folder = PhysicalResourceProvider.INSTANCE.getFolder(path);
+    expect(folder.toUri(), new Uri.directory(path));
+  }
 }
 
 @reflectiveTest
 class PhysicalResourceProviderTest extends _BaseTest {
+  test_getModificationTimes() async {
+    PhysicalResourceProvider provider = PhysicalResourceProvider.INSTANCE;
+    String path = join(tempPath, 'file1.txt');
+    new io.File(path).writeAsStringSync('');
+    Source source = provider.getFile(path).createSource();
+    List<int> times = await provider.getModificationTimes([source]);
+    expect(times, [source.modificationStamp]);
+  }
+
   void test_getStateLocation_uniqueness() {
     PhysicalResourceProvider provider = PhysicalResourceProvider.INSTANCE;
     String idOne = 'one';
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
index 5bd95e5..f3e477a 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -2244,6 +2244,18 @@
     verify([source]);
   }
 
+  void test_fieldInitializerOutsideConstructor_inFunctionTypeParameter() {
+    Source source = addSource(r'''
+class A {
+  int x;
+  A(int p(this.x));
+}''');
+    computeLibrarySourceErrors(source);
+    assertErrors(
+        source, [CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR]);
+    verify([source]);
+  }
+
   void test_fieldInitializerRedirectingConstructor_afterRedirection() {
     Source source = addSource(r'''
 class A {
diff --git a/pkg/analyzer/test/generated/element_resolver_test.dart b/pkg/analyzer/test/generated/element_resolver_test.dart
index da95f04..7ddd33b 100644
--- a/pkg/analyzer/test/generated/element_resolver_test.dart
+++ b/pkg/analyzer/test/generated/element_resolver_test.dart
@@ -301,6 +301,25 @@
     _listener.assertNoErrors();
   }
 
+  void test_visitCommentReference_prefixedIdentifier_class_operator() {
+    ClassElementImpl classA = ElementFactory.classElement2("A");
+    // set method
+    MethodElement method =
+        ElementFactory.methodElement("==", _typeProvider.boolType);
+    classA.methods = <MethodElement>[method];
+    // set name scope
+    _visitor.nameScope = new EnclosedScope(null)
+      ..defineNameWithoutChecking('A', classA);
+    // prepare "A.=="
+    PrefixedIdentifier prefixed = AstFactory.identifier5('A', '==');
+    CommentReference commentReference = new CommentReference(null, prefixed);
+    // resolve
+    _resolveNode(commentReference);
+    expect(prefixed.prefix.staticElement, classA);
+    expect(prefixed.identifier.staticElement, method);
+    _listener.assertNoErrors();
+  }
+
   void test_visitConstructorName_named() {
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String constructorName = "a";
diff --git a/pkg/analyzer/test/generated/engine_test.dart b/pkg/analyzer/test/generated/engine_test.dart
index b3ceaa5..1d0871d 100644
--- a/pkg/analyzer/test/generated/engine_test.dart
+++ b/pkg/analyzer/test/generated/engine_test.dart
@@ -702,13 +702,13 @@
   }
 
   @override
-  bool validateCacheConsistency() {
-    fail("Unexpected invocation of validateCacheConsistency");
-    return false;
+  void visitContentCache(ContentCacheVisitor visitor) {
+    fail("Unexpected invocation of visitContentCache");
   }
 
   @override
-  void visitContentCache(ContentCacheVisitor visitor) {
-    fail("Unexpected invocation of visitContentCache");
+  CacheConsistencyValidator get cacheConsistencyValidator {
+    fail("Unexpected invocation of cacheConsistencyValidator");
+    return null;
   }
 }
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index 6644ccd..e5563a5 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -1359,21 +1359,6 @@
     verify([source, source2]);
   }
 
-  void test_invalidUseOfProtectedMember_function_OK2() {
-    Source source = addSource(r'''
-import 'package:meta/meta.dart';
-class A {
-  @protected
-  void a(){ }
-}
-main() {
-  new A().a();
-}''');
-    computeLibrarySourceErrors(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
   void test_invalidUseOfProtectedMember_function_OK() {
     Source source = addSource(r'''
 import 'package:meta/meta.dart';
@@ -1390,6 +1375,21 @@
     verify([source]);
   }
 
+  void test_invalidUseOfProtectedMember_function_OK2() {
+    Source source = addSource(r'''
+import 'package:meta/meta.dart';
+class A {
+  @protected
+  void a(){ }
+}
+main() {
+  new A().a();
+}''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_invalidUseOfProtectedMember_getter() {
     Source source = addNamedSource(
         '/lib1.dart',
@@ -2047,6 +2047,21 @@
     verify([source]);
   }
 
+  void test_overrideOnNonOverridingField_invalid() {
+    Source source = addSource(r'''
+library dart.core;
+const override = null;
+class A {
+}
+class B extends A {
+  @override
+  final int m = 1;
+}''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [HintCode.OVERRIDE_ON_NON_OVERRIDING_FIELD]);
+    verify([source]);
+  }
+
   void test_overrideOnNonOverridingGetter_invalid() {
     Source source = addSource(r'''
 library dart.core;
diff --git a/pkg/analyzer/test/generated/incremental_resolver_test.dart b/pkg/analyzer/test/generated/incremental_resolver_test.dart
index f0b0107..fa0ad49 100644
--- a/pkg/analyzer/test/generated/incremental_resolver_test.dart
+++ b/pkg/analyzer/test/generated/incremental_resolver_test.dart
@@ -520,6 +520,19 @@
   CompilationUnit oldUnit;
   CompilationUnitElement oldUnitElement;
 
+  void assertSameReferencedNames(
+      ReferencedNames incNames, ReferencedNames fullNames) {
+    expectEqualSets(Iterable actual, Iterable expected) {
+      expect(actual, unorderedEquals(expected));
+    }
+    expectEqualSets(incNames.names, fullNames.names);
+    expectEqualSets(incNames.instantiatedNames, fullNames.instantiatedNames);
+    expectEqualSets(incNames.superToSubs.keys, fullNames.superToSubs.keys);
+    for (String key in fullNames.superToSubs.keys) {
+      expectEqualSets(incNames.superToSubs[key], fullNames.superToSubs[key]);
+    }
+  }
+
   @override
   void setUp() {
     super.setUp();
@@ -1300,6 +1313,25 @@
     }
   }
 
+  void test_strongMode_typeComments_insertWhitespace() {
+    _resolveUnit(r'''
+import 'dart:async';
+
+void fadeIn(int milliseconds) {
+  Future<String> f;
+  f.then/*<String>*/((e) {print("hello");});
+}
+''');
+    _updateAndValidate(r'''
+import 'dart:async';
+
+void fadeIn(int milliseconds) {
+  Future<String> f;
+  f.then/*<String>*/((e) {print("hello") ;});
+}
+''');
+  }
+
   void test_true_emptyLine_betweenClassMembers_insert() {
     _resolveUnit(r'''
 class A {
@@ -1870,6 +1902,7 @@
    */
   void _resetWithIncremental(bool enable) {
     AnalysisOptionsImpl analysisOptions = new AnalysisOptionsImpl();
+    analysisOptions.strongMode = true;
     analysisOptions.incremental = enable;
     analysisOptions.incrementalApi = enable;
     logging.logger = logger;
@@ -1909,6 +1942,8 @@
     logger.expectNoErrors();
     List<AnalysisError> newErrors = analysisContext.computeErrors(source);
     LineInfo newLineInfo = analysisContext.getLineInfo(source);
+    ReferencedNames newReferencedNames =
+        analysisContext.getResult(source, REFERENCED_NAMES);
     // check for expected failure
     if (!expectedSuccess) {
       expect(newUnit.element, isNot(same(oldUnitElement)));
@@ -1941,6 +1976,10 @@
       _assertEqualTokens(newUnit, fullNewUnit);
       // Validate LineInfo
       _assertEqualLineInfo(newLineInfo, analysisContext.getLineInfo(source));
+      // Validate referenced names.
+      ReferencedNames fullReferencedNames =
+          analysisContext.getResult(source, REFERENCED_NAMES);
+      assertSameReferencedNames(newReferencedNames, fullReferencedNames);
       // Validate that "incremental" and "full" units have the same resolution.
       try {
         assertSameResolution(newUnit, fullNewUnit, validateTypes: true);
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 1be8c5b..6156487 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -5770,6 +5770,17 @@
     verify([source]);
   }
 
+  void test_unusedShownName_unresolved() {
+    Source source = addSource(r'''
+import 'dart:math' show max, FooBar;
+main() {
+  print(max(1, 2));
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [HintCode.UNDEFINED_SHOWN_NAME]);
+  }
+
   void test_uriDoesNotExist_dll() {
     addNamedSource("/lib.dll", "");
     Source source = addSource("import 'dart-ext:lib';");
diff --git a/pkg/analyzer/test/generated/non_hint_code_test.dart b/pkg/analyzer/test/generated/non_hint_code_test.dart
index 13abb03..4ec1640 100644
--- a/pkg/analyzer/test/generated/non_hint_code_test.dart
+++ b/pkg/analyzer/test/generated/non_hint_code_test.dart
@@ -155,6 +155,26 @@
     verify([source]);
   }
 
+  void test_deadCode_deadFinalBreakInCase() {
+    Source source = addSource(r'''
+f() {
+  switch (true) {
+  case true:
+    try {
+      int a = 1;
+    } finally {
+      return;
+    }
+    break;
+  default:
+    break;
+  }
+}''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_deadCode_deadOperandLHS_and_debugConst() {
     Source source = addSource(r'''
 const bool DEBUG = false;
@@ -190,26 +210,6 @@
     verify([source]);
   }
 
-  void test_deadCode_deadFinalBreakInCase() {
-    Source source = addSource(r'''
-f() {
-  switch (true) {
-  case true:
-    try {
-      int a = 1;
-    } finally {
-      return;
-    }
-    break;
-  default:
-    break;
-  }
-}''');
-    computeLibrarySourceErrors(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
   void test_deprecatedMemberUse_inDeprecatedClass() {
     Source source = addSource(r'''
 @deprecated
@@ -486,6 +486,50 @@
     verify([source]);
   }
 
+  void test_overrideOnNonOverridingField_inInterface() {
+    Source source = addSource(r'''
+library dart.core;
+const override = null;
+class A {
+  int get a => 0;
+  void set b(_) {}
+  int c;
+}
+class B implements A {
+  @override
+  final int a = 1;
+  @override
+  int b;
+  @override
+  int c;
+}''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_overrideOnNonOverridingField_inSuperclass() {
+    Source source = addSource(r'''
+library dart.core;
+const override = null;
+class A {
+  int get a => 0;
+  void set b(_) {}
+  int c;
+}
+class B extends A {
+  @override
+  final int a = 1;
+  @override
+  int b;
+  @override
+  int c;
+}''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_overrideOnNonOverridingGetter_inInterface() {
     Source source = addSource(r'''
 library dart.core;
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 58c7c6f..e74309d 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -717,26 +717,6 @@
         [ParserErrorCode.ANNOTATION_ON_ENUM_CONSTANT]);
   }
 
-  void test_assertDoesNotTakeAssignment() {
-    parse4("parseAssertStatement", "assert(b = true);",
-        [ParserErrorCode.ASSERT_DOES_NOT_TAKE_ASSIGNMENT]);
-  }
-
-  void test_assertDoesNotTakeCascades() {
-    parse4("parseAssertStatement", "assert(new A()..m());",
-        [ParserErrorCode.ASSERT_DOES_NOT_TAKE_CASCADE]);
-  }
-
-  void test_assertDoesNotTakeRethrow() {
-    parse4("parseAssertStatement", "assert(rethrow);",
-        [ParserErrorCode.ASSERT_DOES_NOT_TAKE_RETHROW]);
-  }
-
-  void test_assertDoesNotTakeThrow() {
-    parse4("parseAssertStatement", "assert(throw x);",
-        [ParserErrorCode.ASSERT_DOES_NOT_TAKE_THROW]);
-  }
-
   void test_breakOutsideOfLoop_breakInDoStatement() {
     parse4("parseDoStatement", "do {break;} while (x);");
   }
@@ -6301,6 +6281,66 @@
     expect(identifier.offset, 9);
   }
 
+  void test_parseCommentReference_operator_withKeyword_notPrefixed() {
+    CommentReference reference =
+        parse("parseCommentReference", <Object>["operator ==", 5], "");
+    SimpleIdentifier identifier = EngineTestCase.assertInstanceOf(
+        (obj) => obj is SimpleIdentifier,
+        SimpleIdentifier,
+        reference.identifier);
+    expect(identifier.token, isNotNull);
+    expect(identifier.name, "==");
+    expect(identifier.offset, 14);
+  }
+
+  void test_parseCommentReference_operator_withKeyword_prefixed() {
+    CommentReference reference =
+        parse("parseCommentReference", <Object>["Object.operator==", 7], "");
+    PrefixedIdentifier prefixedIdentifier = EngineTestCase.assertInstanceOf(
+        (obj) => obj is PrefixedIdentifier,
+        PrefixedIdentifier,
+        reference.identifier);
+    SimpleIdentifier prefix = prefixedIdentifier.prefix;
+    expect(prefix.token, isNotNull);
+    expect(prefix.name, "Object");
+    expect(prefix.offset, 7);
+    expect(prefixedIdentifier.period, isNotNull);
+    SimpleIdentifier identifier = prefixedIdentifier.identifier;
+    expect(identifier.token, isNotNull);
+    expect(identifier.name, "==");
+    expect(identifier.offset, 22);
+  }
+
+  void test_parseCommentReference_operator_withoutKeyword_notPrefixed() {
+    CommentReference reference =
+        parse("parseCommentReference", <Object>["==", 5], "");
+    SimpleIdentifier identifier = EngineTestCase.assertInstanceOf(
+        (obj) => obj is SimpleIdentifier,
+        SimpleIdentifier,
+        reference.identifier);
+    expect(identifier.token, isNotNull);
+    expect(identifier.name, "==");
+    expect(identifier.offset, 5);
+  }
+
+  void test_parseCommentReference_operator_withoutKeyword_prefixed() {
+    CommentReference reference =
+        parse("parseCommentReference", <Object>["Object.==", 7], "");
+    PrefixedIdentifier prefixedIdentifier = EngineTestCase.assertInstanceOf(
+        (obj) => obj is PrefixedIdentifier,
+        PrefixedIdentifier,
+        reference.identifier);
+    SimpleIdentifier prefix = prefixedIdentifier.prefix;
+    expect(prefix.token, isNotNull);
+    expect(prefix.name, "Object");
+    expect(prefix.offset, 7);
+    expect(prefixedIdentifier.period, isNotNull);
+    SimpleIdentifier identifier = prefixedIdentifier.identifier;
+    expect(identifier.token, isNotNull);
+    expect(identifier.name, "==");
+    expect(identifier.offset, 14);
+  }
+
   void test_parseCommentReference_prefixed() {
     CommentReference reference =
         parse("parseCommentReference", <Object>["a.b", 7], "");
diff --git a/pkg/analyzer/test/generated/sdk_test.dart b/pkg/analyzer/test/generated/sdk_test.dart
index 8976b9c..7038f4d 100644
--- a/pkg/analyzer/test/generated/sdk_test.dart
+++ b/pkg/analyzer/test/generated/sdk_test.dart
@@ -4,14 +4,8 @@
 
 library analyzer.test.generated.sdk_test;
 
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/src/dart/ast/token.dart';
-import 'package:analyzer/src/dart/scanner/reader.dart';
-import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
 import 'package:unittest/unittest.dart';
 
 import '../reflective_tests.dart';
diff --git a/pkg/analyzer/test/generated/static_warning_code_test.dart b/pkg/analyzer/test/generated/static_warning_code_test.dart
index 9eb44ab..21c3778 100644
--- a/pkg/analyzer/test/generated/static_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_warning_code_test.dart
@@ -3527,6 +3527,12 @@
     assertErrors(source, [StaticWarningCode.UNDEFINED_IDENTIFIER]);
   }
 
+  void test_undefinedIdentifierAwait_function() {
+    Source source = addSource("void a() { await; }");
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT]);
+  }
+
   void test_undefinedIdentifier_importCore_withShow() {
     Source source = addSource(r'''
 import 'dart:core' show List;
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index 277f8bb..be5ee6b 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -798,7 +798,6 @@
         A<int, String> a1 = new D.named(3);
       }
       void test8() {
-        // Currently we only allow variable constraints.  Test that we reject.
         A<C<int>, String> a0 = new E("hello");
       }
       void test9() { // Check named and optional arguments
@@ -921,7 +920,7 @@
     {
       List<Statement> statements =
           AstFinder.getStatementsInTopLevelFunction(unit, "test8");
-      hasType(assertEOf([_isDynamic, _isDynamic]), rhs(statements[0]));
+      hasType(assertEOf([_isInt, _isString]), rhs(statements[0]));
     }
 
     {
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
index c164540..d82d135 100644
--- a/pkg/analyzer/test/generated/type_system_test.dart
+++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -891,9 +891,7 @@
     expect(_inferCall(clone, [foo.type, foo.type]), [foo.type]);
 
     // Something invalid...
-    expect(_inferCall(clone, [stringType, numType]), [
-      clonable.type.instantiate([dynamicType])
-    ]);
+    expect(_inferCall(clone, [stringType, numType]), null);
   }
 
   void test_genericCastFunction() {
@@ -1007,7 +1005,7 @@
     // <T extends num>() -> T
     var t = TypeBuilder.variable('T', bound: numType);
     var f = TypeBuilder.function(types: [t], required: [], result: t);
-    expect(_inferCall(f, [], stringType), [numType]);
+    expect(_inferCall(f, [], stringType), null);
   }
 
   void test_unifyParametersToFunctionParam() {
@@ -1024,7 +1022,7 @@
           TypeBuilder.function(required: [intType], result: dynamicType),
           TypeBuilder.function(required: [doubleType], result: dynamicType)
         ]),
-        [dynamicType]);
+        null);
   }
 
   void test_unusedReturnTypeIsDynamic() {
@@ -1045,7 +1043,7 @@
       [DartType returnType]) {
     FunctionType inferred = typeSystem.inferGenericFunctionCall(typeProvider,
         ft, ft.parameters.map((p) => p.type).toList(), arguments, returnType);
-    return inferred.typeArguments;
+    return inferred?.typeArguments;
   }
 }
 
diff --git a/pkg/analyzer/test/resource_utils.dart b/pkg/analyzer/test/resource_utils.dart
index 5936144..65f7069 100644
--- a/pkg/analyzer/test/resource_utils.dart
+++ b/pkg/analyzer/test/resource_utils.dart
@@ -4,10 +4,12 @@
 
 library analyzer.test.resource_utils;
 
+import 'dart:async';
 import 'dart:core' hide Resource;
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/util/absolute_path.dart';
 import 'package:path/path.dart' as path;
 import 'package:unittest/unittest.dart';
@@ -104,6 +106,11 @@
   Folder getFolder(String path) => _provider.getFolder(_assertPath(path));
 
   @override
+  Future<List<int>> getModificationTimes(List<Source> sources) async {
+    return sources.map((source) => 0).toList();
+  }
+
+  @override
   Resource getResource(String path) => _provider.getResource(_assertPath(path));
 
   @override
diff --git a/pkg/analyzer/test/src/context/builder_test.dart b/pkg/analyzer/test/src/context/builder_test.dart
index 758a03c..50489e4 100644
--- a/pkg/analyzer/test/src/context/builder_test.dart
+++ b/pkg/analyzer/test/src/context/builder_test.dart
@@ -9,7 +9,9 @@
 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/source/package_map_resolver.dart';
 import 'package:analyzer/src/context/builder.dart';
+import 'package:analyzer/src/context/source.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -51,12 +53,56 @@
    */
   ContentCache contentCache;
 
+  /**
+   * The context builder to be used in the test.
+   */
+  ContextBuilder builder;
+
+  /**
+   * The path to the default SDK, or `null` if the test has not explicitly
+   * invoked [createDefaultSdk].
+   */
+  String defaultSdkPath = null;
+
+  void createDefaultSdk(io.Directory tempDir) {
+    defaultSdkPath = pathContext.join(tempDir.path, 'default', 'sdk');
+    String librariesFilePath = pathContext.join(defaultSdkPath, 'lib',
+        '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart');
+    createFile(
+        librariesFilePath,
+        r'''
+const Map<String, LibraryInfo> libraries = const {
+  "async": const LibraryInfo("async/async.dart"),
+  "core": const LibraryInfo("core/core.dart"),
+};
+''');
+    sdkManager =
+        new DartSdkManager(defaultSdkPath, false, (_) => new MockSdk());
+    builder = new ContextBuilder(resourceProvider, sdkManager, contentCache);
+  }
+
+  void createDirectory(String path) {
+    new io.Directory(path).createSync(recursive: true);
+  }
+
+  void createFile(String path, String content) {
+    new io.File(path)
+      ..createSync(recursive: true)
+      ..writeAsStringSync(content);
+  }
+
   @override
   void setUp() {
     resourceProvider = PhysicalResourceProvider.INSTANCE;
     pathContext = resourceProvider.pathContext;
     sdkManager = new DartSdkManager('', false, (_) => new MockSdk());
     contentCache = new ContentCache();
+    builder = new ContextBuilder(resourceProvider, sdkManager, contentCache);
+  }
+
+  @failingTest
+  void test_buildContext() {
+    fail('Incomplete test');
   }
 
   void test_createPackageMap_fromPackageDirectory_explicit() {
@@ -69,12 +115,10 @@
       String fooPath = pathContext.join(packageDirPath, fooName);
       String barName = 'bar';
       String barPath = pathContext.join(packageDirPath, barName);
-      new io.Directory(projectPath).createSync(recursive: true);
-      new io.Directory(fooPath).createSync(recursive: true);
-      new io.Directory(barPath).createSync(recursive: true);
+      createDirectory(projectPath);
+      createDirectory(fooPath);
+      createDirectory(barPath);
 
-      ContextBuilder builder =
-          new ContextBuilder(resourceProvider, sdkManager, contentCache);
       builder.defaultPackagesDirectoryPath = packageDirPath;
 
       Packages packages = builder.createPackageMap(projectPath);
@@ -95,11 +139,9 @@
       String fooPath = pathContext.join(packageDirPath, fooName);
       String barName = 'bar';
       String barPath = pathContext.join(packageDirPath, barName);
-      new io.Directory(fooPath).createSync(recursive: true);
-      new io.Directory(barPath).createSync(recursive: true);
+      createDirectory(fooPath);
+      createDirectory(barPath);
 
-      ContextBuilder builder =
-          new ContextBuilder(resourceProvider, sdkManager, contentCache);
       Packages packages = builder.createPackageMap(projectPath);
       expect(packages, isNotNull);
       Map<String, Uri> map = packages.asMap();
@@ -115,16 +157,14 @@
       String rootPath = tempDir.path;
       String projectPath = pathContext.join(rootPath, 'project');
       String packageFilePath = pathContext.join(rootPath, 'child', '.packages');
-      new io.Directory(projectPath).createSync(recursive: true);
-      new io.File(packageFilePath)
-        ..createSync(recursive: true)
-        ..writeAsStringSync(r'''
+      createDirectory(projectPath);
+      createFile(
+          packageFilePath,
+          r'''
 foo:/pkg/foo
 bar:/pkg/bar
 ''');
 
-      ContextBuilder builder =
-          new ContextBuilder(resourceProvider, sdkManager, contentCache);
       builder.defaultPackageFilePath = packageFilePath;
       Packages packages = builder.createPackageMap(projectPath);
       expect(packages, isNotNull);
@@ -141,16 +181,14 @@
       String rootPath = tempDir.path;
       String projectPath = pathContext.join(rootPath, 'project');
       String packageFilePath = pathContext.join(rootPath, '.packages');
-      new io.Directory(projectPath).createSync(recursive: true);
-      new io.File(packageFilePath)
-        ..createSync(recursive: true)
-        ..writeAsStringSync(r'''
+      createDirectory(projectPath);
+      createFile(
+          packageFilePath,
+          r'''
 foo:/pkg/foo
 bar:/pkg/bar
 ''');
 
-      ContextBuilder builder =
-          new ContextBuilder(resourceProvider, sdkManager, contentCache);
       Packages packages = builder.createPackageMap(projectPath);
       expect(packages, isNotNull);
       Map<String, Uri> map = packages.asMap();
@@ -166,16 +204,14 @@
       String rootPath = tempDir.path;
       String projectPath = pathContext.join(rootPath, 'project');
       String packageFilePath = pathContext.join(projectPath, '.packages');
-      new io.Directory(projectPath).createSync(recursive: true);
-      new io.File(packageFilePath)
-        ..createSync(recursive: true)
-        ..writeAsStringSync(r'''
+      createDirectory(projectPath);
+      createFile(
+          packageFilePath,
+          r'''
 foo:/pkg/foo
 bar:/pkg/bar
 ''');
 
-      ContextBuilder builder =
-          new ContextBuilder(resourceProvider, sdkManager, contentCache);
       Packages packages = builder.createPackageMap(projectPath);
       expect(packages, isNotNull);
       Map<String, Uri> map = packages.asMap();
@@ -187,13 +223,192 @@
 
   void test_createPackageMap_none() {
     withTempDir((io.Directory tempDir) {
-      ContextBuilder builder =
-          new ContextBuilder(resourceProvider, sdkManager, contentCache);
       Packages packages = builder.createPackageMap(tempDir.path);
       expect(packages, same(Packages.noPackages));
     });
   }
 
+  void test_createSourceFactory_fileProvider() {
+    withTempDir((io.Directory tempDir) {
+      createDefaultSdk(tempDir);
+      String rootPath = tempDir.path;
+      String projectPath = pathContext.join(rootPath, 'project');
+      String packageFilePath = pathContext.join(projectPath, '.packages');
+      String packageA = pathContext.join(rootPath, 'pkgs', 'a');
+      String packageB = pathContext.join(rootPath, 'pkgs', 'b');
+      createFile(
+          packageFilePath,
+          '''
+a:${pathContext.toUri(packageA)}
+b:${pathContext.toUri(packageB)}
+''');
+      AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+      UriResolver resolver = new ResourceUriResolver(resourceProvider);
+      builder.fileResolverProvider = (folder) => resolver;
+      SourceFactoryImpl factory =
+          builder.createSourceFactory(projectPath, options);
+      expect(factory.resolvers, contains(same(resolver)));
+    });
+  }
+
+  void test_createSourceFactory_noProvider_packages_embedder_extensions() {
+    withTempDir((io.Directory tempDir) {
+      createDefaultSdk(tempDir);
+      String rootPath = tempDir.path;
+      String projectPath = pathContext.join(rootPath, 'project');
+      String packageFilePath = pathContext.join(projectPath, '.packages');
+      String packageA = pathContext.join(rootPath, 'pkgs', 'a');
+      String embedderPath = pathContext.join(packageA, '_embedder.yaml');
+      String packageB = pathContext.join(rootPath, 'pkgs', 'b');
+      String extensionPath = pathContext.join(packageB, '_sdkext');
+      createFile(
+          packageFilePath,
+          '''
+a:${pathContext.toUri(packageA)}
+b:${pathContext.toUri(packageB)}
+''');
+      String asyncPath = pathContext.join(packageA, 'sdk', 'async.dart');
+      String corePath = pathContext.join(packageA, 'sdk', 'core.dart');
+      createFile(
+          embedderPath,
+          '''
+embedded_libs:
+  "dart:async": ${_relativeUri(asyncPath, from: packageA)}
+  "dart:core": ${_relativeUri(corePath, from: packageA)}
+''');
+      String fooPath = pathContext.join(packageB, 'ext', 'foo.dart');
+      createFile(
+          extensionPath,
+          '''{
+"dart:foo": "${_relativeUri(fooPath, from: packageB)}"
+}''');
+      AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+
+      SourceFactory factory = builder.createSourceFactory(projectPath, options);
+
+      Source asyncSource = factory.forUri('dart:async');
+      expect(asyncSource, isNotNull);
+      expect(asyncSource.fullName, asyncPath);
+
+      Source fooSource = factory.forUri('dart:foo');
+      expect(fooSource, isNotNull);
+      expect(fooSource.fullName, fooPath);
+
+      Source packageSource = factory.forUri('package:b/b.dart');
+      expect(packageSource, isNotNull);
+      expect(packageSource.fullName, pathContext.join(packageB, 'b.dart'));
+    });
+  }
+
+  void test_createSourceFactory_noProvider_packages_embedder_noExtensions() {
+    withTempDir((io.Directory tempDir) {
+      createDefaultSdk(tempDir);
+      String rootPath = tempDir.path;
+      String projectPath = pathContext.join(rootPath, 'project');
+      String packageFilePath = pathContext.join(projectPath, '.packages');
+      String packageA = pathContext.join(rootPath, 'pkgs', 'a');
+      String embedderPath = pathContext.join(packageA, '_embedder.yaml');
+      String packageB = pathContext.join(rootPath, 'pkgs', 'b');
+      createFile(
+          packageFilePath,
+          '''
+a:${pathContext.toUri(packageA)}
+b:${pathContext.toUri(packageB)}
+''');
+      String asyncPath = pathContext.join(packageA, 'sdk', 'async.dart');
+      String corePath = pathContext.join(packageA, 'sdk', 'core.dart');
+      createFile(
+          embedderPath,
+          '''
+embedded_libs:
+  "dart:async": ${_relativeUri(asyncPath, from: packageA)}
+  "dart:core": ${_relativeUri(corePath, from: packageA)}
+''');
+      AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+
+      SourceFactory factory = builder.createSourceFactory(projectPath, options);
+
+      Source dartSource = factory.forUri('dart:async');
+      expect(dartSource, isNotNull);
+      expect(dartSource.fullName, asyncPath);
+
+      Source packageSource = factory.forUri('package:b/b.dart');
+      expect(packageSource, isNotNull);
+      expect(packageSource.fullName, pathContext.join(packageB, 'b.dart'));
+    });
+  }
+
+  @failingTest
+  void test_createSourceFactory_noProvider_packages_noEmbedder_extensions() {
+    fail('Incomplete test');
+  }
+
+  void test_createSourceFactory_noProvider_packages_noEmbedder_noExtensions() {
+    withTempDir((io.Directory tempDir) {
+      createDefaultSdk(tempDir);
+      String rootPath = tempDir.path;
+      String projectPath = pathContext.join(rootPath, 'project');
+      String packageFilePath = pathContext.join(projectPath, '.packages');
+      String packageA = pathContext.join(rootPath, 'pkgs', 'a');
+      String packageB = pathContext.join(rootPath, 'pkgs', 'b');
+      createFile(
+          packageFilePath,
+          '''
+a:${pathContext.toUri(packageA)}
+b:${pathContext.toUri(packageB)}
+''');
+      AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+
+      SourceFactory factory = builder.createSourceFactory(projectPath, options);
+
+      Source dartSource = factory.forUri('dart:core');
+      expect(dartSource, isNotNull);
+      expect(dartSource.fullName, '$defaultSdkPath/lib/core/core.dart');
+
+      Source packageSource = factory.forUri('package:a/a.dart');
+      expect(packageSource, isNotNull);
+      expect(packageSource.fullName, pathContext.join(packageA, 'a.dart'));
+    });
+  }
+
+  void test_createSourceFactory_packageProvider() {
+    withTempDir((io.Directory tempDir) {
+      createDefaultSdk(tempDir);
+      String rootPath = tempDir.path;
+      String projectPath = pathContext.join(rootPath, 'project');
+      AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+      UriResolver resolver = new PackageMapUriResolver(resourceProvider, {});
+      builder.packageResolverProvider = (folder) => resolver;
+      SourceFactoryImpl factory =
+          builder.createSourceFactory(projectPath, options);
+      expect(factory.resolvers, contains(same(resolver)));
+    });
+  }
+
+  @failingTest
+  void test_findSdk_embedder_extensions() {
+    // See test_createSourceFactory_noProvider_packages_embedder_extensions
+    fail('Incomplete test');
+  }
+
+  @failingTest
+  void test_findSdk_embedder_noExtensions() {
+    // See test_createSourceFactory_noProvider_packages_embedder_noExtensions
+    fail('Incomplete test');
+  }
+
+  @failingTest
+  void test_findSdk_noEmbedder_extensions() {
+    // See test_createSourceFactory_noProvider_packages_noEmbedder_extensions
+    fail('Incomplete test');
+  }
+
+  @failingTest
+  void test_findSdk_noEmbedder_noExtensions() {
+    // See test_createSourceFactory_noProvider_packages_noEmbedder_noExtensions
+    fail('Incomplete test');
+  }
+
   /**
    * Execute the [test] function with a temporary [directory]. The test function
    * can perform any disk operations within the directory and the directory (and
@@ -208,6 +423,11 @@
       directory.deleteSync(recursive: true);
     }
   }
+
+  Uri _relativeUri(String path, {String from}) {
+    String relativePath = pathContext.relative(path, from: from);
+    return pathContext.toUri(relativePath);
+  }
 }
 
 @reflectiveTest
@@ -227,30 +447,24 @@
    */
   ContentCache contentCache;
 
-  void fail_createSourceFactory() {
-    fail('Incomplete test');
-  }
-
-  void fail_findSdkResolver() {
-    fail('Incomplete test');
-  }
+  /**
+   * The context builder to be used in the test.
+   */
+  ContextBuilder builder;
 
   @override
   void setUp() {
     resourceProvider = new MemoryResourceProvider();
     sdkManager = new DartSdkManager('', false, (_) => new MockSdk());
     contentCache = new ContentCache();
+    builder = new ContextBuilder(resourceProvider, sdkManager, contentCache);
   }
 
   void test_convertPackagesToMap_noPackages() {
-    ContextBuilder builder =
-        new ContextBuilder(resourceProvider, sdkManager, contentCache);
     expect(builder.convertPackagesToMap(Packages.noPackages), isNull);
   }
 
   void test_convertPackagesToMap_null() {
-    ContextBuilder builder =
-        new ContextBuilder(resourceProvider, sdkManager, contentCache);
     expect(builder.convertPackagesToMap(null), isNull);
   }
 
@@ -262,8 +476,6 @@
     String barPath = '/pkg/bar';
     Uri barUri = new Uri.directory(barPath);
 
-    ContextBuilder builder =
-        new ContextBuilder(resourceProvider, sdkManager, contentCache);
     MapPackages packages = new MapPackages({fooName: fooUri, barName: barUri});
     Map<String, List<Folder>> result = builder.convertPackagesToMap(packages);
     expect(result, isNotNull);
@@ -274,13 +486,137 @@
     expect(result[barName][0].path, barPath);
   }
 
+  void test_createDefaultOptions_default() {
+    // Invert a subset of the options to ensure that the default options are
+    // being returned.
+    AnalysisOptionsImpl defaultOptions = new AnalysisOptionsImpl();
+    defaultOptions.dart2jsHint = !defaultOptions.dart2jsHint;
+    defaultOptions.enableAssertMessage = !defaultOptions.enableAssertMessage;
+    defaultOptions.enableAsync = !defaultOptions.enableAsync;
+    defaultOptions.enableGenericMethods = !defaultOptions.enableGenericMethods;
+    defaultOptions.enableStrictCallChecks =
+        !defaultOptions.enableStrictCallChecks;
+    defaultOptions.enableSuperMixins = !defaultOptions.enableSuperMixins;
+    builder.defaultOptions = defaultOptions;
+    AnalysisOptions options = builder.createDefaultOptions();
+    _expectEqualOptions(options, defaultOptions);
+  }
+
+  void test_createDefaultOptions_noDefault() {
+    AnalysisOptions options = builder.createDefaultOptions();
+    _expectEqualOptions(options, new AnalysisOptionsImpl());
+  }
+
+  void test_declareVariables_emptyMap() {
+    AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
+    Iterable<String> expected = context.declaredVariables.variableNames;
+    builder.declaredVariables = <String, String>{};
+
+    builder.declareVariables(context);
+    expect(context.declaredVariables.variableNames, unorderedEquals(expected));
+  }
+
+  void test_declareVariables_nonEmptyMap() {
+    AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
+    List<String> expected = context.declaredVariables.variableNames.toList();
+    expect(expected, isNot(contains('a')));
+    expect(expected, isNot(contains('b')));
+    expected.addAll(['a', 'b']);
+    builder.declaredVariables = <String, String>{'a': 'a', 'b': 'b'};
+
+    builder.declareVariables(context);
+    expect(context.declaredVariables.variableNames, unorderedEquals(expected));
+  }
+
+  void test_declareVariables_null() {
+    AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
+    Iterable<String> expected = context.declaredVariables.variableNames;
+
+    builder.declareVariables(context);
+    expect(context.declaredVariables.variableNames, unorderedEquals(expected));
+  }
+
+  void test_findSdk_noPackageMap() {
+    DartSdk sdk = builder.findSdk(null, new AnalysisOptionsImpl());
+    expect(sdk, isNotNull);
+  }
+
+  void test_getAnalysisOptions_default_noOverrides() {
+    AnalysisOptionsImpl defaultOptions = new AnalysisOptionsImpl();
+    defaultOptions.enableGenericMethods = true;
+    builder.defaultOptions = defaultOptions;
+    AnalysisOptionsImpl expected = new AnalysisOptionsImpl();
+    expected.enableGenericMethods = true;
+    String path = '/some/directory/path';
+    String filePath = '$path/${AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE}';
+    resourceProvider.newFile(
+        filePath,
+        '''
+linter:
+  rules:
+    - empty_constructor_bodies
+''');
+
+    AnalysisOptions options = builder.getAnalysisOptions(path);
+    _expectEqualOptions(options, expected);
+  }
+
+  void test_getAnalysisOptions_default_overrides() {
+    AnalysisOptionsImpl defaultOptions = new AnalysisOptionsImpl();
+    defaultOptions.enableGenericMethods = true;
+    builder.defaultOptions = defaultOptions;
+    AnalysisOptionsImpl expected = new AnalysisOptionsImpl();
+    expected.enableAsync = true;
+    expected.enableGenericMethods = true;
+    String path = '/some/directory/path';
+    String filePath = '$path/${AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE}';
+    resourceProvider.newFile(
+        filePath,
+        '''
+analyzer:
+  enableAsync : true
+''');
+
+    AnalysisOptions options = builder.getAnalysisOptions(path);
+    _expectEqualOptions(options, expected);
+  }
+
+  void test_getAnalysisOptions_noDefault_noOverrides() {
+    String path = '/some/directory/path';
+    String filePath = '$path/${AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE}';
+    resourceProvider.newFile(
+        filePath,
+        '''
+linter:
+  rules:
+    - empty_constructor_bodies
+''');
+
+    AnalysisOptions options = builder.getAnalysisOptions(path);
+    _expectEqualOptions(options, new AnalysisOptionsImpl());
+  }
+
+  void test_getAnalysisOptions_noDefault_overrides() {
+    AnalysisOptionsImpl expected = new AnalysisOptionsImpl();
+    expected.enableAsync = true;
+    String path = '/some/directory/path';
+    String filePath = '$path/${AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE}';
+    resourceProvider.newFile(
+        filePath,
+        '''
+analyzer:
+  enableAsync : true
+''');
+
+    AnalysisOptions options = builder.getAnalysisOptions(path);
+    _expectEqualOptions(options, expected);
+  }
+
   void test_getOptionsFile_explicit() {
     String path = '/some/directory/path';
     String filePath = '/options/analysis.yaml';
     resourceProvider.newFile(filePath, '');
 
-    ContextBuilder builder =
-        new ContextBuilder(resourceProvider, sdkManager, contentCache);
     builder.defaultAnalysisOptionsFilePath = filePath;
     File result = builder.getOptionsFile(path);
     expect(result, isNotNull);
@@ -294,8 +630,6 @@
         '$parentPath/${AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE}';
     resourceProvider.newFile(filePath, '');
 
-    ContextBuilder builder =
-        new ContextBuilder(resourceProvider, sdkManager, contentCache);
     File result = builder.getOptionsFile(path);
     expect(result, isNotNull);
     expect(result.path, filePath);
@@ -307,8 +641,6 @@
     String filePath = '$parentPath/${AnalysisEngine.ANALYSIS_OPTIONS_FILE}';
     resourceProvider.newFile(filePath, '');
 
-    ContextBuilder builder =
-        new ContextBuilder(resourceProvider, sdkManager, contentCache);
     File result = builder.getOptionsFile(path);
     expect(result, isNotNull);
     expect(result.path, filePath);
@@ -319,8 +651,6 @@
     String filePath = '$path/${AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE}';
     resourceProvider.newFile(filePath, '');
 
-    ContextBuilder builder =
-        new ContextBuilder(resourceProvider, sdkManager, contentCache);
     File result = builder.getOptionsFile(path);
     expect(result, isNotNull);
     expect(result.path, filePath);
@@ -331,10 +661,38 @@
     String filePath = '$path/${AnalysisEngine.ANALYSIS_OPTIONS_FILE}';
     resourceProvider.newFile(filePath, '');
 
-    ContextBuilder builder =
-        new ContextBuilder(resourceProvider, sdkManager, contentCache);
     File result = builder.getOptionsFile(path);
     expect(result, isNotNull);
     expect(result.path, filePath);
   }
+
+  void _expectEqualOptions(
+      AnalysisOptionsImpl actual, AnalysisOptionsImpl expected) {
+    // TODO(brianwilkerson) Consider moving this to AnalysisOptionsImpl.==.
+    expect(actual.analyzeFunctionBodiesPredicate,
+        same(expected.analyzeFunctionBodiesPredicate));
+    expect(actual.cacheSize, expected.cacheSize);
+    expect(actual.dart2jsHint, expected.dart2jsHint);
+    expect(actual.enableAssertMessage, expected.enableAssertMessage);
+    expect(actual.enableAsync, expected.enableAsync);
+    expect(actual.enableStrictCallChecks, expected.enableStrictCallChecks);
+    expect(actual.enableGenericMethods, expected.enableGenericMethods);
+    expect(actual.enableSuperMixins, expected.enableSuperMixins);
+    expect(actual.enableTiming, expected.enableTiming);
+    expect(actual.enableTrailingCommas, expected.enableTrailingCommas);
+    expect(actual.generateImplicitErrors, expected.generateImplicitErrors);
+    expect(actual.generateSdkErrors, expected.generateSdkErrors);
+    expect(actual.hint, expected.hint);
+    expect(actual.incremental, expected.incremental);
+    expect(actual.incrementalApi, expected.incrementalApi);
+    expect(actual.incrementalValidation, expected.incrementalValidation);
+    expect(actual.lint, expected.lint);
+    expect(actual.preserveComments, expected.preserveComments);
+    expect(actual.strongMode, expected.strongMode);
+    expect(actual.strongModeHints, expected.strongModeHints);
+    expect(actual.implicitCasts, expected.implicitCasts);
+    expect(actual.implicitDynamic, expected.implicitDynamic);
+    expect(actual.trackCacheDependencies, expected.trackCacheDependencies);
+    expect(actual.finerGrainedInvalidation, expected.finerGrainedInvalidation);
+  }
 }
diff --git a/pkg/analyzer/test/src/context/cache_test.dart b/pkg/analyzer/test/src/context/cache_test.dart
index b03791a..ab35ffb 100644
--- a/pkg/analyzer/test/src/context/cache_test.dart
+++ b/pkg/analyzer/test/src/context/cache_test.dart
@@ -4,6 +4,9 @@
 
 library analyzer.test.src.context.cache_test;
 
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
@@ -778,6 +781,28 @@
     expect(entry.getValue(result2), 222);
   }
 
+  test_setValue_userBeforeProvider_invalidateProvider_alsoUser() {
+    AnalysisTarget target1 = new TestSource('/a.dart');
+    AnalysisTarget target2 = new TestSource('/b.dart');
+    CacheEntry entry1 = new CacheEntry(target1);
+    CacheEntry entry2 = new CacheEntry(target2);
+    cache.put(entry1);
+    cache.put(entry2);
+    ResultDescriptor result1 = new ResultDescriptor('result1', -1);
+    ResultDescriptor result2 = new ResultDescriptor('result2', -2);
+    // set results, all of them are VALID
+    entry2.setValue(result2, 222, [new TargetedResult(target1, result1)]);
+    entry1.setValue(result1, 111, TargetedResult.EMPTY_LIST);
+    expect(entry1.getState(result1), CacheState.VALID);
+    expect(entry2.getState(result2), CacheState.VALID);
+    expect(entry1.getValue(result1), 111);
+    expect(entry2.getValue(result2), 222);
+    // invalidate result1, should invalidate also result2
+    entry1.setState(result1, CacheState.INVALID);
+    expect(entry1.getState(result1), CacheState.INVALID);
+    expect(entry2.getState(result2), CacheState.INVALID);
+  }
+
   test_setValueIncremental() {
     AnalysisTarget target = new TestSource();
     CacheEntry entry = new CacheEntry(target);
@@ -1079,6 +1104,35 @@
 }
 
 @reflectiveTest
+class PackageCachePartitionTest extends CachePartitionTest {
+  MemoryResourceProvider resourceProvider;
+  Folder rootFolder;
+
+  CachePartition createPartition() {
+    resourceProvider = new MemoryResourceProvider();
+    rootFolder = resourceProvider.newFolder('/package/root');
+    return new PackageCachePartition(null, rootFolder);
+  }
+
+  void test_contains_false() {
+    CachePartition partition = createPartition();
+    AnalysisTarget target = new TestSource();
+    expect(partition.isResponsibleFor(target), isFalse);
+  }
+
+  void test_contains_true() {
+    SdkCachePartition partition = new SdkCachePartition(null);
+    SourceFactory factory = new SourceFactory([
+      new PackageMapUriResolver(resourceProvider, <String, List<Folder>>{
+        'root': <Folder>[rootFolder]
+      })
+    ]);
+    AnalysisTarget target = factory.forUri("package:root/root.dart");
+    expect(partition.isResponsibleFor(target), isTrue);
+  }
+}
+
+@reflectiveTest
 class ResultDataTest extends EngineTestCase {
   test_creation() {
     String value = 'value';
@@ -1177,6 +1231,15 @@
   _KeepContinueDelta(this.source, this.keepDescriptor);
 
   @override
+  bool gatherChanges(InternalAnalysisContext context, AnalysisTarget target,
+      ResultDescriptor descriptor, Object value) {
+    return false;
+  }
+
+  @override
+  void gatherEnd() {}
+
+  @override
   DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target,
       ResultDescriptor descriptor, Object value) {
     if (descriptor == keepDescriptor) {
diff --git a/pkg/analyzer/test/src/context/context_factory_test.dart b/pkg/analyzer/test/src/context/context_factory_test.dart
deleted file mode 100644
index a116d29..0000000
--- a/pkg/analyzer/test/src/context/context_factory_test.dart
+++ /dev/null
@@ -1,159 +0,0 @@
-// 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.src.context.context_factory_test;
-
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/src/context/context_factory.dart';
-import 'package:unittest/unittest.dart';
-
-import '../../reflective_tests.dart';
-import '../../utils.dart';
-
-main() {
-  initializeTestEnvironment();
-  runReflectiveTests(PackageMapProcessorTest);
-}
-
-@reflectiveTest
-class PackageMapProcessorTest {
-  MemoryResourceProvider resourceProvider;
-
-  Folder empty;
-  Folder tmp_sdk_ext;
-  Folder tmp_embedder;
-  Map<String, List<Folder>> packageMap;
-
-  void setUp() {
-    resourceProvider = new MemoryResourceProvider();
-    empty = resourceProvider.newFolder('/empty');
-    tmp_sdk_ext = resourceProvider.newFolder('/tmp_sdk_ext');
-    tmp_embedder = resourceProvider.newFolder('/tmp_embedder');
-    packageMap = <String, List<Folder>>{
-      'empty': [empty],
-      'tmp_embedder': [tmp_embedder],
-      'tmp_sdk_ext': [tmp_sdk_ext]
-    };
-  }
-
-  void test_basic_processing() {
-    resourceProvider.newFile(
-        '/tmp_sdk_ext/_sdkext',
-        r'''
-  {
-    "dart:ui": "ui.dart"
-  }''');
-    resourceProvider.newFile(
-        '/tmp_embedder/_embedder.yaml',
-        r'''
-embedded_libs:
-  "dart:core" : "core.dart"
-  "dart:fox": "slippy.dart"
-  "dart:bear": "grizzly.dart"
-  "dart:relative": "../relative.dart"
-  "dart:deep": "deep/directory/file.dart"
-''');
-
-    PackageMapProcessor proc = new PackageMapProcessor(packageMap);
-    expect(proc.embeddedLibraries.size(), 5);
-    expect(proc.embeddedLibraries.getLibrary('dart:core').path,
-        '/tmp_embedder/core.dart');
-    expect(proc.extendedLibraries.size(), 1);
-    expect(proc.extendedLibraries.getLibrary('dart:ui').path,
-        '/tmp_sdk_ext/ui.dart');
-  }
-
-  void test_empty_package_map() {
-    PackageMapProcessor proc =
-        new PackageMapProcessor(<String, List<Folder>>{});
-    expect(proc.embeddedLibraries.size(), 0);
-    expect(proc.extendedLibraries.size(), 0);
-    expect(proc.libraryMap.size(), 0);
-  }
-
-  void test_extenders_do_not_override() {
-    resourceProvider.newFile(
-        '/tmp_sdk_ext/_sdkext',
-        r'''
-  {
-    "dart:ui": "ui2.dart"
-  }''');
-    resourceProvider.newFile(
-        '/tmp_embedder/_embedder.yaml',
-        r'''
-embedded_libs:
-  "dart:core" : "core.dart"
-  "dart:ui": "ui.dart"
-''');
-
-    PackageMapProcessor proc = new PackageMapProcessor(packageMap);
-    expect(proc.embeddedLibraries.size(), 2);
-    expect(proc.extendedLibraries.size(), 1);
-    expect(proc.libraryMap.size(), 2);
-    expect(proc.libraryMap.getLibrary('dart:ui').path, '/tmp_embedder/ui.dart');
-  }
-
-  void test_invalid_embedder() {
-    resourceProvider.newFile(
-        '/tmp_embedder/_embedder.yaml',
-        r'''
-invalid contents, will not parse
-''');
-
-    PackageMapProcessor proc = new PackageMapProcessor(packageMap);
-    expect(proc.embeddedLibraries.size(), 0);
-    expect(proc.extendedLibraries.size(), 0);
-    expect(proc.libraryMap.size(), 0);
-  }
-
-  void test_invalid_extender() {
-    resourceProvider.newFile(
-        '/tmp_sdk_ext/_sdkext',
-        r'''
-invalid contents, will not parse
-''');
-
-    PackageMapProcessor proc = new PackageMapProcessor(packageMap);
-    expect(proc.embeddedLibraries.size(), 0);
-    expect(proc.extendedLibraries.size(), 0);
-    expect(proc.libraryMap.size(), 0);
-  }
-
-  void test_no_embedder() {
-    resourceProvider.newFile(
-        '/tmp_sdk_ext/_sdkext',
-        r'''
-  {
-    "dart:ui": "ui2.dart"
-  }''');
-
-    PackageMapProcessor proc = new PackageMapProcessor(packageMap);
-    expect(proc.embeddedLibraries.size(), 0);
-    expect(proc.extendedLibraries.size(), 1);
-    expect(proc.libraryMap.size(), 1);
-  }
-
-  void test_no_embedder_or_extender() {
-    PackageMapProcessor proc = new PackageMapProcessor(packageMap);
-    expect(proc.embeddedLibraries.size(), 0);
-    expect(proc.extendedLibraries.size(), 0);
-    expect(proc.libraryMap.size(), 0);
-  }
-
-  void test_no_extender() {
-    resourceProvider.newFile(
-        '/tmp_embedder/_embedder.yaml',
-        r'''
-embedded_libs:
-  "dart:core" : "core.dart"
-  "dart:ui": "ui.dart"
-''');
-
-    PackageMapProcessor proc = new PackageMapProcessor(packageMap);
-    expect(proc.embeddedLibraries.size(), 2);
-    expect(proc.extendedLibraries.size(), 0);
-    expect(proc.libraryMap.size(), 2);
-  }
-}
diff --git a/pkg/analyzer/test/src/context/context_test.dart b/pkg/analyzer/test/src/context/context_test.dart
index a2f3cb3..28dceb7 100644
--- a/pkg/analyzer/test/src/context/context_test.dart
+++ b/pkg/analyzer/test/src/context/context_test.dart
@@ -11,11 +11,13 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/visitor.dart';
+import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/cancelable_future.dart';
 import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
@@ -279,6 +281,26 @@
     });
   }
 
+  void test_applyChanges_changedSource_updateModificationTime() {
+    String path = '/test.dart';
+    File file = resourceProvider.newFile(path, 'var V = 1;');
+    Source source = file.createSource();
+    context.applyChanges(new ChangeSet()..addedSource(source));
+    // Analyze all.
+    _analyzeAll_assertFinished();
+    expect(context.analysisCache.getState(source, RESOLVED_UNIT),
+        CacheState.INVALID);
+    // Update the file and notify the context about the change.
+    resourceProvider.updateFile(path, 'var V = 2;');
+    context.applyChanges(new ChangeSet()..changedSource(source));
+    // The analysis results are invalidated.
+    // We have seen the new contents, so 'modificationTime' is also updated.
+    expect(context.analysisCache.getState(source, RESOLVED_UNIT),
+        CacheState.INVALID);
+    expect(
+        context.getCacheEntry(source).modificationTime, file.modificationStamp);
+  }
+
   void test_applyChanges_empty() {
     context.applyChanges(new ChangeSet());
     expect(context.performAnalysisTask().changeNotices, isNull);
@@ -401,7 +423,6 @@
     expect(context.getResolvedCompilationUnit2(source, source), unit);
     // remove overlay
     context.setContents(source, null);
-    context.validateCacheConsistency();
     _analyzeAll_assertFinished();
     expect(context.getResolvedCompilationUnit2(source, source), unit);
   }
@@ -434,6 +455,50 @@
     });
   }
 
+  void test_cacheConsistencyValidator_computed() {
+    CacheConsistencyValidator validator = context.cacheConsistencyValidator;
+    // Add sources.
+    MemoryResourceProvider resourceProvider = new MemoryResourceProvider();
+    String path1 = '/test1.dart';
+    String path2 = '/test2.dart';
+    Source source1 = resourceProvider.newFile(path1, '// 1-1').createSource();
+    Source source2 = resourceProvider.newFile(path2, '// 2-1').createSource();
+    context.applyChanges(
+        new ChangeSet()..addedSource(source1)..addedSource(source2));
+    // Same modification times.
+    expect(
+        validator.sourceModificationTimesComputed([source1, source2],
+            [source1.modificationStamp, source2.modificationStamp]),
+        isFalse);
+    // Add overlay
+    context.setContents(source1, '// 1-2');
+    expect(
+        validator.sourceModificationTimesComputed([source1, source2],
+            [source1.modificationStamp + 1, source2.modificationStamp]),
+        isFalse);
+    context.setContents(source1, null);
+    // Different modification times.
+    expect(
+        validator.sourceModificationTimesComputed([source1, source2],
+            [source1.modificationStamp + 1, source2.modificationStamp]),
+        isTrue);
+  }
+
+  void test_cacheConsistencyValidator_getSources() {
+    CacheConsistencyValidator validator = context.cacheConsistencyValidator;
+    // Add sources.
+    MemoryResourceProvider resourceProvider = new MemoryResourceProvider();
+    String path1 = '/test1.dart';
+    String path2 = '/test2.dart';
+    Source source1 = resourceProvider.newFile(path1, '// 1-1').createSource();
+    Source source2 = resourceProvider.newFile(path2, '// 2-1').createSource();
+    context.applyChanges(
+        new ChangeSet()..addedSource(source1)..addedSource(source2));
+    // Verify.
+    expect(validator.getSourcesToComputeModificationTimes(),
+        unorderedEquals([source1, source2]));
+  }
+
   void test_computeDocumentationComment_class_block() {
     String comment = "/** Comment */";
     Source source = addSource(
@@ -2079,7 +2144,7 @@
     if (context.analysisOptions.finerGrainedInvalidation) {
       expect(source.readCount, 7);
     } else {
-      expect(source.readCount, 4);
+      expect(source.readCount, 5);
     }
   }
 
@@ -2561,24 +2626,13 @@
    * Perform analysis tasks up to 512 times and assert that it was enough.
    */
   void _analyzeAll_assertFinished([int maxIterations = 512]) {
-    bool finishedAnalyzing = false;
     for (int i = 0; i < maxIterations; i++) {
       List<ChangeNotice> notice = context.performAnalysisTask().changeNotices;
       if (notice == null) {
-        finishedAnalyzing = true;
-        bool inconsistent = context.validateCacheConsistency();
-        if (!inconsistent) {
-          return;
-        }
+        return;
       }
     }
-    if (finishedAnalyzing) {
-      fail(
-          "performAnalysisTask failed to finish analyzing all sources after $maxIterations iterations");
-    } else {
-      fail(
-          "performAnalysisTask failed to terminate after analyzing all sources");
-    }
+    fail("performAnalysisTask failed to terminate after analyzing all sources");
   }
 
   void _assertNoExceptions() {
@@ -2675,6 +2729,49 @@
     context.analysisOptions = options;
   }
 
+  void test_class_addMethod_useAsHole_inTopLevelVariable() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
+class A {
+}
+''');
+    Source b = addSource(
+        '/b.dart',
+        r'''
+import 'a.dart';
+var B = A.foo;
+''');
+    Source c = addSource(
+        '/c.dart',
+        r'''
+import 'b.dart';
+var C = B;
+''');
+    _performPendingAnalysisTasks();
+    expect(context.getErrors(b).errors, hasLength(1));
+    // Update a.dart: add A.foo.
+    //   'B' in b.dart is invalid, because 'B' references 'foo'
+    //   c.dart is invalid, because 'C' references 'B'
+    context.setContents(
+        a,
+        r'''
+class A {
+  static void foo(int p) {}
+}
+''');
+    _assertValidForChangedLibrary(a);
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+
+    _assertValidForDependentLibrary(b);
+    _assertInvalid(b, LIBRARY_ERRORS_READY);
+    _assertInvalidUnits(b, RESOLVED_UNIT4);
+
+    _assertValidForDependentLibrary(c);
+    _assertInvalid(c, LIBRARY_ERRORS_READY);
+    _assertInvalidUnits(c, RESOLVED_UNIT4);
+  }
+
   void test_class_addMethod_useClass() {
     Source a = addSource(
         '/a.dart',
@@ -2709,6 +2806,182 @@
     _assertValid(b, LIBRARY_ERRORS_READY);
   }
 
+  void test_class_constructor_named_changeName() {
+    // Update a.dart: change A.named() to A.named2().
+    //   b.dart is invalid, because it references A.named().
+    _verifyTwoLibrariesInvalidatesResolution(
+        r'''
+class A {
+  A.named();
+}
+''',
+        r'''
+class A {
+  A.named2();
+}
+''',
+        r'''
+import 'a.dart';
+main() {
+  new A.named();
+}
+''');
+  }
+
+  void test_class_constructor_named_parameters_add() {
+    // Update a.dart: add a new parameter to A.named().
+    //   b.dart is invalid, because it references A.named().
+    _verifyTwoLibrariesInvalidatesResolution(
+        r'''
+class A {
+  A.named();
+}
+''',
+        r'''
+class A {
+  A.named(int p);
+}
+''',
+        r'''
+import 'a.dart';
+main() {
+  new A.named();
+}
+''');
+  }
+
+  void test_class_constructor_named_parameters_remove() {
+    // Update a.dart: remove a new parameter of A.named().
+    //   b.dart is invalid, because it references A.named().
+    _verifyTwoLibrariesInvalidatesResolution(
+        r'''
+class A {
+  A.named(int p);
+}
+''',
+        r'''
+class A {
+  A.named();
+}
+''',
+        r'''
+import 'a.dart';
+main() {
+  new A.named();
+}
+''');
+  }
+
+  void test_class_constructor_named_remove_notUsed() {
+    // Update a.dart: remove A.foo().
+    //   b.dart is valid, because it does not reference A.foo().
+    _verifyTwoLibrariesAllValid(
+        r'''
+class A {
+  A.foo();
+  A.bar();
+}
+''',
+        r'''
+class A {
+  A.bar();
+}
+''',
+        r'''
+import 'a.dart';
+main() {
+  new A.bar();
+}
+''');
+  }
+
+  void test_class_constructor_named_remove_used() {
+    // Update a.dart: remove A.named().
+    //   b.dart is invalid, because it references A.named().
+    _verifyTwoLibrariesInvalidatesResolution(
+        r'''
+class A {
+  A.named();
+}
+''',
+        r'''
+class A {
+}
+''',
+        r'''
+import 'a.dart';
+main() {
+  new A.named();
+}
+''');
+  }
+
+  void test_class_constructor_unnamed_parameters_remove() {
+    // Update a.dart: change A().
+    //   b.dart is invalid, because it references A().
+    _verifyTwoLibrariesInvalidatesResolution(
+        r'''
+class A {
+  A(int a, int b);
+}
+''',
+        r'''
+class A {
+  A(int a);
+}
+''',
+        r'''
+import 'a.dart';
+main() {
+  new A(1, 2);
+}
+''');
+  }
+
+  void test_class_constructor_unnamed_remove_notUsed() {
+    // Update a.dart: remove A().
+    //   b.dart is invalid, because it instantiates A.
+    _verifyTwoLibrariesInvalidatesResolution(
+        r'''
+class A {
+  A();
+  A.named();
+}
+''',
+        r'''
+class A {
+  A.named();
+}
+''',
+        r'''
+import 'a.dart';
+main() {
+  new A.named();
+}
+''');
+  }
+
+  void test_class_constructor_unnamed_remove_used() {
+    // Update a.dart: remove A.named().
+    //   b.dart is invalid, because it references A.named().
+    _verifyTwoLibrariesInvalidatesResolution(
+        r'''
+class A {
+  A();
+}
+''',
+        r'''
+class A {
+}
+''',
+        r'''
+import 'a.dart';
+main() {
+  new A();
+}
+''');
+  }
+
   void test_class_method_change_notUsed() {
     Source a = addSource(
         '/a.dart',
@@ -2816,6 +3089,88 @@
     _assertInvalid(b, LIBRARY_ERRORS_READY);
   }
 
+  void test_class_method_remove_notUsed_instantiated() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
+abstract class I {
+ void foo();
+}
+class A implements I {
+ void foo() {}
+}
+''');
+    Source b = addSource(
+        '/b.dart',
+        r'''
+import 'a.dart';
+main() {
+  new A();
+}
+''');
+    _performPendingAnalysisTasks();
+    // Update a.dart: remove 'A.foo'.
+    //   b.dart is valid because it does not reference 'foo'.
+    //     The class 'A' has a warning, but it is still not abstract.
+    context.setContents(
+        a,
+        r'''
+abstract class I {
+ void fo();
+}
+class A implements I {
+}
+''');
+    _assertValidForChangedLibrary(a);
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+
+    _assertValidForDependentLibrary(b);
+    _assertValidAllLibraryUnitResults(b);
+    _assertValidAllResolution(b);
+    _assertValidAllErrors(b);
+  }
+
+  void test_class_method_remove_subclass() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
+abstract class I {
+ void foo();
+}
+class A implements I {
+ void foo() {}
+}
+''');
+    Source b = addSource(
+        '/b.dart',
+        r'''
+import 'a.dart';
+class B extends A {}
+''');
+    _performPendingAnalysisTasks();
+    // Update a.dart: remove A.bar, add A.bar2.
+    //   b.dart
+    //     Resolution is valid because 'foo' is not referenced.
+    //     HINTS are invalid because 'B' might have invalid @override.
+    //     VERIFY_ERRORS are invalid because 'B' might not implement something.
+    //     Other errors are also invalid.
+    context.setContents(
+        a,
+        r'''
+abstract class I {
+ void foo();
+}
+class A implements I {
+}
+''');
+    _assertValidForChangedLibrary(a);
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+
+    _assertValidForDependentLibrary(b);
+    _assertValidAllResolution(b);
+    _assertInvalidHintsVerifyErrors(b);
+  }
+
   void test_class_private_member() {
     Source a = addSource(
         '/a.dart',
@@ -2865,52 +3220,27 @@
     _assertValid(b, LIBRARY_ERRORS_READY);
   }
 
-  void test_class_super_makeAbstract_instantiate() {
+  void test_enum_add() {
     Source a = addSource(
         '/a.dart',
         r'''
-abstract class I {
- void m();
-}
-class A implements I {
- void m() {}
-}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-class B extends A {}
-''');
-    Source c = addSource(
-        '/c.dart',
-        r'''
-import 'b.dart';
 main() {
-  new B();
+  print(MyEnum.A);
 }
 ''');
     _performPendingAnalysisTasks();
-    // Update a.dart: remove A.bar, add A.bar2.
-    //   b.dart is valid, because it doesn't references 'bar' or 'bar2'.
+    // Insert a new enum declaration.
+    // No errors expected.
     context.setContents(
         a,
         r'''
-abstract class I {
- void m();
+main() {
+  print(MyEnum.A);
 }
-class A implements I {
- void m2() {}
-}
+enum MyEnum { A, B, C }
 ''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-
-    _assertValidForDependentLibrary(b);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-
-    _assertValidForDependentLibrary(c);
-    _assertInvalid(c, LIBRARY_ERRORS_READY);
+    _performPendingAnalysisTasks();
+    expect(context.getErrors(a).errors, isEmpty);
   }
 
   void test_private_class() {
@@ -3005,6 +3335,72 @@
     _assertInvalid(b, LIBRARY_ERRORS_READY);
   }
 
+  void test_sequence_add_annotation() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
+const myAnnotation = const Object();
+class A {}
+''');
+    _performPendingAnalysisTasks();
+    // Add a new annotation.
+    context.setContents(
+        a,
+        r'''
+const myAnnotation = const Object();
+@myAnnotation
+class A {}
+''');
+    _assertValidForChangedLibrary(a);
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    // Analysis is done successfully.
+    _performPendingAnalysisTasks();
+    _assertValid(a, LIBRARY_ERRORS_READY);
+    _assertValid(a, READY_RESOLVED_UNIT);
+  }
+
+  void test_sequence_applyChanges_changedSource() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
+class A {}
+class B {}
+''');
+    Source b = addSource(
+        '/b.dart',
+        r'''
+import 'a.dart';
+main() {
+  new A();
+  new B();
+}
+''');
+    _performPendingAnalysisTasks();
+    resourceProvider.updateFile(
+        '/a.dart',
+        r'''
+class A2 {}
+class B {}
+''');
+    // Update a.dart: remove A, add A2.
+    //   b.dart is invalid, because it references A.
+    var changeSet = new ChangeSet()..changedSource(a);
+    context.applyChanges(changeSet);
+    _assertValidForChangedLibrary(a);
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertValidForDependentLibrary(b);
+    _assertInvalid(b, LIBRARY_ERRORS_READY);
+    _assertInvalidUnits(b, RESOLVED_UNIT4);
+    // Analyze.
+    _performPendingAnalysisTasks();
+    expect(context.getErrors(a).errors, hasLength(0));
+    expect(context.getErrors(b).errors, hasLength(1));
+    _assertValid(a, READY_RESOLVED_UNIT);
+    _assertValid(b, READY_RESOLVED_UNIT);
+    _assertValidAllLibraryUnitResults(a);
+    _assertValidAllLibraryUnitResults(b);
+  }
+
   void test_sequence_class_give_take() {
     Source a = addSource(
         '/a.dart',
@@ -3060,6 +3456,252 @@
     expect(context.getErrors(b).errors, hasLength(1));
   }
 
+  void test_sequence_class_removeMethod_overridden() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
+class A {
+  void foo() {}
+}
+''');
+    Source b = addSource(
+        '/b.dart',
+        r'''
+import 'a.dart';
+class B extends A {
+  @override
+  void foo() {}
+}
+''');
+    _performPendingAnalysisTasks();
+    expect(context.getErrors(b).errors, hasLength(0));
+    // Update a.dart: remove add A.foo.
+    //   b.dart has a new hint, because B.foo does not override anything
+    context.setContents(
+        a,
+        r'''
+class A {
+}
+''');
+    _assertValidForChangedLibrary(a);
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertValidForDependentLibrary(b);
+    _assertValidAllResolution(b);
+    _assertInvalidHintsVerifyErrors(b);
+
+    _performPendingAnalysisTasks();
+    expect(context.getErrors(b).errors, hasLength(1));
+  }
+
+  void test_sequence_closureParameterTypesPropagation() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
+main() {
+  f((p) => 4.2);
+}
+f(c(int p)) {}
+''');
+    _performPendingAnalysisTasks();
+    LibrarySpecificUnit targetA = new LibrarySpecificUnit(a, a);
+    // Update and analyze.
+    String newCode = r'''
+newFunction() {}
+main() {
+  f((p) => 4.2);
+}
+f(c(int p)) {}
+''';
+    context.setContents(a, newCode);
+    _performPendingAnalysisTasks();
+    // Validate "(p) => 4.2" types.
+    CompilationUnit unit = context.getResult(targetA, RESOLVED_UNIT2);
+    SimpleIdentifier parameterName =
+        EngineTestCase.findSimpleIdentifier(unit, newCode, 'p) => 4.2);');
+    expect(parameterName.staticType, context.typeProvider.dynamicType);
+    expect(parameterName.propagatedType, context.typeProvider.intType);
+  }
+
+  void test_sequence_dependenciesWithCycles() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
+const A = 1;
+''');
+    Source b = addSource(
+        '/b.dart',
+        r'''
+import 'c.dart';
+const B = C1 + 1;
+''');
+    Source c = addSource(
+        '/c.dart',
+        r'''
+import 'a.dart';
+import 'b.dart';
+const C1 = A + 1;
+const C2 = B + 2;
+''');
+    Source d = addSource(
+        '/d.dart',
+        r'''
+import 'c.dart';
+const D = C2 + 1;
+''');
+    _performPendingAnalysisTasks();
+    // Update "A" constant.
+    // This should invalidate results in all sources.
+    context.setContents(
+        a,
+        r'''
+const A = 2;
+''');
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertInvalid(b, LIBRARY_ERRORS_READY);
+    _assertInvalid(c, LIBRARY_ERRORS_READY);
+    _assertInvalid(d, LIBRARY_ERRORS_READY);
+  }
+
+  void test_sequence_inBodyChange_addRef_deltaChange() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
+class A {
+}
+''');
+    Source b = addSource(
+        '/b.dart',
+        r'''
+import 'a.dart';
+main(A a) {
+}
+''');
+    _performPendingAnalysisTasks();
+    expect(context.getErrors(b).errors, hasLength(0));
+    // Update b.dart: in-body incremental change - start referencing 'foo'.
+    //   Should update referenced names.
+    context.setContents(
+        b,
+        r'''
+import 'a.dart';
+main(A a) {
+  a.foo;
+}
+''');
+    _performPendingAnalysisTasks();
+    expect(context.getErrors(b).errors, hasLength(1));
+    // Update a.dart: add A.foo
+    //   b.dart is invalid, because it references 'foo'.
+    context.setContents(
+        a,
+        r'''
+class A {
+  int foo;
+}
+''');
+    _assertValidForChangedLibrary(a);
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertValidForDependentLibrary(b);
+    _assertInvalid(b, LIBRARY_ERRORS_READY);
+    _assertInvalidUnits(b, RESOLVED_UNIT4);
+    // No errors after analysis.
+    _performPendingAnalysisTasks();
+    expect(context.getErrors(b).errors, hasLength(0));
+  }
+
+  void test_sequence_inBodyChange_removeRef_deltaChange() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
+class A {
+}
+''');
+    Source b = addSource(
+        '/b.dart',
+        r'''
+import 'a.dart';
+main(A a) {
+  a.foo;
+}
+''');
+    _performPendingAnalysisTasks();
+    expect(context.getErrors(b).errors, hasLength(1));
+    // Update b.dart: in-body incremental change - stop referencing 'foo'.
+    //   Should update referenced names.
+    context.setContents(
+        b,
+        r'''
+import 'a.dart';
+main(A a) {
+}
+''');
+    _performPendingAnalysisTasks();
+    expect(context.getErrors(b).errors, hasLength(0));
+    // Update a.dart: add A.foo
+    //   b.dart is still valid, because it does references 'foo' anymore.
+    context.setContents(
+        a,
+        r'''
+class A {
+  int foo;
+}
+''');
+    _assertValidForChangedLibrary(a);
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertValidForDependentLibrary(b);
+    _assertValidAllLibraryUnitResults(b);
+    _assertValid(b, LIBRARY_ERRORS_READY);
+  }
+
+  void test_sequence_middleLimited_thenFirstFull() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
+class A {}
+''');
+    Source b = addSource(
+        '/b.dart',
+        r'''
+export 'a.dart';
+''');
+    Source c = addSource(
+        '/c.dart',
+        r'''
+import 'b.dart';
+A a;
+''');
+    _performPendingAnalysisTasks();
+    // Update b.dart: limited invalidation.
+    // Results in c.dart are valid, because the change in b.dart does not
+    // affect anything in c.dart.
+    context.setContents(
+        b,
+        r'''
+export 'a.dart';
+class B {}
+''');
+    _assertValid(a, LIBRARY_ERRORS_READY);
+    _assertInvalid(b, LIBRARY_ERRORS_READY);
+    _assertValid(c, LIBRARY_ERRORS_READY);
+    _assertUnitValid(c, RESOLVED_UNIT4);
+    _assertUnitValid(c, RESOLVED_UNIT5);
+    // Update a.dart: unlimited invalidation.
+    // Results RESOLVED_UNIT4, RESOLVED_UNIT5, and RESOLVED_UNIT6 in c.dart
+    // are invalid, because after unlimited change to a.dart everything
+    // should be invalidated.
+    // This fixes the problem that c.dart was not re-resolving type names.
+    context.setContents(
+        a,
+        r'''
+import 'dart:async';
+class A {}
+''');
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertInvalid(b, LIBRARY_ERRORS_READY);
+    _assertInvalid(c, LIBRARY_ERRORS_READY);
+    _assertInvalidUnits(c, RESOLVED_UNIT4);
+  }
+
   void test_sequence_noChange_thenChange() {
     Source a = addSource(
         '/a.dart',
@@ -3138,8 +3780,8 @@
     _assertValidForChangedLibrary(a);
     _assertInvalid(a, LIBRARY_ERRORS_READY);
     _assertValidForDependentLibrary(b);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-    _assertInvalidUnits(b, RESOLVED_UNIT4);
+    _assertValidAllResolution(b);
+    _assertValidAllErrors(b);
     // The a.dart's unit and element are the same.
     {
       LibrarySpecificUnit target = new LibrarySpecificUnit(a, a);
@@ -3153,6 +3795,136 @@
     expect(context.getErrors(b).errors, hasLength(0));
   }
 
+  void test_sequence_reorder_localFunctions() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
+f1() {
+  localFunction() {
+    const C = 1;
+  }
+}
+f2() {}
+''');
+    _performPendingAnalysisTasks();
+    // Update a.dart: reorder functions.
+    // This should not fail with FrozenHashCodeException, because identifiers
+    // of local elements should be relative to the enclosing top-level elements.
+    context.setContents(
+        a,
+        r'''
+f2() {}
+f1() {
+  localFunction() {
+    const C = 1;
+  }
+}
+''');
+    _assertValidForChangedLibrary(a);
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+  }
+
+  void test_sequence_unitConstants_addRemove() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
+const A = 1;
+const B = 2;
+const C = 3;
+foo() {
+  const V1 = 10;
+}
+bar() {
+  const V2 = 20;
+}
+''');
+    _performPendingAnalysisTasks();
+    LibrarySpecificUnit unitA = new LibrarySpecificUnit(a, a);
+    List<ConstantEvaluationTarget> oldConstants =
+        context.getResult(unitA, COMPILATION_UNIT_CONSTANTS);
+    expect(oldConstants, hasLength(5));
+    ConstVariableElement oldA = _findConstVariable(oldConstants, 'A');
+    ConstVariableElement oldB = _findConstVariable(oldConstants, 'B');
+    ConstVariableElement oldC = _findConstVariable(oldConstants, 'C');
+    ConstVariableElement oldV1 = _findConstVariable(oldConstants, 'V1');
+    ConstVariableElement oldV2 = _findConstVariable(oldConstants, 'V2');
+    expect(context.analysisCache.get(oldA), isNotNull);
+    expect(context.analysisCache.get(oldB), isNotNull);
+    expect(context.analysisCache.get(oldC), isNotNull);
+    expect(context.analysisCache.get(oldV1), isNotNull);
+    // Update and validate new constants.
+    context.setContents(
+        a,
+        r'''
+const A = 1;
+const B = 2;
+const D = 4;
+foo() {
+  const V1 = 10;
+}
+baz() {
+  const V3 = 30;
+}
+''');
+    List<ConstantEvaluationTarget> newConstants =
+        context.getResult(unitA, COMPILATION_UNIT_CONSTANTS);
+    expect(newConstants, hasLength(5));
+    expect(newConstants, contains(same(oldA)));
+    expect(newConstants, contains(same(oldB)));
+    expect(newConstants, contains(same(oldV1)));
+    ConstVariableElement newD = _findConstVariable(newConstants, 'D');
+    ConstVariableElement newV3 = _findConstVariable(newConstants, 'V3');
+    // Perform analysis, compute constant values.
+    _performPendingAnalysisTasks();
+    // Validate const variable values.
+    expect(context.analysisCache.get(oldA), isNotNull);
+    expect(context.analysisCache.get(oldB), isNotNull);
+    expect(context.analysisCache.get(oldV1), isNotNull);
+    expect(context.analysisCache.get(oldC), isNull);
+    expect(context.analysisCache.get(oldV2), isNull);
+    expect(context.analysisCache.get(newD), isNotNull);
+    expect(context.analysisCache.get(newV3), isNotNull);
+    expect(oldA.evaluationResult.value.toIntValue(), 1);
+    expect(oldB.evaluationResult.value.toIntValue(), 2);
+    expect(newD.evaluationResult.value.toIntValue(), 4);
+    expect(oldV1.evaluationResult.value.toIntValue(), 10);
+    expect(newV3.evaluationResult.value.toIntValue(), 30);
+  }
+
+  void test_sequence_unitConstants_local_insertSpace() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
+main() {
+  const C = 1;
+}
+''');
+    _performPendingAnalysisTasks();
+    LibrarySpecificUnit unitA = new LibrarySpecificUnit(a, a);
+    List<ConstantEvaluationTarget> oldConstants =
+        context.getResult(unitA, COMPILATION_UNIT_CONSTANTS);
+    expect(oldConstants, hasLength(1));
+    ConstVariableElement C = _findConstVariable(oldConstants, 'C');
+    expect(context.analysisCache.get(C), isNotNull);
+    // Insert a space before the name.
+    context.setContents(
+        a,
+        r'''
+main() {
+  const  C = 1;
+}
+''');
+    List<ConstantEvaluationTarget> newConstants =
+        context.getResult(unitA, COMPILATION_UNIT_CONSTANTS);
+    expect(newConstants, hasLength(1));
+    expect(newConstants, contains(same(C)));
+    // Perform analysis, compute constant values.
+    _performPendingAnalysisTasks();
+    // Validate const variable values.
+    expect(context.analysisCache.get(C), isNotNull);
+    expect(C.evaluationResult.value.toIntValue(), 1);
+  }
+
   void test_sequence_useAnyResolvedUnit() {
     Source a = addSource(
         '/a.dart',
@@ -3408,8 +4180,8 @@
 ''');
     _performPendingAnalysisTasks();
     // Update a.dart: remove A.m, add A.m2.
-    //   b.dart is invalid, because B extends A.
-    //   c.dart is invalid, because 'main' references B.
+    //   b.dart has valid resolution, and invalid errors.
+    //   c.dart is invalid, because 'main' references 'm'.
     context.setContents(
         a,
         r'''
@@ -3421,9 +4193,8 @@
     _assertInvalid(a, LIBRARY_ERRORS_READY);
 
     _assertValidForDependentLibrary(b);
-    _assertInvalidLibraryElements(b, LIBRARY_ELEMENT4);
-    _assertInvalidUnits(b, RESOLVED_UNIT4);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
+    _assertValidAllResolution(b);
+    _assertInvalidHintsVerifyErrors(b);
 
     _assertValidForDependentLibrary(c);
     _assertInvalidLibraryElements(c, LIBRARY_ELEMENT5);
@@ -3471,12 +4242,9 @@
 ''');
     _assertInvalid(a, LIBRARY_ERRORS_READY);
 
-    // TODO(scheglov) In theory b.dart is not affected, because it does not
-    // call A.m, does not override it, etc.
     _assertValidForDependentLibrary(b);
-    _assertInvalidLibraryElements(b, LIBRARY_ELEMENT4);
-    _assertInvalidUnits(b, RESOLVED_UNIT4);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
+    _assertValidAllResolution(b);
+    _assertInvalidHintsVerifyErrors(b);
 
     _assertValidForDependentLibrary(c);
     _assertInvalidLibraryElements(c, LIBRARY_ELEMENT5);
@@ -3492,6 +4260,18 @@
   }
 
   /**
+   * Assert that [VERIFY_ERRORS] and other error results that include it,
+   * are invalid.
+   */
+  void _assertInvalidHintsVerifyErrors(Source unit) {
+    _assertUnitInvalid(unit, HINTS);
+    _assertUnitInvalid(unit, VERIFY_ERRORS);
+    _assertUnitInvalid(unit, LIBRARY_UNIT_ERRORS);
+    _assertInvalid(unit, DART_ERRORS);
+    _assertInvalid(unit, LIBRARY_ERRORS_READY);
+  }
+
+  /**
    * Assert that [LIBRARY_ELEMENT_RESULTS] for [first] and after it are invalid.
    */
   void _assertInvalidLibraryElements(
@@ -3545,6 +4325,18 @@
         reason: '$descriptor in $target');
   }
 
+  /**
+   * Assert that all error results for the given [unit] are valid.
+   */
+  void _assertValidAllErrors(Source unit) {
+    for (ListResultDescriptor<AnalysisError> result in ERROR_SOURCE_RESULTS) {
+      _assertValid(unit, result);
+    }
+    for (ListResultDescriptor<AnalysisError> result in ERROR_UNIT_RESULTS) {
+      _assertUnitValid(unit, result);
+    }
+  }
+
   void _assertValidAllLibraryUnitResults(Source source, {Source library}) {
     for (ResultDescriptor<LibraryElement> result in LIBRARY_ELEMENT_RESULTS) {
       _assertValid(source, result);
@@ -3556,6 +4348,14 @@
     }
   }
 
+  void _assertValidAllResolution(Source unit) {
+    _assertValidUnits(unit, null);
+    _assertUnitValidTaskResults(unit, ResolveUnitTypeNamesTask.DESCRIPTOR);
+    _assertUnitValidTaskResults(unit, ResolveUnitTask.DESCRIPTOR);
+    _assertValidTaskResults(unit, ResolveLibraryReferencesTask.DESCRIPTOR);
+    _assertValidTaskResults(unit, ResolveLibraryTask.DESCRIPTOR);
+  }
+
   void _assertValidForAnyLibrary(Source source) {
     // Source results.
     _assertValidTaskResults(source, ScanDartTask.DESCRIPTOR);
@@ -3589,6 +4389,25 @@
     }
   }
 
+  void _assertValidUnits(Source unit, ResultDescriptor<CompilationUnit> last,
+      {Source library}) {
+    var target = new LibrarySpecificUnit(library ?? unit, unit);
+    bool foundLast = false;
+    for (ResultDescriptor<CompilationUnit> result in RESOLVED_UNIT_RESULTS) {
+      if (!foundLast) {
+        _assertValid(target, result);
+      }
+      foundLast = foundLast || result == last;
+    }
+  }
+
+  ConstVariableElement _findConstVariable(
+      List<ConstantEvaluationTarget> constants, String name) {
+    return constants.singleWhere((c) {
+      return c is ConstVariableElement && c.name == name;
+    });
+  }
+
   void _performPendingAnalysisTasks([int maxTasks = 512]) {
     for (int i = 0; context.performAnalysisTask().hasMoreWork; i++) {
       if (i > maxTasks) {
@@ -3596,6 +4415,32 @@
       }
     }
   }
+
+  void _verifyTwoLibrariesAllValid(
+      String firstCodeA, String secondCodeA, String codeB) {
+    Source a = addSource('/a.dart', firstCodeA);
+    Source b = addSource('/b.dart', codeB);
+    _performPendingAnalysisTasks();
+    context.setContents(a, secondCodeA);
+    _assertValidForChangedLibrary(a);
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertValidForDependentLibrary(b);
+    _assertValidAllResolution(b);
+    _assertValidAllErrors(b);
+  }
+
+  void _verifyTwoLibrariesInvalidatesResolution(
+      String firstCodeA, String secondCodeA, String codeB) {
+    Source a = addSource('/a.dart', firstCodeA);
+    Source b = addSource('/b.dart', codeB);
+    _performPendingAnalysisTasks();
+    context.setContents(a, secondCodeA);
+    _assertValidForChangedLibrary(a);
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertValidForDependentLibrary(b);
+    _assertInvalid(b, LIBRARY_ERRORS_READY);
+    _assertInvalidUnits(b, RESOLVED_UNIT4);
+  }
 }
 
 class _AnalysisContextImplTest_Source_exists_true extends TestSource {
diff --git a/pkg/analyzer/test/src/context/test_all.dart b/pkg/analyzer/test/src/context/test_all.dart
index 33c2986..d0f1619 100644
--- a/pkg/analyzer/test/src/context/test_all.dart
+++ b/pkg/analyzer/test/src/context/test_all.dart
@@ -9,7 +9,6 @@
 import '../../utils.dart';
 import 'builder_test.dart' as builder_test;
 import 'cache_test.dart' as cache_test;
-import 'context_factory_test.dart' as context_factory_test;
 import 'context_test.dart' as context_test;
 
 /// Utility for manually running all tests.
@@ -18,7 +17,6 @@
   group('context tests', () {
     builder_test.main();
     cache_test.main();
-    context_factory_test.main();
     context_test.main();
   });
 }
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index 960726e..cf6d9cd 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -275,7 +275,7 @@
       analysisContext.computeErrors(source);
       expect(unit, isNotNull);
       ConstantValueComputer computer = _makeConstantValueComputer();
-      computer.add(unit, source, source);
+      computer.add(unit);
       computer.computeValues();
       NodeList<CompilationUnitMember> members = unit.declarations;
       expect(members, hasLength(3));
@@ -296,7 +296,7 @@
         analysisContext.resolveCompilationUnit(source, libraryElement);
     expect(unit, isNotNull);
     ConstantValueComputer computer = _makeConstantValueComputer();
-    computer.add(unit, source, source);
+    computer.add(unit);
     computer.computeValues();
     NodeList<CompilationUnitMember> members = unit.declarations;
     expect(members, hasLength(2));
@@ -331,8 +331,8 @@
         analysisContext.resolveCompilationUnit(partSource, libraryElement);
     expect(partUnit, isNotNull);
     ConstantValueComputer computer = _makeConstantValueComputer();
-    computer.add(libraryUnit, librarySource, librarySource);
-    computer.add(partUnit, partSource, librarySource);
+    computer.add(libraryUnit);
+    computer.add(partUnit);
     computer.computeValues();
     NodeList<CompilationUnitMember> libraryMembers = libraryUnit.declarations;
     expect(libraryMembers, hasLength(2));
@@ -353,7 +353,7 @@
         analysisContext.resolveCompilationUnit(source, libraryElement);
     expect(unit, isNotNull);
     ConstantValueComputer computer = _makeConstantValueComputer();
-    computer.add(unit, source, source);
+    computer.add(unit);
     computer.computeValues();
     NodeList<CompilationUnitMember> members = unit.declarations;
     expect(members, hasLength(1));
@@ -370,7 +370,7 @@
         analysisContext.resolveCompilationUnit(source, libraryElement);
     expect(unit, isNotNull);
     ConstantValueComputer computer = _makeConstantValueComputer();
-    computer.add(unit, source, source);
+    computer.add(unit);
     computer.computeValues();
     TopLevelVariableDeclaration declaration = unit.declarations
         .firstWhere((member) => member is TopLevelVariableDeclaration);
@@ -1200,7 +1200,7 @@
         analysisContext.resolveCompilationUnit(source, element);
     expect(unit, isNotNull);
     ConstantValueComputer computer = _makeConstantValueComputer();
-    computer.add(unit, source, source);
+    computer.add(unit);
     computer.computeValues();
     assertErrors(source, expectedErrorCodes);
   }
@@ -1380,7 +1380,6 @@
     ConstantEvaluationValidator_ForTest validator =
         new ConstantEvaluationValidator_ForTest(analysisContext2);
     validator.computer = new ConstantValueComputer(
-        analysisContext2,
         analysisContext2.typeProvider,
         analysisContext2.declaredVariables,
         validator,
diff --git a/pkg/analyzer/test/src/dart/constant/utilities_test.dart b/pkg/analyzer/test/src/dart/constant/utilities_test.dart
index f4fd958..48443b3 100644
--- a/pkg/analyzer/test/src/dart/constant/utilities_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/utilities_test.dart
@@ -183,7 +183,7 @@
   }
 
   List<ConstantEvaluationTarget> _findConstants() {
-    ConstantFinder finder = new ConstantFinder(_context, _source, _source);
+    ConstantFinder finder = new ConstantFinder();
     _node.accept(finder);
     List<ConstantEvaluationTarget> constants = finder.constantsToCompute;
     expect(constants, isNotNull);
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index a6e718d..b8a61fe 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -2782,6 +2782,31 @@
     expect(parameterTypes[0], same(typeI));
   }
 
+  void test_getMethod_parameterized_flushCached_whenVersionChanges() {
+    //
+    // class A<E> { E m(E p) {} }
+    //
+    ClassElementImpl classA = ElementFactory.classElement2("A", ["E"]);
+    DartType typeE = classA.type.typeArguments[0];
+    String methodName = "m";
+    MethodElementImpl methodM =
+        ElementFactory.methodElement(methodName, typeE, [typeE]);
+    classA.methods = <MethodElement>[methodM];
+    methodM.type = new FunctionTypeImpl(methodM);
+    //
+    // A<I>
+    //
+    InterfaceType typeI = ElementFactory.classElement2("I").type;
+    InterfaceTypeImpl typeAI = new InterfaceTypeImpl(classA);
+    typeAI.typeArguments = <DartType>[typeI];
+    // Methods list is cached.
+    MethodElement method = typeAI.methods.single;
+    expect(typeAI.methods.single, same(method));
+    // Methods list is flushed on version change.
+    classA.version++;
+    expect(typeAI.methods.single, isNot(same(method)));
+  }
+
   void test_getMethod_unimplemented() {
     //
     // class A {}
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
index 1adaae0..4321f0d 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
@@ -157,6 +157,51 @@
 
   @override
   @failingTest
+  void test_constructors_inferFromArguments() {
+    // TODO(jmesserly): does this need to be implemented in AST summaries?
+    // The test might need a change as well to not be based on local variable
+    // types, which don't seem to be available.
+    super.test_constructors_inferFromArguments();
+  }
+
+  @override
+  @failingTest
+  void test_constructors_inferFromArguments_const() {
+    super.test_constructors_inferFromArguments_const();
+  }
+
+  @override
+  @failingTest
+  void test_constructors_inferFromArguments_factory() {
+    super.test_constructors_inferFromArguments_factory();
+  }
+
+  @override
+  @failingTest
+  void test_constructors_inferFromArguments_named() {
+    super.test_constructors_inferFromArguments_named();
+  }
+
+  @override
+  @failingTest
+  void test_constructors_inferFromArguments_namedFactory() {
+    super.test_constructors_inferFromArguments_namedFactory();
+  }
+
+  @override
+  @failingTest
+  void test_constructors_inferFromArguments_redirecting() {
+    super.test_constructors_inferFromArguments_redirecting();
+  }
+
+  @override
+  @failingTest
+  void test_constructors_inferFromArguments_redirectingFactory() {
+    super.test_constructors_inferFromArguments_redirectingFactory();
+  }
+
+  @override
+  @failingTest
   void test_genericMethods_inferJSBuiltin() {
     super.test_genericMethods_inferJSBuiltin();
   }
@@ -547,6 +592,72 @@
     expect(unit.topLevelVariables[0].type.toString(), 'int');
   }
 
+  @override
+  @failingTest
+  void test_unsafeBlockClosureInference_closureCall() {
+    super.test_unsafeBlockClosureInference_closureCall();
+  }
+
+  @override
+  @failingTest
+  void test_unsafeBlockClosureInference_constructorCall_implicitTypeParam() {
+    super.test_unsafeBlockClosureInference_constructorCall_implicitTypeParam();
+  }
+
+  @override
+  @failingTest
+  void
+      test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr2() {
+    super
+        .test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr2();
+  }
+
+  @override
+  @failingTest
+  void
+      test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr2() {
+    super
+        .test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr2();
+  }
+
+  @override
+  @failingTest
+  void test_unsafeBlockClosureInference_functionCall_implicitTypeParam() {
+    super.test_unsafeBlockClosureInference_functionCall_implicitTypeParam();
+  }
+
+  @override
+  @failingTest
+  void
+      test_unsafeBlockClosureInference_functionCall_implicitTypeParam_viaExpr() {
+    super
+        .test_unsafeBlockClosureInference_functionCall_implicitTypeParam_viaExpr();
+  }
+
+  @override
+  @failingTest
+  void test_unsafeBlockClosureInference_functionCall_noTypeParam_viaExpr() {
+    super.test_unsafeBlockClosureInference_functionCall_noTypeParam_viaExpr();
+  }
+
+  @override
+  @failingTest
+  void test_unsafeBlockClosureInference_inList_untyped() {
+    super.test_unsafeBlockClosureInference_inList_untyped();
+  }
+
+  @override
+  @failingTest
+  void test_unsafeBlockClosureInference_inMap_untyped() {
+    super.test_unsafeBlockClosureInference_inMap_untyped();
+  }
+
+  @override
+  @failingTest
+  void test_unsafeBlockClosureInference_methodCall_implicitTypeParam() {
+    super.test_unsafeBlockClosureInference_methodCall_implicitTypeParam();
+  }
+
   LibraryElementImpl _checkSource(
       SummaryResynthesizer resynthesizer, Source source) {
     LibraryElementImpl resynthesized =
diff --git a/pkg/analyzer/test/src/summary/resynthesize_test.dart b/pkg/analyzer/test/src/summary/resynthesize_test.dart
index 881ad8f..b6e8b30 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_test.dart
@@ -692,18 +692,12 @@
     compareMetadata(resynthesized.metadata, original.metadata, desc);
 
     // Validate modifiers.
-    for (Modifier modifier in Modifier.persistedValues) {
+    for (Modifier modifier in Modifier.values) {
       bool got = _hasModifier(resynthesized, modifier);
       bool want = _hasModifier(original, modifier);
       expect(got, want,
           reason: 'Mismatch in $desc.$modifier: got $got, want $want');
     }
-    for (Modifier modifier in Modifier.transientValues) {
-      bool got = rImpl.hasModifier(modifier);
-      bool want = false;
-      expect(got, false,
-          reason: 'Mismatch in $desc.$modifier: got $got, want $want');
-    }
 
     // Validate members.
     if (oImpl is Member) {
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
index a3e2695..d3e94d3 100644
--- a/pkg/analyzer/test/src/summary/summary_common.dart
+++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -11,7 +11,6 @@
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/java_engine_io.dart';
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
@@ -21,16 +20,17 @@
     as public_namespace;
 import 'package:analyzer/src/summary/summarize_elements.dart'
     as summarize_elements;
+import 'package:path/path.dart' show posix;
 import 'package:unittest/unittest.dart';
 
 import '../context/mock_sdk.dart';
 
 /**
- * Convert [path] to a suitably formatted absolute path URI for the current
- * platform.
+ * Convert the given Posix style file [path] to the corresponding absolute URI.
  */
 String absUri(String path) {
-  return FileUtilities2.createFile(path).toURI().toString();
+  String absolutePath = posix.absolute(path);
+  return posix.toUri(absolutePath).toString();
 }
 
 /**
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index 25a6bef..8c081f7 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -772,11 +772,10 @@
 part of lib;
 '''
     });
-    expect(outputs, hasLength(4));
+    expect(outputs, hasLength(3));
     // simple outputs
     expect(outputs[BUILD_LIBRARY_ERRORS], isEmpty);
     expect(outputs[IS_LAUNCHABLE], isFalse);
-    expect(outputs[REFERENCED_NAMES], isNotNull);
     // LibraryElement output
     expect(libraryElement, isNotNull);
     expect(libraryElement.entryPoint, isNull);
@@ -3185,7 +3184,7 @@
     _performParseTask(r'''
 part of lib;
 class B {}''');
-    expect(outputs, hasLength(10));
+    expect(outputs, hasLength(11));
     expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(0));
     expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
     _assertHasCore(outputs[IMPORTED_LIBRARIES], 1);
@@ -3193,9 +3192,10 @@
     expect(outputs[LIBRARY_SPECIFIC_UNITS], hasLength(1));
     expect(outputs[PARSE_ERRORS], hasLength(0));
     expect(outputs[PARSED_UNIT], isNotNull);
+    expect(outputs[REFERENCED_NAMES], isNotNull);
+    expect(outputs[REFERENCED_SOURCES], hasLength(2));
     expect(outputs[SOURCE_KIND], SourceKind.PART);
     expect(outputs[UNITS], hasLength(1));
-    expect(outputs[REFERENCED_SOURCES], hasLength(2));
   }
 
   test_perform_computeSourceKind_noDirectives_hasContainingLibrary() {
@@ -3220,7 +3220,7 @@
 
   test_perform_doesNotExist() {
     _performParseTask(null);
-    expect(outputs, hasLength(10));
+    expect(outputs, hasLength(11));
     expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(0));
     expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
     _assertHasCore(outputs[IMPORTED_LIBRARIES], 1);
@@ -3228,9 +3228,10 @@
     expect(outputs[LIBRARY_SPECIFIC_UNITS], hasLength(1));
     expect(outputs[PARSE_ERRORS], hasLength(0));
     expect(outputs[PARSED_UNIT], isNotNull);
+    expect(outputs[REFERENCED_NAMES], isNotNull);
+    expect(outputs[REFERENCED_SOURCES], hasLength(2));
     expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
     expect(outputs[UNITS], hasLength(1));
-    expect(outputs[REFERENCED_SOURCES], hasLength(2));
   }
 
   test_perform_enableAsync_false() {
@@ -3240,7 +3241,7 @@
     _performParseTask(r'''
 import 'dart:async';
 class B {void foo() async {}}''');
-    expect(outputs, hasLength(10));
+    expect(outputs, hasLength(11));
     expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(1));
     expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
     _assertHasCore(outputs[IMPORTED_LIBRARIES], 2);
@@ -3248,16 +3249,17 @@
     expect(outputs[LIBRARY_SPECIFIC_UNITS], hasLength(1));
     expect(outputs[PARSE_ERRORS], hasLength(1));
     expect(outputs[PARSED_UNIT], isNotNull);
+    expect(outputs[REFERENCED_NAMES], isNotNull);
+    expect(outputs[REFERENCED_SOURCES], hasLength(3));
     expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
     expect(outputs[UNITS], hasLength(1));
-    expect(outputs[REFERENCED_SOURCES], hasLength(3));
   }
 
   test_perform_enableAsync_true() {
     _performParseTask(r'''
 import 'dart:async';
 class B {void foo() async {}}''');
-    expect(outputs, hasLength(10));
+    expect(outputs, hasLength(11));
     expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(1));
     expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
     _assertHasCore(outputs[IMPORTED_LIBRARIES], 2);
@@ -3265,9 +3267,10 @@
     expect(outputs[LIBRARY_SPECIFIC_UNITS], hasLength(1));
     expect(outputs[PARSE_ERRORS], hasLength(0));
     expect(outputs[PARSED_UNIT], isNotNull);
+    expect(outputs[REFERENCED_NAMES], isNotNull);
+    expect(outputs[REFERENCED_SOURCES], hasLength(3));
     expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
     expect(outputs[UNITS], hasLength(1));
-    expect(outputs[REFERENCED_SOURCES], hasLength(3));
   }
 
   test_perform_flushTokenStream() {
@@ -3285,7 +3288,7 @@
 export '${a}lib3.dart';
 part 'part.dart';
 class A {}''');
-    expect(outputs, hasLength(10));
+    expect(outputs, hasLength(11));
     expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(1));
     expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
     _assertHasCore(outputs[IMPORTED_LIBRARIES], 2);
@@ -3293,9 +3296,10 @@
     expect(outputs[LIBRARY_SPECIFIC_UNITS], hasLength(2));
     expect(outputs[PARSE_ERRORS], hasLength(2));
     expect(outputs[PARSED_UNIT], isNotNull);
+    expect(outputs[REFERENCED_NAMES], isNotNull);
+    expect(outputs[REFERENCED_SOURCES], hasLength(4));
     expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
     expect(outputs[UNITS], hasLength(2));
-    expect(outputs[REFERENCED_SOURCES], hasLength(4));
   }
 
   test_perform_library() {
@@ -3305,7 +3309,7 @@
 export 'lib3.dart';
 part 'part.dart';
 class A {''');
-    expect(outputs, hasLength(10));
+    expect(outputs, hasLength(11));
     expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(1));
     expect(outputs[EXPORTED_LIBRARIES], hasLength(1));
     _assertHasCore(outputs[IMPORTED_LIBRARIES], 2);
@@ -3313,9 +3317,10 @@
     expect(outputs[LIBRARY_SPECIFIC_UNITS], hasLength(2));
     expect(outputs[PARSE_ERRORS], hasLength(1));
     expect(outputs[PARSED_UNIT], isNotNull);
+    expect(outputs[REFERENCED_NAMES], isNotNull);
+    expect(outputs[REFERENCED_SOURCES], hasLength(5));
     expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
     expect(outputs[UNITS], hasLength(2));
-    expect(outputs[REFERENCED_SOURCES], hasLength(5));
   }
 
   test_perform_library_selfReferenceAsPart() {
@@ -3330,7 +3335,7 @@
     _performParseTask(r'''
 part of lib;
 class B {}''');
-    expect(outputs, hasLength(10));
+    expect(outputs, hasLength(11));
     expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(0));
     expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
     _assertHasCore(outputs[IMPORTED_LIBRARIES], 1);
@@ -3338,9 +3343,10 @@
     expect(outputs[LIBRARY_SPECIFIC_UNITS], hasLength(1));
     expect(outputs[PARSE_ERRORS], hasLength(0));
     expect(outputs[PARSED_UNIT], isNotNull);
+    expect(outputs[REFERENCED_NAMES], isNotNull);
+    expect(outputs[REFERENCED_SOURCES], hasLength(2));
     expect(outputs[SOURCE_KIND], SourceKind.PART);
     expect(outputs[UNITS], hasLength(1));
-    expect(outputs[REFERENCED_SOURCES], hasLength(2));
   }
 
   void _performParseTask(String content) {
@@ -4106,7 +4112,7 @@
 
   ReferencedNames _computeReferencedNames(String code) {
     Source source = newSource('/test.dart', code);
-    computeResult(source, REFERENCED_NAMES, matcher: isBuildLibraryElementTask);
+    computeResult(source, REFERENCED_NAMES, matcher: isParseDartTask);
     return outputs[REFERENCED_NAMES];
   }
 }
diff --git a/pkg/analyzer/test/src/task/dart_work_manager_test.dart b/pkg/analyzer/test/src/task/dart_work_manager_test.dart
index da36f87..31ee542 100644
--- a/pkg/analyzer/test/src/task/dart_work_manager_test.dart
+++ b/pkg/analyzer/test/src/task/dart_work_manager_test.dart
@@ -106,6 +106,21 @@
     expect_unknownSourceQueue([source4, source1]);
   }
 
+  /**
+   * When we perform limited invalidation, we keep [SOURCE_KIND] valid. So, we
+   * don't need to put such sources into [DartWorkManager.unknownSourceQueue],
+   * and remove from [DartWorkManager.librarySourceQueue].
+   */
+  void test_applyChange_change_hasSourceKind() {
+    entry1.setValue(SOURCE_KIND, SourceKind.LIBRARY, []);
+    manager.librarySourceQueue.addAll([source1, source2]);
+    manager.unknownSourceQueue.addAll([source3]);
+    // change source1
+    manager.applyChange([], [source1, source2], []);
+    expect_librarySourceQueue([source1]);
+    expect_unknownSourceQueue([source2, source3]);
+  }
+
   void test_applyChange_remove() {
     manager.librarySourceQueue.addAll([source1, source3]);
     manager.unknownSourceQueue.addAll([source4]);
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 8d495af..ecd98cb 100644
--- a/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
+++ b/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
@@ -6,6 +6,7 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/visitor.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -66,6 +67,7 @@
     ClassElement classElement = helper.element;
     expect(classElement.constructors, unorderedEquals([newConstructorElement]));
     // verify delta
+    expect(helper.delta.hasUnnamedConstructorChange, isTrue);
     expect(helper.delta.addedConstructors,
         unorderedEquals([newConstructorElement]));
     expect(helper.delta.removedConstructors,
@@ -99,7 +101,9 @@
       expect(constructors[0].isSynthetic, isTrue);
     }
     // verify delta
-    expect(helper.delta.addedConstructors, unorderedEquals([]));
+    expect(helper.delta.hasUnnamedConstructorChange, isTrue);
+    expect(helper.delta.addedConstructors,
+        unorderedEquals([classElement.unnamedConstructor]));
     expect(helper.delta.removedConstructors, unorderedEquals([oldElementA]));
     expect(helper.delta.addedAccessors, isEmpty);
     expect(helper.delta.removedAccessors, isEmpty);
@@ -107,6 +111,66 @@
     expect(helper.delta.removedMethods, isEmpty);
   }
 
+  test_classDelta_constructor_1to1_unnamed_addParameter() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {
+  A();
+}
+''');
+    helper.initOld(oldUnit);
+    ConstructorElement oldConstructor = helper.element.unnamedConstructor;
+    _buildNewUnit(r'''
+class A {
+  A(int p);
+}
+''');
+    helper.initNew(newUnit, unitDelta);
+    ClassElement classElement = helper.element;
+    ConstructorElement newConstructor = classElement.unnamedConstructor;
+    expect(classElement.constructors, [newConstructor]);
+    // verify delta
+    expect(helper.delta.hasUnnamedConstructorChange, isTrue);
+    expect(helper.delta.addedConstructors, unorderedEquals([newConstructor]));
+    expect(helper.delta.removedConstructors, unorderedEquals([oldConstructor]));
+    expect(helper.delta.addedAccessors, isEmpty);
+    expect(helper.delta.removedAccessors, isEmpty);
+    expect(helper.delta.addedMethods, isEmpty);
+    expect(helper.delta.removedMethods, isEmpty);
+  }
+
+  test_classDelta_constructor_1to1_unnamed_removeParameter() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {
+  final int a;
+  final int b;
+  A(this.a, this.b);
+}
+''');
+    helper.initOld(oldUnit);
+    ConstructorElement oldConstructor = helper.element.unnamedConstructor;
+    _buildNewUnit(r'''
+class A {
+  final int a;
+  final int b;
+  A(this.a);
+}
+''');
+    helper.initNew(newUnit, unitDelta);
+    ClassElement classElement = helper.element;
+    ConstructorElement newConstructor = classElement.unnamedConstructor;
+    expect(classElement.constructors, [newConstructor]);
+    // verify delta
+    expect(helper.delta.hasUnnamedConstructorChange, isTrue);
+    expect(helper.delta.addedConstructors, unorderedEquals([newConstructor]));
+    expect(helper.delta.removedConstructors, unorderedEquals([oldConstructor]));
+    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'''
@@ -161,6 +225,7 @@
 }
 ''');
     helper.initNew(newUnit, unitDelta);
+    expect(helper.delta.hasUnnamedConstructorChange, isFalse);
     // nodes
     ClassMember nodeB = helper.newMembers[0];
     expect(nodeB, same(helper.oldMembers[1]));
@@ -685,6 +750,26 @@
     expect(helper.delta.removedMethods, unorderedEquals([oldElementA]));
   }
 
+  test_classDelta_null_abstractKeyword_add() {
+    _verifyNoClassDeltaForTheLast(
+        r'''
+class A {}
+''',
+        r'''
+abstract class A {}
+''');
+  }
+
+  test_classDelta_null_abstractKeyword_remove() {
+    _verifyNoClassDeltaForTheLast(
+        r'''
+abstract class A {}
+''',
+        r'''
+class A {}
+''');
+  }
+
   test_classDelta_null_extendsClause_add() {
     _verifyNoClassDeltaForTheLast(
         r'''
@@ -1366,6 +1451,14 @@
     expect(elementB, isNotNull);
     expect(elementA.name, 'A');
     expect(elementB.name, 'B');
+    expect(elementA.fields.map((f) => f.name),
+        unorderedEquals(['index', 'values', 'A1', 'A2']));
+    expect(elementA.accessors.map((a) => a.name),
+        unorderedEquals(['index', 'values', 'A1', 'A2']));
+    expect(elementB.fields.map((f) => f.name),
+        unorderedEquals(['index', 'values', 'B1', 'B2']));
+    expect(elementB.accessors.map((a) => a.name),
+        unorderedEquals(['index', 'values', 'B1', 'B2']));
     // unit.types
     expect(unitElement.enums, unorderedEquals([elementA, elementB]));
     // verify delta
@@ -1565,6 +1658,18 @@
 ''');
   }
 
+  test_update_annotation_add() {
+    _buildOldUnit(r'''
+const myAnnotation = const Object();
+foo() {}
+''');
+    _buildNewUnit(r'''
+const myAnnotation = const Object();
+@myAnnotation
+foo() {}
+''');
+  }
+
   test_update_beforeClassWithDelta_nameOffset() {
     _buildOldUnit(r'''
 class A {}
@@ -1634,6 +1739,39 @@
 ''');
   }
 
+  test_update_commentReference_multipleCommentTokens() {
+    _buildOldUnit(r'''
+class A {
+  /// C1 [C2]
+  /// C3 [C4]
+  /// C5 [C6]
+  void m() {}
+}
+''');
+    _buildNewUnit(r'''
+class A {
+  int field;
+
+  /// C1 [C2]
+  /// C3 [C4]
+  /// C5 [C6]
+  void m() {}
+}
+''');
+  }
+
+  test_update_commentReference_new() {
+    _buildOldUnit(r'''
+/// Comment reference with new [new A].
+class A {}
+''');
+    _buildNewUnit(r'''
+class B {}
+/// Comment reference with new [new A].
+class A {}
+''');
+  }
+
   test_update_commentReference_notClosed() {
     _buildOldUnit(r'''
 /// [c)
@@ -1646,6 +1784,33 @@
 ''');
   }
 
+  test_update_element_implicitAccessors_classField() {
+    _buildOldUnit(r'''
+// 0
+class A {
+  var F = 0;
+}
+''');
+    _materializeLazyElements(unitElement);
+    _buildNewUnit(r'''
+// 012
+class A {
+  var F = 0;
+}
+''');
+  }
+
+  test_update_element_implicitAccessors_topLevelVariable() {
+    _buildOldUnit(r'''
+var A = 0;
+var B = 1;
+''');
+    _materializeLazyElements(unitElement);
+    _buildNewUnit(r'''
+var B = 1;
+''');
+  }
+
   test_update_rewrittenConstructorName() {
     _buildOldUnit(r'''
 class A {
@@ -1715,6 +1880,10 @@
     expect(unitElement, isNotNull);
   }
 
+  void _materializeLazyElements(CompilationUnitElement unitElement) {
+    unitElement.accept(new _MaterializeLazyElementsVisitor());
+  }
+
   void _verifyNoClassDeltaForTheLast(String oldCode, String newCode) {
     _buildOldUnit(oldCode);
     List<CompilationUnitMember> oldMembers = oldUnit.declarations.toList();
@@ -1733,6 +1902,8 @@
  * Compares tokens and ASTs, and built elements of declared identifiers.
  */
 class _BuiltElementsValidator extends AstComparator {
+  final Set visited = new Set.identity();
+
   @override
   bool isEqualNodes(AstNode expected, AstNode actual) {
     // Elements of nodes which are children of ClassDeclaration(s) must be
@@ -1761,6 +1932,16 @@
           actual.getAncestor((n) => n is ClassDeclaration);
       expect(element.enclosingElement, same(classNode.element));
     }
+    // ElementAnnotationImpl must use the enclosing CompilationUnitElement.
+    if (actual is Annotation) {
+      AstNode parent = actual.parent;
+      if (parent is Declaration) {
+        ElementAnnotationImpl actualElement = actual.elementAnnotation;
+        CompilationUnitElement enclosingUnitElement =
+            parent.element.getAncestor((a) => a is CompilationUnitElement);
+        expect(actualElement.compilationUnit, same(enclosingUnitElement));
+      }
+    }
     // Identifiers like 'a.b' in 'new a.b()' might be rewritten if resolver
     // sees that 'a' is actually a class name, so 'b' is a constructor name.
     //
@@ -1784,13 +1965,17 @@
         expect(actual.inDeclarationContext(), isTrue);
         Element expectedElement = expected.staticElement;
         Element actualElement = actual.staticElement;
-        _verifyElement(expectedElement, actualElement, 'staticElement');
+        _verifyElement(
+            expectedElement, actualElement, 'staticElement ($expectedElement)');
       }
     }
     return true;
   }
 
   void _verifyElement(Element expected, Element actual, String desc) {
+    if (!visited.add(expected)) {
+      return;
+    }
     if (expected == null && actual == null) {
       return;
     }
@@ -1820,6 +2005,23 @@
             '${expectedEnclosing.name}.$desc');
       }
     }
+    // Compare implicit accessors.
+    if (expected is PropertyInducingElement &&
+        actual is PropertyInducingElement &&
+        !expected.isSynthetic) {
+      _verifyElement(expected.getter, actual.getter, '$desc getter');
+      _verifyElement(expected.setter, actual.setter, '$desc setter');
+    }
+    // Compare parameters.
+    if (expected is ExecutableElement && actual is ExecutableElement) {
+      List<ParameterElement> actualParameters = actual.parameters;
+      List<ParameterElement> expectedParameters = expected.parameters;
+      expect(actualParameters, hasLength(expectedParameters.length));
+      for (int i = 0; i < expectedParameters.length; i++) {
+        _verifyElement(
+            expectedParameters[i], actualParameters[i], '$desc parameters[$i]');
+      }
+    }
   }
 
   void _verifyEqual(String name, expected, actual) {
@@ -1833,13 +2035,15 @@
   final String name;
 
   ClassElementDelta delta;
-  ClassElement element;
+  ClassElementImpl element;
+  int oldVersion;
   List<ClassMember> oldMembers;
   List<ClassMember> newMembers;
 
   _ClassDeltaHelper(this.name);
 
   void initNew(CompilationUnit newUnit, CompilationUnitElementDelta unitDelta) {
+    expect(element.version, isNot(oldVersion));
     ClassDeclaration newClass = _findClassNode(newUnit, name);
     expect(newClass, isNotNull);
     newMembers = newClass.members.toList();
@@ -1851,6 +2055,7 @@
     ClassDeclaration oldClass = _findClassNode(oldUnit, name);
     expect(oldClass, isNotNull);
     element = oldClass.element;
+    oldVersion = element.version;
     oldMembers = oldClass.members.toList();
   }
 
@@ -1858,3 +2063,11 @@
       unit.declarations.singleWhere((unitMember) =>
           unitMember is ClassDeclaration && unitMember.name.name == name);
 }
+
+class _MaterializeLazyElementsVisitor extends GeneralizingElementVisitor {
+  @override
+  visitExecutableElement(ExecutableElement element) {
+    element.parameters;
+    super.visitExecutableElement(element);
+  }
+}
diff --git a/pkg/analyzer/test/src/task/options_test.dart b/pkg/analyzer/test/src/task/options_test.dart
index f65c3fb..a0cbca8 100644
--- a/pkg/analyzer/test/src/task/options_test.dart
+++ b/pkg/analyzer/test/src/task/options_test.dart
@@ -7,6 +7,7 @@
 import 'package:analyzer/analyzer.dart';
 import 'package:analyzer/source/analysis_options_provider.dart';
 import 'package:analyzer/source/error_processor.dart';
+import 'package:analyzer/src/context/context.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/task/options.dart';
@@ -128,6 +129,18 @@
     expect(unusedLocal.severity, ErrorSeverity.ERROR);
   }
 
+  test_configure_excludes() {
+    configureContext('''
+analyzer:
+  exclude:
+    - foo/bar.dart
+    - 'test/**'
+''');
+
+    List<String> excludes = context.getConfigurationData(CONTEXT_EXCLUDES);
+    expect(excludes, unorderedEquals(['foo/bar.dart', 'test/**']));
+  }
+
   test_configure_strong_mode() {
     configureContext('''
 analyzer:
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index 0b1a115..343a2ae 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -264,7 +264,7 @@
 test() {
   int x = 0;
   x += 5;
-  /*error:STATIC_TYPE_ERROR*/x += 3.14;
+  /*error:STATIC_TYPE_ERROR*/x += /*error:INVALID_ASSIGNMENT*/3.14;
 
   double y = 0.0;
   y += 5;
@@ -690,14 +690,14 @@
 
 foo1() async => x;
 Future foo2() async => x;
-Future<int> foo3() async => /*info:DYNAMIC_CAST*/x;
+Future<int> foo3() async => x;
 Future<int> foo4() async => new Future<int>.value(/*info:DYNAMIC_CAST*/x);
 Future<int> foo5() async =>
     /*error:RETURN_OF_INVALID_TYPE*/new Future<String>.value(/*info:DYNAMIC_CAST*/x);
 
 bar1() async { return x; }
 Future bar2() async { return x; }
-Future<int> bar3() async { return /*info:DYNAMIC_CAST*/x; }
+Future<int> bar3() async { return x; }
 Future<int> bar4() async { return new Future<int>.value(/*info:DYNAMIC_CAST*/x); }
 Future<int> bar5() async {
   return /*error:RETURN_OF_INVALID_TYPE*/new Future<String>.value(/*info:DYNAMIC_CAST*/x);
@@ -713,7 +713,7 @@
   String d = /*error:INVALID_ASSIGNMENT*/await z;
 }
 
-Future<bool> get issue_264 async {
+Future<bool> get issue_ddc_264 async {
   await 42;
   if (new Random().nextBool()) {
     return true;
@@ -721,6 +721,11 @@
     return new Future<bool>.value(false);
   }
 }
+
+
+Future<String> issue_sdk_26404() async {
+  return (1 > 0) ? new Future<String>.value('hello') : "world";
+}
 ''');
   }
 
@@ -1917,6 +1922,23 @@
     check(implicitCasts: false);
   }
 
+  void test_implicitCasts_genericMethods() {
+    addFile('var x = <String>[].map((x) => "");');
+    check(implicitCasts: false);
+  }
+
+  void test_implicitCasts_numericOps() {
+    // Regression test for https://github.com/dart-lang/sdk/issues/26912
+    addFile(r'''
+void f() {
+  int x = 0;
+  int y = 0;
+  x += y;
+}
+    ''');
+    check(implicitCasts: false);
+  }
+
   void test_implicitDynamic_field() {
     addFile(r'''
 class C {
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index 0446efa..feef92f 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -62,7 +62,7 @@
     var mainUnit = checkFile(r'''
 import 'dart:async';
 import 'dart:math' show Random;
-var f = /*info:INFERRED_TYPE_CLOSURE*/() async {
+var f = /*info:INFERRED_TYPE_CLOSURE,warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/() async {
   if (new Random().nextBool()) {
     return new Future<int>.value(1);
   } else {
@@ -101,7 +101,7 @@
     var mainUnit = checkFile(r'''
 import 'dart:async';
 import 'dart:math' show Random;
-var f = /*info:INFERRED_TYPE_CLOSURE*/() async {
+var f = /*info:INFERRED_TYPE_CLOSURE,warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/() async {
   if (new Random().nextBool()) {
     return 1;
   } else {
@@ -140,7 +140,7 @@
     var mainUnit = checkFile(r'''
 import 'dart:async';
 import 'dart:math' show Random;
-var f = /*info:INFERRED_TYPE_CLOSURE*/() async {
+var f = /*info:INFERRED_TYPE_CLOSURE,warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/() async {
   if (new Random().nextBool()) {
     return new Future<int>.value(1);
   } else {
@@ -175,7 +175,7 @@
   void test_blockBodiedLambdas_asyncStar_topLevel() {
     var mainUnit = checkFile(r'''
   import 'dart:async';
-var f = /*info:INFERRED_TYPE_CLOSURE*/() async* {
+var f = /*info:INFERRED_TYPE_CLOSURE,warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/() async* {
   yield 1;
   Stream<double> s;
   yield* s;
@@ -198,7 +198,7 @@
   void test_blockBodiedLambdas_basic_topLevel() {
     checkFile(r'''
 List<int> o;
-var y = o.map(/*info:INFERRED_TYPE_CLOSURE*/(x) { return x + 1; });
+var y = o.map(/*info:INFERRED_TYPE_CLOSURE,warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/(x) { return x + 1; });
 Iterable<int> z = y;
 ''');
   }
@@ -223,7 +223,7 @@
   void test_blockBodiedLambdas_doesNotInferBottom_async_topLevel() {
     var mainUnit = checkFile(r'''
 import 'dart:async';
-var f = () async { return null; };
+var f = /*warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/() async { return null; };
 ''');
     var f = mainUnit.topLevelVariables[0];
     expect(f.type.toString(), '() → Future<dynamic>');
@@ -249,7 +249,7 @@
   void test_blockBodiedLambdas_doesNotInferBottom_asyncStar_topLevel() {
     var mainUnit = checkFile(r'''
 import 'dart:async';
-var f = () async* { yield null; };
+var f = /*warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/() async* { yield null; };
 ''');
     var f = mainUnit.topLevelVariables[0];
     expect(f.type.toString(), '() → Stream<dynamic>');
@@ -304,7 +304,7 @@
 
   void test_blockBodiedLambdas_doesNotInferBottom_syncStar_topLevel() {
     var mainUnit = checkFile(r'''
-var f = () sync* { yield null; };
+var f = /*warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/() sync* { yield null; };
 ''');
     var f = mainUnit.topLevelVariables[0];
     expect(f.type.toString(), '() → Iterable<dynamic>');
@@ -357,7 +357,7 @@
     checkFile(r'''
 import 'dart:math' show Random;
 List<num> o;
-var y = o.map(/*info:INFERRED_TYPE_CLOSURE*/(x) {
+var y = o.map(/*info:INFERRED_TYPE_CLOSURE,warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/(x) {
   if (new Random().nextBool()) {
     return x.toInt() + 1;
   } else {
@@ -388,7 +388,7 @@
   void test_blockBodiedLambdas_nestedLambdas_topLevel() {
     // Original feature request: https://github.com/dart-lang/sdk/issues/25487
     var mainUnit = checkFile(r'''
-var f = /*info:INFERRED_TYPE_CLOSURE*/() {
+var f = /*info:INFERRED_TYPE_CLOSURE,warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/() {
   return /*info:INFERRED_TYPE_CLOSURE*/(int x) { return 2.0 * x; };
 };
 ''');
@@ -440,7 +440,7 @@
 
   void test_blockBodiedLambdas_syncStar_topLevel() {
     var mainUnit = checkFile(r'''
-var f = /*info:INFERRED_TYPE_CLOSURE*/() sync* {
+var f = /*info:INFERRED_TYPE_CLOSURE,warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/() sync* {
   yield 1;
   yield* /*info:INFERRED_TYPE_LITERAL*/[3, 4.0];
 };
@@ -588,6 +588,152 @@
 ''');
   }
 
+  void test_constructors_inferFromArguments() {
+    var unit = checkFile('''
+class C<T> {
+  T t;
+  C(this.t);
+}
+
+var x = /*info:INFERRED_TYPE_ALLOCATION*/new C(42);
+
+// Don't infer if we had a context type.
+num y;
+C<int> c_int = /*info:INFERRED_TYPE_ALLOCATION*/new C(/*info:DOWN_CAST_IMPLICIT*/y);
+
+// These hints are not reported because we resolve with a null error listener.
+C<num> c_num = /*pass should be info:INFERRED_TYPE_ALLOCATION*/new C(123);
+C<num> c_num2 = (/*pass should be info:INFERRED_TYPE_ALLOCATION*/new C(456))
+    ..t = /*error:INVALID_ASSIGNMENT*/1.0;
+
+// Down't infer from explicit dynamic.
+var c_dynamic = new C<dynamic>(42);
+
+main() {
+  x.t = /*error:INVALID_ASSIGNMENT*/'hello';
+}
+''');
+    var vars = unit.topLevelVariables;
+    expect(vars[0].type.toString(), 'C<int>');
+    expect(vars.firstWhere((e) => e.name == 'c_int').type.toString(), 'C<int>');
+    expect(vars.firstWhere((e) => e.name == 'c_num').type.toString(), 'C<num>');
+    expect(vars.firstWhere((e) => e.name == 'c_dynamic').type.toString(),
+        'C<dynamic>');
+  }
+
+  void test_constructors_inferFromArguments_const() {
+    var unit = checkFile('''
+class C<T> {
+  final T t;
+  const C(this.t);
+}
+
+var x = /*info:INFERRED_TYPE_ALLOCATION*/const C(42);
+''');
+    expect(unit.topLevelVariables[0].type.toString(), 'C<int>');
+  }
+
+  void test_constructors_inferFromArguments_factory() {
+    var unit = checkFile('''
+class C<T> {
+  T t;
+
+  C._();
+
+  factory C(T t) {
+    var x = new C<T>._();
+    x.t = t;
+    return x;
+  }
+}
+
+var x = /*info:INFERRED_TYPE_ALLOCATION*/new C(42);
+
+main() {
+  x.t = /*error:INVALID_ASSIGNMENT*/'hello';
+}
+''');
+    expect(unit.topLevelVariables[0].type.toString(), 'C<int>');
+  }
+
+  void test_constructors_inferFromArguments_named() {
+    var unit = checkFile('''
+class C<T> {
+  T t;
+  C.named(List<T> t);
+}
+
+var x = /*info:INFERRED_TYPE_ALLOCATION*/new C.named(<int>[]);
+
+main() {
+  x.t = /*error:INVALID_ASSIGNMENT*/'hello';
+}
+''');
+    expect(unit.topLevelVariables[0].type.toString(), 'C<int>');
+  }
+
+  void test_constructors_inferFromArguments_namedFactory() {
+    var unit = checkFile('''
+class C<T> {
+  T t;
+  C();
+
+  factory C.named(T t) {
+    var x = new C<T>();
+    x.t = t;
+    return x;
+  }
+}
+
+var x = /*info:INFERRED_TYPE_ALLOCATION*/new C.named(42);
+
+main() {
+  x.t = /*error:INVALID_ASSIGNMENT*/'hello';
+}
+''');
+    expect(unit.topLevelVariables[0].type.toString(), 'C<int>');
+  }
+
+  void test_constructors_inferFromArguments_redirecting() {
+    var unit = checkFile('''
+class C<T> {
+  T t;
+  C(this.t);
+  C.named(List<T> t) : this(t[0]);
+}
+
+var x = /*info:INFERRED_TYPE_ALLOCATION*/new C.named(<int>[42]);
+
+main() {
+  x.t = /*error:INVALID_ASSIGNMENT*/'hello';
+}
+''');
+    expect(unit.topLevelVariables[0].type.toString(), 'C<int>');
+  }
+
+  void test_constructors_inferFromArguments_redirectingFactory() {
+    var unit = checkFile('''
+abstract class C<T> {
+  T get t;
+  void set t(T x);
+
+  factory C(T t) = CImpl<T>;
+}
+
+class CImpl<T> implements C<T> {
+  T t;
+  CImpl(this.t);
+}
+
+var x = /*info:INFERRED_TYPE_ALLOCATION*/new C(42);
+
+main() {
+  x.t = /*error:INVALID_ASSIGNMENT*/'hello';
+}
+''');
+    expect(unit.topLevelVariables[0].type.toString(), 'C<int>');
+  }
+
   void test_doNotInferOverriddenFieldsThatExplicitlySayDynamic_infer() {
     checkFile('''
 class A {
@@ -1073,8 +1219,8 @@
     A<int, String> a1 = /*info:INFERRED_TYPE_ALLOCATION*/new D.named(
         /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/3);
   }
-  { // Currently we only allow variable constraints.  Test that we reject.
-    A<C<int>, String> a0 = /*error:STATIC_TYPE_ERROR*/new E("hello");
+  {
+    A<C<int>, String> a0 = /*info:INFERRED_TYPE_ALLOCATION*/new E("hello");
   }
   { // Check named and optional arguments
     A<int, String> a0 = /*info:INFERRED_TYPE_ALLOCATION*/new F(3, "hello",
@@ -3711,6 +3857,300 @@
     // No type should be inferred for a because there is a circular reference
     // between a and c.
   }
+
+  void test_unsafeBlockClosureInference_closureCall() {
+    // Note: this is a DYNAMIC_INVOKE due to dartbug.com/26962.
+    var mainUnit = checkFile('''
+var v = /*info:DYNAMIC_INVOKE*/((x) => 1.0)(
+  /*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'double');
+  }
+
+  void test_unsafeBlockClosureInference_constructorCall_explicitDynamicParam() {
+    var mainUnit = checkFile('''
+class C<T> {
+  C(T x());
+}
+var v = new C<dynamic>(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'C<dynamic>');
+  }
+
+  void test_unsafeBlockClosureInference_constructorCall_explicitTypeParam() {
+    var mainUnit = checkFile('''
+class C<T> {
+  C(T x());
+}
+var v = new C<int>(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'C<int>');
+  }
+
+  void test_unsafeBlockClosureInference_constructorCall_implicitTypeParam() {
+    var mainUnit = checkFile('''
+class C<T> {
+  C(T x());
+}
+var v = /*info:INFERRED_TYPE_ALLOCATION*/new C(
+  /*info:INFERRED_TYPE_CLOSURE,warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/() {
+    return 1;
+  });
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'C<int>');
+  }
+
+  void test_unsafeBlockClosureInference_constructorCall_noTypeParam() {
+    var mainUnit = checkFile('''
+class C {
+  C(x());
+}
+var v = new C(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'C');
+  }
+
+  void test_unsafeBlockClosureInference_functionCall_explicitDynamicParam() {
+    var mainUnit = checkFile('''
+dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
+var v = f/*<dynamic>*/(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'List<dynamic>');
+  }
+
+  @failingTest
+  void
+      test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1() {
+    // Note: (f/*<dynamic>*/) is nort properly resulting in an instantiated
+    // function type due to dartbug.com/25824.
+    var mainUnit = checkFile('''
+dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
+var v = (f/*<dynamic>*/)(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'List<dynamic>');
+  }
+
+  void
+      test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr2() {
+    var mainUnit = checkFile('''
+dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
+var v = (f)/*<dynamic>*/(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'List<dynamic>');
+  }
+
+  void test_unsafeBlockClosureInference_functionCall_explicitTypeParam() {
+    var mainUnit = checkFile('''
+dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
+var v = f/*<int>*/(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'List<int>');
+  }
+
+  @failingTest
+  void
+      test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1() {
+    // TODO(paulberry): for some reason (f/*<int>) is nort properly resulting
+    // in an instantiated function type.
+    var mainUnit = checkFile('''
+dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
+var v = (f/*<int>*/)(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'List<int>');
+  }
+
+  void
+      test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr2() {
+    var mainUnit = checkFile('''
+dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
+var v = (f)/*<int>*/(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'List<int>');
+  }
+
+  void test_unsafeBlockClosureInference_functionCall_implicitTypeParam() {
+    var mainUnit = checkFile('''
+dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
+var v = f(
+  /*info:INFERRED_TYPE_CLOSURE,warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/() {
+    return 1;
+  });
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'List<int>');
+  }
+
+  void
+      test_unsafeBlockClosureInference_functionCall_implicitTypeParam_viaExpr() {
+    var mainUnit = checkFile('''
+dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
+var v = (f)(
+  /*info:INFERRED_TYPE_CLOSURE,warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/() {
+    return 1;
+  });
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'List<int>');
+  }
+
+  void test_unsafeBlockClosureInference_functionCall_noTypeParam() {
+    var mainUnit = checkFile('''
+double f(x) => 1.0;
+var v = f(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'double');
+  }
+
+  void test_unsafeBlockClosureInference_functionCall_noTypeParam_viaExpr() {
+    // TODO(paulberry): why is the call to f() considered a DYNAMIC_INVOKE?
+    var mainUnit = checkFile('''
+double f(x) => 1.0;
+var v = /*info:DYNAMIC_INVOKE*/(f)(
+  /*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'double');
+  }
+
+  void test_unsafeBlockClosureInference_inList_dynamic() {
+    var mainUnit = checkFile('''
+var v = <dynamic>[/*info:INFERRED_TYPE_CLOSURE*/() { return 1; }];
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'List<dynamic>');
+  }
+
+  void test_unsafeBlockClosureInference_inList_typed() {
+    var mainUnit = checkFile('''
+typedef int F();
+var v = <F>[/*info:INFERRED_TYPE_CLOSURE*/() { return 1; }];
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'List<() → int>');
+  }
+
+  void test_unsafeBlockClosureInference_inList_untyped() {
+    var mainUnit = checkFile('''
+var v = /*info:INFERRED_TYPE_LITERAL*/[
+  /*info:INFERRED_TYPE_CLOSURE,warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/() {
+    return 1;
+  }];
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'List<() → int>');
+  }
+
+  void test_unsafeBlockClosureInference_inMap_dynamic() {
+    var mainUnit = checkFile('''
+var v = <int, dynamic>{1: /*info:INFERRED_TYPE_CLOSURE*/() { return 1; }};
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'Map<int, dynamic>');
+  }
+
+  void test_unsafeBlockClosureInference_inMap_typed() {
+    var mainUnit = checkFile('''
+typedef int F();
+var v = <int, F>{1: /*info:INFERRED_TYPE_CLOSURE*/() { return 1; }};
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'Map<int, () → int>');
+  }
+
+  void test_unsafeBlockClosureInference_inMap_untyped() {
+    var mainUnit = checkFile('''
+var v = /*info:INFERRED_TYPE_LITERAL*/{
+  1: /*info:INFERRED_TYPE_CLOSURE,warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/() {
+    return 1;
+  }};
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'Map<int, () → int>');
+  }
+
+  void test_unsafeBlockClosureInference_methodCall_explicitDynamicParam() {
+    var mainUnit = checkFile('''
+class C {
+  dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
+}
+var v = new C().f/*<dynamic>*/(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'List<dynamic>');
+  }
+
+  void test_unsafeBlockClosureInference_methodCall_explicitTypeParam() {
+    var mainUnit = checkFile('''
+class C {
+  dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
+}
+var v = new C().f/*<int>*/(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'List<int>');
+  }
+
+  void test_unsafeBlockClosureInference_methodCall_implicitTypeParam() {
+    var mainUnit = checkFile('''
+class C {
+  dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
+}
+var v = new C().f(
+  /*info:INFERRED_TYPE_CLOSURE,warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/() {
+    return 1;
+  });
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'List<int>');
+  }
+
+  void test_unsafeBlockClosureInference_methodCall_noTypeParam() {
+    var mainUnit = checkFile('''
+class C {
+  double f(x) => 1.0;
+}
+var v = new C().f(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.name, 'v');
+    expect(v.type.toString(), 'double');
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/tool/task_dependency_graph/tasks.dot b/pkg/analyzer/tool/task_dependency_graph/tasks.dot
index 11040b1..feb61eb 100644
--- a/pkg/analyzer/tool/task_dependency_graph/tasks.dot
+++ b/pkg/analyzer/tool/task_dependency_graph/tasks.dot
@@ -25,7 +25,6 @@
   BuildLibraryElementTask -> BUILD_LIBRARY_ERRORS
   BuildLibraryElementTask -> IS_LAUNCHABLE
   BuildLibraryElementTask -> LIBRARY_ELEMENT1
-  BuildLibraryElementTask -> REFERENCED_NAMES
   BuildPublicNamespaceTask -> LIBRARY_ELEMENT3
   BuildSourceExportClosureTask -> EXPORT_SOURCE_CLOSURE
   BuildTypeProviderTask -> TYPE_PROVIDER
@@ -91,6 +90,7 @@
   EXPORTED_LIBRARIES -> ResolveTopLevelLibraryTypeBoundsTask
   EXPORTED_LIBRARIES [shape=box]
   EXPORT_SOURCE_CLOSURE -> BuildExportNamespaceTask
+  EXPORT_SOURCE_CLOSURE -> ResolveTopLevelUnitTypeBoundsTask
   EXPORT_SOURCE_CLOSURE [shape=box]
   EvaluateUnitConstantsTask -> CREATED_RESOLVED_UNIT13
   EvaluateUnitConstantsTask -> RESOLVED_UNIT13
@@ -211,6 +211,7 @@
   ParseDartTask -> LIBRARY_SPECIFIC_UNITS
   ParseDartTask -> PARSED_UNIT
   ParseDartTask -> PARSE_ERRORS
+  ParseDartTask -> REFERENCED_NAMES
   ParseDartTask -> REFERENCED_SOURCES
   ParseDartTask -> SOURCE_KIND
   ParseDartTask -> UNITS
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 44cc1d1..46316b7 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -523,7 +523,7 @@
   _PackageInfo _findPackages(CommandLineOptions options) {
     if (packageResolverProvider != null) {
       // The resolver provider will do all the work later.
-      return null;
+      return new _PackageInfo(null, null);
     }
 
     Packages packages;
@@ -648,6 +648,8 @@
     contextOptions.generateSdkErrors = options.showSdkWarnings;
     contextOptions.lint = options.lints;
     contextOptions.strongMode = options.strongMode;
+    contextOptions.implicitCasts = options.implicitCasts;
+    contextOptions.implicitDynamic = options.implicitDynamic;
     return contextOptions;
   }
 
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index 3706464..030f1bf 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -150,6 +150,12 @@
   /// Whether to use strong static checking.
   final bool strongMode;
 
+  /// Whether implicit casts are enabled (in strong mode)
+  final bool implicitCasts;
+
+  /// Whether implicit dynamic is enabled (mainly for strong mode users)
+  final bool implicitDynamic;
+
   /// Whether to treat lints as fatal
   final bool lintsAreFatal;
 
@@ -197,6 +203,8 @@
         sourceFiles = args.rest,
         warningsAreFatal = args['fatal-warnings'],
         strongMode = args['strong'],
+        implicitCasts = !args['no-implicit-casts'],
+        implicitDynamic = !args['no-implicit-dynamic'],
         lintsAreFatal = args['fatal-lints'];
 
   /// Parse [args] into [CommandLineOptions] describing the specified
@@ -478,7 +486,13 @@
           negatable: false,
           hide: true)
       ..addFlag('strong',
-          help: 'Enable strong static checks (https://goo.gl/DqcBsw)');
+          help: 'Enable strong static checks (https://goo.gl/DqcBsw)')
+      ..addFlag('no-implicit-casts',
+          negatable: false,
+          help: 'Disable implicit casts in strong mode (https://goo.gl/cTLz40)')
+      ..addFlag('no-implicit-dynamic',
+          negatable: false,
+          help: 'Disable implicit dynamic (https://goo.gl/m0UgXD)');
 
     try {
       // TODO(scheglov) https://code.google.com/p/dart/issues/detail?id=11061
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
index b0f01b8..0cffc40 100644
--- a/pkg/compiler/lib/src/closure.dart
+++ b/pkg/compiler/lib/src/closure.dart
@@ -255,6 +255,9 @@
   final String name;
   final ExecutableElement executableContext;
 
+  final int hashCode = _nextHashCode = (_nextHashCode + 10007).toUnsigned(30);
+  static int _nextHashCode = 0;
+
   BoxLocal(this.name, this.executableContext);
 
   String toString() => 'BoxLocal($name)';
@@ -326,7 +329,7 @@
 /// A local variable used encode the direct (uncaptured) references to [this].
 class ThisLocal extends Local {
   final ExecutableElement executableContext;
-  final hashCode = ++ElementX.elementHashCode;
+  final hashCode = ElementX.newHashCode();
 
   ThisLocal(this.executableContext);
 
@@ -1125,7 +1128,7 @@
   visitFunctionExpression(FunctionExpression node) {
     Element element = elements[node];
 
-    if (element.isParameter) {
+    if (element.isRegularParameter) {
       // TODO(ahe): This is a hack. This method should *not* call
       // visitChildren.
       return node.name.accept(this);
diff --git a/pkg/compiler/lib/src/common/backend_api.dart b/pkg/compiler/lib/src/common/backend_api.dart
index c4c9020..5582734 100644
--- a/pkg/compiler/lib/src/common/backend_api.dart
+++ b/pkg/compiler/lib/src/common/backend_api.dart
@@ -17,15 +17,8 @@
 import '../constants/values.dart' show ConstantValue;
 import '../dart_types.dart' show DartType, InterfaceType;
 import '../elements/elements.dart'
-    show
-        ClassElement,
-        Element,
-        FunctionElement,
-        LibraryElement,
-        MetadataAnnotation,
-        MethodElement;
-import '../enqueue.dart'
-    show Enqueuer, EnqueueTask, CodegenEnqueuer, ResolutionEnqueuer;
+    show ClassElement, Element, FunctionElement, LibraryElement;
+import '../enqueue.dart' show Enqueuer, EnqueueTask, ResolutionEnqueuer;
 import '../io/code_output.dart' show CodeBuffer;
 import '../io/source_information.dart' show SourceInformationStrategy;
 import '../js_backend/backend_helpers.dart' as js_backend show BackendHelpers;
@@ -36,8 +29,7 @@
     show checkNativeAnnotation, checkJsInteropAnnotation;
 import '../serialization/serialization.dart'
     show DeserializerPlugin, SerializerPlugin;
-import '../tree/tree.dart' show Node, Send;
-import '../universe/call_structure.dart' show CallStructure;
+import '../tree/tree.dart' show Node;
 import '../universe/world_impact.dart' show ImpactStrategy, WorldImpact;
 import 'codegen.dart' show CodegenWorkItem;
 import 'registry.dart' show Registry;
@@ -52,9 +44,6 @@
   /// Returns true if the backend supports reflection.
   bool get supportsReflection;
 
-  /// Returns true if the backend supports reflection.
-  bool get supportsAsyncAwait;
-
   /// The [ConstantSystem] used to interpret compile-time constants for this
   /// backend.
   ConstantSystem get constantSystem;
@@ -229,14 +218,6 @@
 
   bool isInterceptorClass(ClassElement element) => false;
 
-  /// Returns `true` if [element] is a foreign element, that is, that the
-  /// backend has specialized handling for the element.
-  bool isForeign(Element element) => false;
-
-  /// Returns `true` if [element] is a native element, that is, that the
-  /// corresponding entity already exists in the target language.
-  bool isNative(Element element) => false;
-
   /// Returns `true` if [element] is implemented via typed JavaScript interop.
   // TODO(johnniwinther): Move this to [JavaScriptBackend].
   bool isJsInterop(Element element) => false;
@@ -247,10 +228,6 @@
     return native.maybeEnableNative(compiler, library);
   }
 
-  /// Processes [element] for resolution and returns the [MethodElement] that
-  /// defines the implementation of [element].
-  MethodElement resolveExternalFunction(MethodElement element) => element;
-
   @override
   bool isTargetSpecificLibrary(LibraryElement library) {
     // TODO(johnniwinther): Remove this when patching is only done by the
@@ -375,12 +352,6 @@
   void registerAsyncMarker(
       FunctionElement element, Enqueuer enqueuer, Registry registry) {}
 
-  /// Called when resolving a call to a foreign function. If a non-null value
-  /// is returned, this is stored as native data for [node] in the resolved
-  /// AST.
-  dynamic resolveForeignCall(Send node, Element element,
-      CallStructure callStructure, ForeignResolver resolver) {}
-
   /// Returns the location of the patch-file associated with [libraryName]
   /// resolved from [plaformConfigUri].
   ///
diff --git a/pkg/compiler/lib/src/common/resolution.dart b/pkg/compiler/lib/src/common/resolution.dart
index 515aa68..d48603d 100644
--- a/pkg/compiler/lib/src/common/resolution.dart
+++ b/pkg/compiler/lib/src/common/resolution.dart
@@ -6,27 +6,35 @@
 
 import '../common.dart';
 import '../compiler.dart' show Compiler;
+import '../compile_time_constants.dart';
 import '../constants/expressions.dart' show ConstantExpression;
+import '../constants/values.dart' show ConstantValue;
 import '../core_types.dart' show CoreClasses, CoreTypes;
 import '../dart_types.dart' show DartType, InterfaceType, Types;
 import '../elements/elements.dart'
     show
         AstElement,
         ClassElement,
+        ConstructorElement,
         Element,
         ExecutableElement,
         FunctionElement,
         FunctionSignature,
         LibraryElement,
         MetadataAnnotation,
+        MethodElement,
         ResolvedAst,
         TypedefElement;
 import '../enqueue.dart' show ResolutionEnqueuer;
-import '../options.dart' show ParserOptions;
+import '../id_generator.dart';
+import '../mirrors_used.dart';
+import '../options.dart' show CompilerOptions, ParserOptions;
 import '../parser/element_listener.dart' show ScannerOptions;
 import '../parser/parser_task.dart';
 import '../patch_parser.dart';
-import '../tree/tree.dart' show TypeAnnotation;
+import '../resolution/resolution.dart';
+import '../tree/tree.dart' show Send, TypeAnnotation;
+import '../universe/call_structure.dart' show CallStructure;
 import '../universe/world_impact.dart' show WorldImpact;
 import 'backend_api.dart';
 import 'work.dart' show ItemCompilationContext, WorkItem;
@@ -55,9 +63,8 @@
   Iterable<MapLiteralUse> get mapLiterals => const <MapLiteralUse>[];
   Iterable<ListLiteralUse> get listLiterals => const <ListLiteralUse>[];
   Iterable<String> get constSymbolNames => const <String>[];
-  Iterable<ConstantExpression> get constantLiterals {
-    return const <ConstantExpression>[];
-  }
+  Iterable<ConstantExpression> get constantLiterals =>
+      const <ConstantExpression>[];
 
   Iterable<dynamic> get nativeData => const <dynamic>[];
 }
@@ -206,6 +213,32 @@
   /// Resolve target specific information for [element] and register it with
   /// [registry].
   void resolveNativeElement(Element element, NativeRegistry registry) {}
+
+  /// Processes [element] for resolution and returns the [MethodElement] that
+  /// defines the implementation of [element].
+  MethodElement resolveExternalFunction(MethodElement element) => element;
+
+  /// Called when resolving a call to a foreign function. If a non-null value
+  /// is returned, this is stored as native data for [node] in the resolved
+  /// AST.
+  dynamic resolveForeignCall(Send node, Element element,
+      CallStructure callStructure, ForeignResolver resolver) {
+    return null;
+  }
+
+  /// Returns the default superclass for the given [element] in this target.
+  ClassElement defaultSuperclass(ClassElement element);
+
+  /// Returns `true` if [element] is a native element, that is, that the
+  /// corresponding entity already exists in the target language.
+  bool isNative(Element element) => false;
+
+  /// Returns `true` if [element] is a foreign element, that is, that the
+  /// backend has specialized handling for the element.
+  bool isForeign(Element element) => false;
+
+  /// Returns `true` if this target supports async/await.
+  bool get supportsAsyncAwait => true;
 }
 
 // TODO(johnniwinther): Rename to `Resolver` or `ResolverContext`.
@@ -216,6 +249,24 @@
   CoreTypes get coreTypes;
   Types get types;
   Target get target;
+  ResolverTask get resolver;
+  ResolutionEnqueuer get enqueuer;
+  CompilerOptions get options;
+  IdGenerator get idGenerator;
+  ConstantEnvironment get constants;
+  MirrorUsageAnalyzerTask get mirrorUsageAnalyzerTask;
+
+  // TODO(het): Move all elements into common/elements.dart
+  LibraryElement get coreLibrary;
+  FunctionElement get identicalFunction;
+  ClassElement get mirrorSystemClass;
+  FunctionElement get mirrorSystemGetNameFunction;
+  ConstructorElement get mirrorsUsedConstructor;
+  ConstructorElement get symbolConstructor;
+
+  // TODO(het): This is only referenced in a test...
+  /// The constant for the [proxy] variable defined in dart:core.
+  ConstantValue get proxyConstant;
 
   /// If set to `true` resolution caches will not be cleared. Use this only for
   /// testing.
@@ -237,6 +288,14 @@
   /// Resolve [element] if it has not already been resolved.
   void ensureResolved(Element element);
 
+  /// Called whenever a class has been resolved.
+  void onClassResolved(ClassElement element);
+
+  /// Registers that [element] has a compile time error.
+  ///
+  /// The error itself is given in [message].
+  void registerCompileTimeError(Element element, DiagnosticMessage message);
+
   ResolutionWorkItem createWorkItem(
       Element element, ItemCompilationContext compilationContext);
 
@@ -274,6 +333,10 @@
   void emptyCache();
 
   void forgetElement(Element element);
+
+  /// Returns `true` if [value] is the top-level [proxy] annotation from the
+  /// core library.
+  bool isProxyConstant(ConstantValue value);
 }
 
 /// A container of commonly used dependencies for tasks that involve parsing.
diff --git a/pkg/compiler/lib/src/common/tasks.dart b/pkg/compiler/lib/src/common/tasks.dart
index f1d3426..100181c 100644
--- a/pkg/compiler/lib/src/common/tasks.dart
+++ b/pkg/compiler/lib/src/common/tasks.dart
@@ -211,6 +211,9 @@
   /// Whether measurement of tasks is enabled.
   final bool enableTaskMeasurements;
 
+  static int _hashCodeGenerator = 197;
+  final int hashCode = _hashCodeGenerator++;
+
   Measurer({this.enableTaskMeasurements: false});
 
   /// The currently running task, that is, the task whose [Stopwatch] is
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index d567bba..7f73dcc 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -166,9 +166,6 @@
 
   ClassElement typedDataClass;
 
-  /// The constant for the [proxy] variable defined in dart:core.
-  ConstantValue proxyConstant;
-
   // TODO(johnniwinther): Move this to the JavaScriptBackend.
   /// The class for patch annotation defined in dart:_js_helper.
   ClassElement patchAnnotationClass;
@@ -373,7 +370,8 @@
   ///
   /// Override this to mock the resolver for testing.
   ResolverTask createResolverTask() {
-    return new ResolverTask(this, backend.constantCompilerTask);
+    return new ResolverTask(
+        resolution, backend.constantCompilerTask, world, measurer);
   }
 
   Universe get resolverWorld => enqueuer.resolution.universe;
@@ -386,6 +384,8 @@
   bool get disableTypeInference =>
       options.disableTypeInference || compilationFailed;
 
+  // TODO(het): remove this from here. Either inline at all use sites or add it
+  // to Reporter.
   void unimplemented(Spannable spannable, String methodName) {
     reporter.internalError(spannable, "$methodName not implemented.");
   }
@@ -581,17 +581,6 @@
     }).then((_) => backend.onLibrariesLoaded(loadedLibraries));
   }
 
-  bool isProxyConstant(ConstantValue value) {
-    FieldElement field = coreLibrary.find('proxy');
-    if (field == null) return false;
-    if (!resolution.hasBeenResolved(field)) return false;
-    if (proxyConstant == null) {
-      proxyConstant = constants
-          .getConstantValue(resolver.constantCompiler.compileConstant(field));
-    }
-    return proxyConstant == value;
-  }
-
   Element findRequiredElement(LibraryElement library, String name) {
     var element = library.find(name);
     if (element == null) {
@@ -851,7 +840,7 @@
           }
         }
 
-        if (options.resolveOnly) {
+        if (options.resolveOnly && !compilationFailed) {
           reporter.log('Serializing to ${options.resolutionOutput}');
           serialization
               .serializeToSink(userOutputProvider.createEventSink('', 'data'),
@@ -1129,7 +1118,7 @@
     if (markCompilationAsFailed(message, kind)) {
       compilationFailed = true;
     }
-    registerCompiletimeError(currentElement, message);
+    registerCompileTimeError(currentElement, message);
   }
 
   /**
@@ -1272,7 +1261,7 @@
   }
 
   /// Associate [element] with a compile-time error [message].
-  void registerCompiletimeError(Element element, DiagnosticMessage message) {
+  void registerCompileTimeError(Element element, DiagnosticMessage message) {
     // The information is only needed if [generateCodeWithCompileTimeErrors].
     if (options.generateCodeWithCompileTimeErrors) {
       if (element == null) {
@@ -1553,7 +1542,7 @@
       } else {
         errorElement = currentElement;
       }
-      compiler.registerCompiletimeError(errorElement, message);
+      compiler.registerCompileTimeError(errorElement, message);
       compiler.fatalDiagnosticReported(message, infos, kind);
     }
   }
@@ -1906,6 +1895,48 @@
   Target get target => compiler.backend;
 
   @override
+  ResolverTask get resolver => compiler.resolver;
+
+  @override
+  ResolutionEnqueuer get enqueuer => compiler.enqueuer.resolution;
+
+  @override
+  CompilerOptions get options => compiler.options;
+
+  @override
+  IdGenerator get idGenerator => compiler.idGenerator;
+
+  @override
+  ConstantEnvironment get constants => compiler.constants;
+
+  @override
+  MirrorUsageAnalyzerTask get mirrorUsageAnalyzerTask =>
+      compiler.mirrorUsageAnalyzerTask;
+
+  @override
+  LibraryElement get coreLibrary => compiler.coreLibrary;
+
+  @override
+  FunctionElement get identicalFunction => compiler.identicalFunction;
+
+  @override
+  ClassElement get mirrorSystemClass => compiler.mirrorSystemClass;
+
+  @override
+  FunctionElement get mirrorSystemGetNameFunction =>
+      compiler.mirrorSystemGetNameFunction;
+
+  @override
+  ConstructorElement get mirrorsUsedConstructor =>
+      compiler.mirrorsUsedConstructor;
+
+  @override
+  ConstructorElement get symbolConstructor => compiler.symbolConstructor;
+
+  @override
+  ConstantValue proxyConstant;
+
+  @override
   void registerClass(ClassElement cls) {
     compiler.world.registerClass(cls);
   }
@@ -1944,6 +1975,14 @@
   }
 
   @override
+  void onClassResolved(ClassElement element) =>
+      compiler.onClassResolved(element);
+
+  @override
+  void registerCompileTimeError(Element element, DiagnosticMessage message) =>
+      compiler.registerCompileTimeError(element, message);
+
+  @override
   bool hasResolvedAst(ExecutableElement element) {
     assert(invariant(element, element.isDeclaration,
         message: "Element $element must be the declaration."));
@@ -2084,6 +2123,18 @@
     _worldImpactCache.remove(element);
     _resolutionImpactCache.remove(element);
   }
+
+  @override
+  bool isProxyConstant(ConstantValue value) {
+    FieldElement field = coreLibrary.find('proxy');
+    if (field == null) return false;
+    if (!hasBeenResolved(field)) return false;
+    if (proxyConstant == null) {
+      proxyConstant = constants
+          .getConstantValue(resolver.constantCompiler.compileConstant(field));
+    }
+    return proxyConstant == value;
+  }
 }
 
 class GlobalDependencyRegistry extends EagerRegistry {
diff --git a/pkg/compiler/lib/src/constants/expressions.dart b/pkg/compiler/lib/src/constants/expressions.dart
index 922ae06..9eb3fdc 100644
--- a/pkg/compiler/lib/src/constants/expressions.dart
+++ b/pkg/compiler/lib/src/constants/expressions.dart
@@ -101,12 +101,7 @@
 
   int _computeHashCode();
 
-  int get hashCode {
-    if (_hashCode == null) {
-      _hashCode = _computeHashCode();
-    }
-    return _hashCode;
-  }
+  int get hashCode => _hashCode ??= _computeHashCode();
 
   bool _equals(ConstantExpression other);
 
@@ -482,11 +477,15 @@
   @override
   ConstantValue evaluate(
       Environment environment, ConstantSystem constantSystem) {
-    return constantSystem.createMap(
-        environment.compiler,
-        type,
-        keys.map((k) => k.evaluate(environment, constantSystem)).toList(),
-        values.map((v) => v.evaluate(environment, constantSystem)).toList());
+    Map<ConstantValue, ConstantValue> valueMap =
+        <ConstantValue, ConstantValue>{};
+    for (int index = 0; index < keys.length; index++) {
+      ConstantValue key = keys[index].evaluate(environment, constantSystem);
+      ConstantValue value = values[index].evaluate(environment, constantSystem);
+      valueMap[key] = value;
+    }
+    return constantSystem.createMap(environment.compiler, type,
+        valueMap.keys.toList(), valueMap.values.toList());
   }
 
   ConstantExpression apply(NormalizedArguments arguments) {
@@ -654,7 +653,7 @@
     for (ConstantExpression expression in expressions) {
       ConstantValue value = expression.evaluate(environment, constantSystem);
       DartString valueString;
-      if (value.isNum || value.isBool) {
+      if (value.isNum || value.isBool || value.isNull) {
         PrimitiveConstantValue primitive = value;
         valueString =
             new DartString.literal(primitive.primitiveValue.toString());
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
index 28cc94a..80f149d 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
@@ -3859,7 +3859,7 @@
     if (Elements.isLocal(element)) {
       LocalElement local = element;
       if (insideInitializer &&
-          (local.isParameter || local.isInitializingFormal) &&
+          (local.isRegularParameter || local.isInitializingFormal) &&
           local.enclosingElement == currentFunction) {
         assert(local.enclosingElement.isConstructor);
         // Initializers in an initializer-list can communicate via parameters.
@@ -3871,7 +3871,7 @@
         // outlive the activation of the function).
         markAsCaptured(local);
       } else if (inTryStatement) {
-        assert(local.isParameter ||
+        assert(local.isRegularParameter ||
             local.isVariable ||
             local.isInitializingFormal);
         // Search for the position of the try block containing the variable
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index 4301a55..1b41be1 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -878,7 +878,8 @@
           }
         }
       }
-      options = options.copy(resolutionInputs: resolutionInputs);
+      options =
+          CompilerOptions.copy(options, resolutionInputs: resolutionInputs);
     }
     return oldCompileFunc(options, input, compilerDiagnostics, compilerOutput);
   }
@@ -892,15 +893,12 @@
       api.CompilerDiagnostics compilerDiagnostics,
       api.CompilerOutput compilerOutput,
       [List<_SerializedData> serializedData]) {
-    CompilerOptions options = new CompilerOptions.parse(
+    CompilerOptions options = CompilerOptions.copy(compilerOptions,
         entryPoint: entryPoint,
-        libraryRoot: compilerOptions.libraryRoot,
-        packageRoot: compilerOptions.packageRoot,
-        packageConfig: compilerOptions.packageConfig,
-        packagesDiscoveryProvider: compilerOptions.packagesDiscoveryProvider,
-        environment: compilerOptions.environment,
         resolutionOutput: serializedUri,
-        options: [Flags.resolveOnly]);
+        analyzeAll: true,
+        analyzeOnly: true,
+        resolveOnly: true);
     return compileWithSerializedData(options, compilerInput,
         compilerDiagnostics, compilerOutput, serializedData);
   }
diff --git a/pkg/compiler/lib/src/dart_backend/backend.dart b/pkg/compiler/lib/src/dart_backend/backend.dart
index 371eed6..c9d69ae 100644
--- a/pkg/compiler/lib/src/dart_backend/backend.dart
+++ b/pkg/compiler/lib/src/dart_backend/backend.dart
@@ -20,8 +20,6 @@
 
   bool get supportsReflection => true;
 
-  bool get supportsAsyncAwait => true;
-
   // TODO(zarah) Maybe change this to a command-line option.
   // Right now, it is set by the tests.
   bool useMirrorHelperLibrary = false;
diff --git a/pkg/compiler/lib/src/dart_backend/placeholder_collector.dart b/pkg/compiler/lib/src/dart_backend/placeholder_collector.dart
index e6656a7..65f2576 100644
--- a/pkg/compiler/lib/src/dart_backend/placeholder_collector.dart
+++ b/pkg/compiler/lib/src/dart_backend/placeholder_collector.dart
@@ -277,7 +277,7 @@
       }
       return false;
     }
-    if (element.isParameter &&
+    if (element.isRegularParameter &&
         !isTypedefParameter(element) &&
         isNamedOptionalParameter()) {
       currentFunctionScope.registerParameter(node);
diff --git a/pkg/compiler/lib/src/dart_types.dart b/pkg/compiler/lib/src/dart_types.dart
index fb0eac4..271d09f 100644
--- a/pkg/compiler/lib/src/dart_types.dart
+++ b/pkg/compiler/lib/src/dart_types.dart
@@ -10,7 +10,7 @@
 import 'common.dart';
 import 'core_types.dart';
 import 'elements/elements.dart';
-import 'elements/modelx.dart' show TypeDeclarationElementX, ErroneousElementX;
+import 'elements/modelx.dart' show TypeDeclarationElementX;
 import 'ordered_typeset.dart' show OrderedTypeSet;
 import 'util/util.dart' show equalElements;
 
@@ -298,6 +298,8 @@
   }
 
   String toString() => name;
+
+  int get hashCode => 6007;
 }
 
 class MalformedType extends DartType {
@@ -323,8 +325,8 @@
    */
   final List<DartType> typeArguments;
 
-  final int hashCode = (nextHash++) & 0x3fffffff;
-  static int nextHash = 43765;
+  final int hashCode = _nextHash = (_nextHash + 1).toUnsigned(30);
+  static int _nextHash = 43765;
 
   MalformedType(this.element, this.userProvidedBadType,
       [this.typeArguments = null]);
@@ -845,6 +847,10 @@
   void computeUnaliased(Resolution resolution) {
     if (_unaliased == null) {
       element.ensureResolved(resolution);
+      if (element.isMalformed) {
+        _unaliased = const DynamicType();
+        return;
+      }
       element.checkCyclicReference(resolution);
       element.alias.computeUnaliased(resolution);
       _unaliased = element.alias.unaliased.substByContext(this);
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index 0f4f8d7..b45d3012 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -978,6 +978,10 @@
 
   /// Computes a suggestive name for this import.
   String computeImportDeferName(Compiler compiler) => 'main';
+
+  ImportElement get declaration => null;
+
+  String toString() => 'main';
 }
 
 /// A node in the deferred import graph defined by a deferred import directive.
@@ -1024,4 +1028,6 @@
   }
 
   int get hashCode => declaration.hashCode * 17;
+
+  String toString() => '$declaration';
 }
diff --git a/pkg/compiler/lib/src/diagnostics/messages.dart b/pkg/compiler/lib/src/diagnostics/messages.dart
index dbcab63..11c0000 100644
--- a/pkg/compiler/lib/src/diagnostics/messages.dart
+++ b/pkg/compiler/lib/src/diagnostics/messages.dart
@@ -100,7 +100,6 @@
   BEFORE_TOP_LEVEL,
   BINARY_OPERATOR_BAD_ARITY,
   BODY_EXPECTED,
-  CALL_NOT_SUPPORTED_ON_NATIVE_CLASS,
   CANNOT_EXTEND,
   CANNOT_EXTEND_ENUM,
   CANNOT_EXTEND_MALFORMED,
@@ -186,9 +185,11 @@
   DUPLICATED_RESOURCE,
   EMPTY_CATCH_DECLARATION,
   EMPTY_ENUM_DECLARATION,
+  EMPTY_NAMED_PARAMETER_LIST,
+  EMPTY_OPTIONAL_PARAMETER_LIST,
   EMPTY_HIDE,
-  EQUAL_MAP_ENTRY_KEY,
   EMPTY_SHOW,
+  EQUAL_MAP_ENTRY_KEY,
   EXISTING_DEFINITION,
   EXISTING_LABEL,
   EXPECTED_IDENTIFIER_NOT_RESERVED_WORD,
@@ -878,6 +879,36 @@
             },
           ]),
 
+      MessageKind.EMPTY_OPTIONAL_PARAMETER_LIST: const MessageTemplate(
+          MessageKind.EMPTY_OPTIONAL_PARAMETER_LIST,
+          "Optional parameter lists cannot be empty.",
+          howToFix: "Try adding an optional parameter to the list.",
+          examples: const [
+            const {
+              'main.dart': """
+foo([]) {}
+
+main() {
+  foo();
+}"""
+            }
+          ]),
+
+      MessageKind.EMPTY_NAMED_PARAMETER_LIST: const MessageTemplate(
+          MessageKind.EMPTY_NAMED_PARAMETER_LIST,
+          "Named parameter lists cannot be empty.",
+          howToFix: "Try adding a named parameter to the list.",
+          examples: const [
+            const {
+              'main.dart': """
+foo({}) {}
+
+main() {
+  foo();
+}"""
+            }
+          ]),
+
       MessageKind.NOT_A_TYPE: const MessageTemplate(
           MessageKind.NOT_A_TYPE, "'#{node}' is not a type."),
 
@@ -3671,11 +3702,6 @@
           """
 $MIRRORS_NOT_SUPPORTED_BY_BACKEND_PADDING#{importChain}"""),
 
-      MessageKind.CALL_NOT_SUPPORTED_ON_NATIVE_CLASS: const MessageTemplate(
-          MessageKind.CALL_NOT_SUPPORTED_ON_NATIVE_CLASS,
-          "Non-supported 'call' member on a native class, or a "
-          "subclass of a native class."),
-
       MessageKind.DIRECTLY_THROWING_NSM: const MessageTemplate(
           MessageKind.DIRECTLY_THROWING_NSM,
           "This 'noSuchMethod' implementation is guaranteed to throw an "
diff --git a/pkg/compiler/lib/src/elements/common.dart b/pkg/compiler/lib/src/elements/common.dart
index 5ff8341..0eb92a6 100644
--- a/pkg/compiler/lib/src/elements/common.dart
+++ b/pkg/compiler/lib/src/elements/common.dart
@@ -67,7 +67,7 @@
   bool get isAbstractField => kind == ElementKind.ABSTRACT_FIELD;
 
   @override
-  bool get isParameter => kind == ElementKind.PARAMETER;
+  bool get isRegularParameter => kind == ElementKind.PARAMETER;
 
   @override
   bool get isInitializingFormal => kind == ElementKind.INITIALIZING_FORMAL;
diff --git a/pkg/compiler/lib/src/elements/elements.dart b/pkg/compiler/lib/src/elements/elements.dart
index 52f5f30..aac0b0d 100644
--- a/pkg/compiler/lib/src/elements/elements.dart
+++ b/pkg/compiler/lib/src/elements/elements.dart
@@ -254,18 +254,22 @@
   /// explicit getter and/or setter.
   bool get isAbstractField;
 
-  /// `true` if this element is formal parameter either from a constructor,
-  /// method, or typedef declaration or from an inlined function typed
+  /// `true` if this element is a formal parameter from a constructor,
+  /// a method, a typedef declaration, or from an inlined function typed
   /// parameter.
   ///
   /// This property is `false` if this element is an initializing formal.
   /// See [isInitializingFormal].
-  bool get isParameter;
+  bool get isRegularParameter;
 
   /// `true` if this element is an initializing formal of constructor, that
   /// is a formal of the form `this.foo`.
   bool get isInitializingFormal;
 
+  /// `true` if this element is a formal parameter, either regular or
+  /// initializing.
+  bool get isParameter => isRegularParameter || isInitializingFormal;
+
   /// `true` if this element represents a resolution error.
   bool get isError;
 
@@ -590,45 +594,45 @@
   static String operatorNameToIdentifier(String name) {
     if (name == null) {
       return name;
-    } else if (identical(name, '==')) {
+    } else if (name == '==') {
       return r'operator$eq';
-    } else if (identical(name, '~')) {
+    } else if (name == '~') {
       return r'operator$not';
-    } else if (identical(name, '[]')) {
+    } else if (name == '[]') {
       return r'operator$index';
-    } else if (identical(name, '[]=')) {
+    } else if (name == '[]=') {
       return r'operator$indexSet';
-    } else if (identical(name, '*')) {
+    } else if (name == '*') {
       return r'operator$mul';
-    } else if (identical(name, '/')) {
+    } else if (name == '/') {
       return r'operator$div';
-    } else if (identical(name, '%')) {
+    } else if (name == '%') {
       return r'operator$mod';
-    } else if (identical(name, '~/')) {
+    } else if (name == '~/') {
       return r'operator$tdiv';
-    } else if (identical(name, '+')) {
+    } else if (name == '+') {
       return r'operator$add';
-    } else if (identical(name, '<<')) {
+    } else if (name == '<<') {
       return r'operator$shl';
-    } else if (identical(name, '>>')) {
+    } else if (name == '>>') {
       return r'operator$shr';
-    } else if (identical(name, '>=')) {
+    } else if (name == '>=') {
       return r'operator$ge';
-    } else if (identical(name, '>')) {
+    } else if (name == '>') {
       return r'operator$gt';
-    } else if (identical(name, '<=')) {
+    } else if (name == '<=') {
       return r'operator$le';
-    } else if (identical(name, '<')) {
+    } else if (name == '<') {
       return r'operator$lt';
-    } else if (identical(name, '&')) {
+    } else if (name == '&') {
       return r'operator$and';
-    } else if (identical(name, '^')) {
+    } else if (name == '^') {
       return r'operator$xor';
-    } else if (identical(name, '|')) {
+    } else if (name == '|') {
       return r'operator$or';
-    } else if (identical(name, '-')) {
+    } else if (name == '-') {
       return r'operator$sub';
-    } else if (identical(name, 'unary-')) {
+    } else if (name == 'unary-') {
       return r'operator$negate';
     } else {
       return name;
@@ -936,6 +940,8 @@
 abstract class PrefixElement extends Element {
   Element lookupLocalMember(String memberName);
 
+  void forEachLocalMember(void f(Element member));
+
   /// Is true if this prefix belongs to a deferred import.
   bool get isDeferred;
 
diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
index bb331d9..265eb2e 100644
--- a/pkg/compiler/lib/src/elements/modelx.dart
+++ b/pkg/compiler/lib/src/elements/modelx.dart
@@ -39,12 +39,14 @@
 abstract class DeclarationSite {}
 
 abstract class ElementX extends Element with ElementCommon {
-  static int elementHashCode = 0;
+  static int _elementHashCode = 0;
+  static int newHashCode() =>
+      _elementHashCode = (_elementHashCode + 1).toUnsigned(30);
 
   final String name;
   final ElementKind kind;
   final Element enclosingElement;
-  final int hashCode = ++elementHashCode;
+  final int hashCode = newHashCode();
   List<MetadataAnnotation> metadataInternal;
 
   ElementX(this.name, this.kind, this.enclosingElement) {
@@ -398,8 +400,18 @@
   }
 
   @override
-  set immediateRedirectionTarget(_) {
-    throw new UnsupportedError("immediateRedirectionTarget=");
+  get _immediateRedirectionTarget {
+    throw new UnsupportedError("_immediateRedirectionTarget");
+  }
+
+  @override
+  set _immediateRedirectionTarget(_) {
+    throw new UnsupportedError("_immediateRedirectionTarget=");
+  }
+
+  @override
+  setImmediateRedirectionTarget(a, b) {
+    throw new UnsupportedError("setImmediateRedirectionTarget");
   }
 
   @override
@@ -428,8 +440,13 @@
   }
 
   @override
-  set redirectionDeferredPrefix(_) {
-    throw new UnsupportedError("redirectionDeferredPrefix=");
+  get _redirectionDeferredPrefix {
+    throw new UnsupportedError("_redirectionDeferredPrefix");
+  }
+
+  @override
+  set _redirectionDeferredPrefix(_) {
+    throw new UnsupportedError("_redirectionDeferredPrefix=");
   }
 }
 
@@ -437,7 +454,7 @@
 class WrappedMessage {
   /// The message position. If [:null:] the position of the reference to the
   /// [WarnOnUseElementX] is used.
-  final Spannable spannable;
+  final SourceSpan sourceSpan;
 
   /**
    * The message to report on resolving a wrapped element.
@@ -449,7 +466,7 @@
    */
   final Map messageArguments;
 
-  WrappedMessage(this.spannable, this.messageKind, this.messageArguments);
+  WrappedMessage(this.sourceSpan, this.messageKind, this.messageArguments);
 }
 
 class WarnOnUseElementX extends ElementX implements WarnOnUseElement {
@@ -462,21 +479,21 @@
   /// The element whose usage cause a warning.
   final Element wrappedElement;
 
-  WarnOnUseElementX(WrappedMessage this.warning, WrappedMessage this.info,
-      Element enclosingElement, Element wrappedElement)
+  WarnOnUseElementX(
+      this.warning, this.info, Element enclosingElement, Element wrappedElement)
       : this.wrappedElement = wrappedElement,
         super(wrappedElement.name, ElementKind.WARN_ON_USE, enclosingElement);
 
   Element unwrap(DiagnosticReporter reporter, Spannable usageSpannable) {
     var unwrapped = wrappedElement;
     if (warning != null) {
-      Spannable spannable = warning.spannable;
+      Spannable spannable = warning.sourceSpan;
       if (spannable == null) spannable = usageSpannable;
       DiagnosticMessage warningMessage = reporter.createMessage(
           spannable, warning.messageKind, warning.messageArguments);
       List<DiagnosticMessage> infos = <DiagnosticMessage>[];
       if (info != null) {
-        Spannable spannable = info.spannable;
+        Spannable spannable = info.sourceSpan;
         if (spannable == null) spannable = usageSpannable;
         infos.add(reporter.createMessage(
             spannable, info.messageKind, info.messageArguments));
@@ -930,8 +947,11 @@
 }
 
 class SyntheticImportElement extends ImportElementX {
-  SyntheticImportElement(CompilationUnitElement enclosingElement, Uri uri)
-      : super(enclosingElement, null, uri);
+  SyntheticImportElement(CompilationUnitElement enclosingElement, Uri uri,
+      LibraryElement libraryDependency)
+      : super(enclosingElement, null, uri) {
+    this.libraryDependency = libraryDependency;
+  }
 
   @override
   Token get position => library.position;
@@ -1247,6 +1267,8 @@
 
   Element lookupLocalMember(String memberName) => importScope[memberName];
 
+  void forEachLocalMember(f(Element member)) => importScope.forEach(f);
+
   DartType computeType(Resolution resolution) => const DynamicType();
 
   Token get position => firstPosition;
@@ -2197,8 +2219,10 @@
       String name, ElementKind kind, Modifiers modifiers, Element enclosing)
       : super(name, kind, modifiers, enclosing);
 
-  FunctionElement immediateRedirectionTarget;
-  PrefixElement redirectionDeferredPrefix;
+  ConstructorElement _immediateRedirectionTarget;
+  PrefixElement _redirectionDeferredPrefix;
+
+  ConstructorElementX get patch => super.patch;
 
   bool get isRedirectingFactory => immediateRedirectionTarget != null;
 
@@ -2211,45 +2235,93 @@
   DartType _effectiveTargetType;
   bool _isEffectiveTargetMalformed;
 
-  bool get hasEffectiveTarget => effectiveTargetInternal != null;
+  bool get hasEffectiveTarget {
+    if (isPatched) {
+      return patch.hasEffectiveTarget;
+    }
+    return effectiveTargetInternal != null;
+  }
+
+  void setImmediateRedirectionTarget(
+      ConstructorElement target, PrefixElement prefix) {
+    if (isPatched) {
+      patch.setImmediateRedirectionTarget(target, prefix);
+    } else {
+      assert(invariant(this, _immediateRedirectionTarget == null,
+          message: "Immediate redirection target has already been "
+              "set on $this."));
+      _immediateRedirectionTarget = target;
+      _redirectionDeferredPrefix = prefix;
+    }
+  }
+
+  ConstructorElement get immediateRedirectionTarget {
+    if (isPatched) {
+      return patch.immediateRedirectionTarget;
+    }
+    return _immediateRedirectionTarget;
+  }
+
+  PrefixElement get redirectionDeferredPrefix {
+    if (isPatched) {
+      return patch.redirectionDeferredPrefix;
+    }
+    return _redirectionDeferredPrefix;
+  }
 
   void setEffectiveTarget(ConstructorElement target, DartType type,
       {bool isMalformed: false}) {
-    assert(invariant(this, target != null,
-        message: 'No effective target provided for $this.'));
-    assert(invariant(this, effectiveTargetInternal == null,
-        message: 'Effective target has already been computed for $this.'));
-    effectiveTargetInternal = target;
-    _effectiveTargetType = type;
-    _isEffectiveTargetMalformed = isMalformed;
+    if (isPatched) {
+      patch.setEffectiveTarget(target, type, isMalformed: isMalformed);
+    } else {
+      assert(invariant(this, target != null,
+          message: 'No effective target provided for $this.'));
+      assert(invariant(this, effectiveTargetInternal == null,
+          message: 'Effective target has already been computed for $this.'));
+      assert(invariant(this, !target.isMalformed || isMalformed,
+          message: 'Effective target is not marked as malformed for $this: '
+              'target=$target, type=$type, isMalformed: $isMalformed'));
+      assert(invariant(this, isMalformed || type.isInterfaceType,
+          message: 'Effective target type is not an interface type for $this: '
+              'target=$target, type=$type, isMalformed: $isMalformed'));
+      effectiveTargetInternal = target;
+      _effectiveTargetType = type;
+      _isEffectiveTargetMalformed = isMalformed;
+    }
   }
 
   ConstructorElement get effectiveTarget {
-    if (Elements.isMalformed(immediateRedirectionTarget)) {
-      return immediateRedirectionTarget;
-    }
-    assert(!isRedirectingFactory || effectiveTargetInternal != null);
-    if (isRedirectingFactory) {
-      return effectiveTargetInternal;
-    }
     if (isPatched) {
-      return effectiveTargetInternal ?? this;
+      return patch.effectiveTarget;
+    }
+    if (isRedirectingFactory) {
+      assert(effectiveTargetInternal != null);
+      return effectiveTargetInternal;
     }
     return this;
   }
 
-  InterfaceType get effectiveTargetType {
+  DartType get effectiveTargetType {
+    if (isPatched) {
+      return patch.effectiveTargetType;
+    }
     assert(invariant(this, _effectiveTargetType != null,
         message: 'Effective target type has not yet been computed for $this.'));
     return _effectiveTargetType;
   }
 
-  InterfaceType computeEffectiveTargetType(InterfaceType newType) {
+  DartType computeEffectiveTargetType(InterfaceType newType) {
+    if (isPatched) {
+      return patch.computeEffectiveTargetType(newType);
+    }
     if (!isRedirectingFactory) return newType;
     return effectiveTargetType.substByContext(newType);
   }
 
   bool get isEffectiveTargetMalformed {
+    if (isPatched) {
+      return patch.isEffectiveTargetMalformed;
+    }
     if (!isRedirectingFactory) return false;
     assert(invariant(this, _isEffectiveTargetMalformed != null,
         message: 'Malformedness has not yet been computed for $this.'));
@@ -3121,6 +3193,8 @@
   bool isBreakTarget = false;
   bool isContinueTarget = false;
 
+  final int hashCode = ElementX.newHashCode();
+
   JumpTargetX(this.statement, this.nestingLevel, this.executableContext);
 
   String get name => "target";
@@ -3220,6 +3294,8 @@
 
   Token get endToken;
 
+  final int hashCode = ElementX.newHashCode();
+
   MetadataAnnotationX([this.resolutionState = STATE_NOT_STARTED]);
 
   MetadataAnnotation ensureResolved(Resolution resolution) {
diff --git a/pkg/compiler/lib/src/helpers/debug_collection.dart b/pkg/compiler/lib/src/helpers/debug_collection.dart
index c0276cf..751b8c8 100644
--- a/pkg/compiler/lib/src/helpers/debug_collection.dart
+++ b/pkg/compiler/lib/src/helpers/debug_collection.dart
@@ -131,12 +131,16 @@
   E singleWhere(bool test(E element)) => iterable.singleWhere(test);
 
   E elementAt(int index) => iterable.elementAt(index);
+
+  String toString() => iterable.toString();
 }
 
 class DebugList<E> extends DebugIterable<E> implements List<E> {
   DebugCallback addCallback;
+  DebugCallback addAllCallback;
 
-  DebugList(List<E> list, {this.addCallback}) : super(list);
+  DebugList(List<E> list, {this.addCallback, this.addAllCallback})
+      : super(list);
 
   List<E> get list => iterable;
 
@@ -159,7 +163,12 @@
     list.add(value);
   }
 
-  void addAll(Iterable<E> iterable) => list.addAll(iterable);
+  void addAll(Iterable<E> iterable) {
+    if (addAllCallback != null) {
+      addAllCallback('addAll', iterable, null);
+    }
+    list.addAll(iterable);
+  }
 
   Iterable<E> get reversed => list.reversed;
 
diff --git a/pkg/compiler/lib/src/inferrer/node_tracer.dart b/pkg/compiler/lib/src/inferrer/node_tracer.dart
index c50929d..dca18a5 100644
--- a/pkg/compiler/lib/src/inferrer/node_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/node_tracer.dart
@@ -333,7 +333,7 @@
    * [isAddedToContainer].
    */
   bool isParameterOfListAddingMethod(Element element) {
-    if (!element.isParameter) return false;
+    if (!element.isRegularParameter) return false;
     if (element.enclosingClass != compiler.backend.listImplementation) {
       return false;
     }
@@ -349,7 +349,7 @@
    * [isValueAddedToMap] and [isKeyAddedToMap].
    */
   bool isParameterOfMapAddingMethod(Element element) {
-    if (!element.isParameter) return false;
+    if (!element.isRegularParameter) return false;
     if (element.enclosingClass != compiler.backend.mapImplementation) {
       return false;
     }
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index 3b0127a..d5492f1 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -88,9 +88,9 @@
   /// change.
   bool isStable = false;
 
-  // TypeInformations are unique.
-  static int staticHashCode = 0;
-  final int hashCode = staticHashCode++;
+  // TypeInformations are unique. Store an arbitrary identity hash code.
+  static int _staticHashCode = 0;
+  final int hashCode = _staticHashCode = (_staticHashCode + 1).toUnsigned(30);
 
   bool get isConcrete => false;
 
@@ -344,7 +344,7 @@
   bool disableInferenceForClosures = true;
 
   factory ElementTypeInformation(Element element, TypeInformationSystem types) {
-    if (element.isParameter || element.isInitializingFormal) {
+    if (element.isRegularParameter || element.isInitializingFormal) {
       ParameterElement parameter = element;
       if (parameter.functionDeclaration.isInstanceMember) {
         return new ParameterTypeInformation._instanceMember(element, types);
@@ -601,7 +601,7 @@
   bool isTearOffClosureParameter = false;
 
   void tagAsTearOffClosureParameter(TypeGraphInferrerEngine inferrer) {
-    assert(element.isParameter);
+    assert(element.isRegularParameter);
     isTearOffClosureParameter = true;
     // We have to add a flow-edge for the default value (if it exists), as we
     // might not see all call-sites and thus miss the use of it.
diff --git a/pkg/compiler/lib/src/js/rewrite_async.dart b/pkg/compiler/lib/src/js/rewrite_async.dart
index 2a9d8bf..9578f3f 100644
--- a/pkg/compiler/lib/src/js/rewrite_async.dart
+++ b/pkg/compiler/lib/src/js/rewrite_async.dart
@@ -283,7 +283,7 @@
   /// Each buffer ends up as its own case part in the big state-switch.
   void beginLabel(int label) {
     assert(!labelledParts.containsKey(label));
-    currentStatementBuffer = new List<js.Statement>();
+    currentStatementBuffer = <js.Statement>[];
     labelledParts[label] = currentStatementBuffer;
     addStatement(new js.Comment(labelComments[label]));
   }
@@ -967,7 +967,7 @@
       bool oldInsideUntranslatedBreakable = insideUntranslatedBreakable;
       insideUntranslatedBreakable = true;
       addStatement(js.js.statement('do {#} while (#)',
-          [translateInBlock(node.body), visitExpression(node.condition)]));
+          [translateToStatement(node.body), visitExpression(node.condition)]));
       insideUntranslatedBreakable = oldInsideUntranslatedBreakable;
       return;
     }
@@ -1013,7 +1013,7 @@
       withExpressions([node.init, node.condition, node.update],
           (List<js.Expression> transformed) {
         addStatement(new js.For(transformed[0], transformed[1], transformed[2],
-            translateInBlock(node.body)));
+            translateToStatement(node.body)));
       });
       insideUntranslatedBreakable = oldInsideUntranslated;
       return;
@@ -1063,23 +1063,34 @@
     unsupported(node);
   }
 
-  // Only used for code where `!shouldTransform(node)`.
-  js.Block translateInBlock(js.Statement node) {
+  List<js.Statement> translateToStatementSequence(js.Statement node) {
     assert(!shouldTransform(node));
     List<js.Statement> oldBuffer = currentStatementBuffer;
-    currentStatementBuffer = new List();
+    currentStatementBuffer = <js.Statement>[];
     List<js.Statement> resultBuffer = currentStatementBuffer;
     visitStatement(node);
     currentStatementBuffer = oldBuffer;
-    return new js.Block(resultBuffer);
+    return resultBuffer;
+  }
+
+  js.Statement translateToStatement(js.Statement node) {
+    List<js.Statement> statements = translateToStatementSequence(node);
+    if (statements.length == 1)
+      return statements.single;
+    return new js.Block(statements);
+  }
+
+  js.Block translateToBlock(js.Statement node) {
+    return new js.Block(translateToStatementSequence(node));
   }
 
   @override
   void visitIf(js.If node) {
     if (!shouldTransform(node.then) && !shouldTransform(node.otherwise)) {
       withExpression(node.condition, (js.Expression condition) {
-        addStatement(new js.If(condition, translateInBlock(node.then),
-            translateInBlock(node.otherwise)));
+        js.Statement translatedThen = translateToStatement(node.then);
+        js.Statement translatedElse = translateToStatement(node.otherwise);
+        addStatement(new js.If(condition, translatedThen, translatedElse));
       }, store: false);
       return;
     }
@@ -1137,7 +1148,7 @@
   void visitLabeledStatement(js.LabeledStatement node) {
     if (!shouldTransform(node)) {
       addStatement(
-          new js.LabeledStatement(node.label, translateInBlock(node.body)));
+          new js.LabeledStatement(node.label, translateToStatement(node.body)));
       return;
     }
     // `continue label` is really continuing the nested loop.
@@ -1302,9 +1313,9 @@
         List<js.SwitchClause> cases = node.cases.map((js.SwitchClause clause) {
           if (clause is js.Case) {
             return new js.Case(
-                clause.expression, translateInBlock(clause.body));
+                clause.expression, translateToBlock(clause.body));
           } else if (clause is js.Default) {
-            return new js.Default(translateInBlock(clause.body));
+            return new js.Default(translateToBlock(clause.body));
           }
         }).toList();
         addStatement(new js.Switch(key, cases));
@@ -1426,14 +1437,14 @@
   /// See the comments of [rewriteFunction] for more explanation.
   void visitTry(js.Try node) {
     if (!shouldTransform(node)) {
-      js.Block body = translateInBlock(node.body);
+      js.Block body = translateToBlock(node.body);
       js.Catch catchPart = (node.catchPart == null)
           ? null
           : new js.Catch(node.catchPart.declaration,
-              translateInBlock(node.catchPart.body));
+                translateToBlock(node.catchPart.body));
       js.Block finallyPart = (node.finallyPart == null)
           ? null
-          : translateInBlock(node.finallyPart);
+          : translateToBlock(node.finallyPart);
       addStatement(new js.Try(body, catchPart, finallyPart));
       return;
     }
@@ -1576,7 +1587,7 @@
       bool oldInsideUntranslated = insideUntranslatedBreakable;
       insideUntranslatedBreakable = true;
       withExpression(node.condition, (js.Expression condition) {
-        addStatement(new js.While(condition, translateInBlock(node.body)));
+        addStatement(new js.While(condition, translateToStatement(node.body)));
       }, store: false);
       insideUntranslatedBreakable = oldInsideUntranslated;
       return;
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index cbae712..4bf0d1e 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -232,8 +232,6 @@
 
   bool get supportsReflection => emitter.emitter.supportsReflection;
 
-  bool get supportsAsyncAwait => true;
-
   final Annotations annotations;
 
   /// Set of classes that need to be considered for reflection although not
@@ -660,7 +658,7 @@
   }
 
   bool usedByBackend(Element element) {
-    if (element.isParameter ||
+    if (element.isRegularParameter ||
         element.isInitializingFormal ||
         element.isField) {
       if (usedByBackend(element.enclosingElement)) return true;
@@ -669,7 +667,7 @@
   }
 
   bool invokedReflectively(Element element) {
-    if (element.isParameter || element.isInitializingFormal) {
+    if (element.isRegularParameter || element.isInitializingFormal) {
       ParameterElement parameter = element;
       if (invokedReflectively(parameter.functionDeclaration)) return true;
     }
@@ -947,8 +945,6 @@
       cls.ensureResolved(resolution);
       cls.forEachMember((ClassElement classElement, Element member) {
         if (member.name == Identifiers.call) {
-          reporter.reportErrorMessage(
-              member, MessageKind.CALL_NOT_SUPPORTED_ON_NATIVE_CLASS);
           return;
         }
         if (member.isSynthesized) return;
diff --git a/pkg/compiler/lib/src/js_backend/backend_serialization.dart b/pkg/compiler/lib/src/js_backend/backend_serialization.dart
index 97da2f5..471456cb 100644
--- a/pkg/compiler/lib/src/js_backend/backend_serialization.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_serialization.dart
@@ -18,8 +18,10 @@
 
 const String _BACKEND_DATA_TAG = 'jsBackendData';
 const Key DART_TYPES_RETURNED = const Key('dartTypesReturned');
+const Key THIS_TYPES_RETURNED = const Key('thisTypesReturned');
 const Key SPECIAL_TYPES_RETURNED = const Key('specialTypesReturned');
 const Key DART_TYPES_INSTANTIATED = const Key('dartTypesInstantiated');
+const Key THIS_TYPES_INSTANTIATED = const Key('thisTypesInstantiated');
 const Key SPECIAL_TYPES_INSTANTIATED = const Key('specialTypesInstantiated');
 const Key CODE_TEMPLATE = const Key('codeTemplate');
 const Key SIDE_EFFECTS = const Key('sideEffects');
@@ -150,15 +152,43 @@
 }
 
 class NativeBehaviorSerialization {
-  /// Returns a list of the [DartType]s in [types].
+  static const int NORMAL_TYPE = 0;
+  static const int THIS_TYPE = 1;
+  static const int SPECIAL_TYPE = 2;
+
+  static int getTypeKind(var type) {
+    if (type is DartType) {
+      // TODO(johnniwinther): Remove this when annotation are no longer resolved
+      // to this-types.
+      if (type is GenericType &&
+          type.isGeneric &&
+          type == type.element.thisType) {
+        return THIS_TYPE;
+      }
+      return NORMAL_TYPE;
+    }
+    return SPECIAL_TYPE;
+  }
+
+  /// Returns a list of the non-this-type [DartType]s in [types].
   static List<DartType> filterDartTypes(List types) {
-    return types.where((type) => type is DartType).toList();
+    return types.where((type) => getTypeKind(type) == NORMAL_TYPE).toList();
+  }
+
+  // TODO(johnniwinther): Remove this when annotation are no longer resolved
+  // to this-types.
+  /// Returns a list of the classes of this-types in [types].
+  static List<Element> filterThisTypes(List types) {
+    return types
+        .where((type) => getTypeKind(type) == THIS_TYPE)
+        .map((type) => type.element)
+        .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)
+        .where((type) => getTypeKind(type) == SPECIAL_TYPE)
         .map((SpecialType type) => type.name)
         .toList();
   }
@@ -167,11 +197,15 @@
       NativeBehavior behavior, ObjectEncoder encoder) {
     encoder.setTypes(
         DART_TYPES_RETURNED, filterDartTypes(behavior.typesReturned));
+    encoder.setElements(
+        THIS_TYPES_RETURNED, filterThisTypes(behavior.typesReturned));
     encoder.setStrings(
         SPECIAL_TYPES_RETURNED, filterSpecialTypes(behavior.typesReturned));
 
     encoder.setTypes(
         DART_TYPES_INSTANTIATED, filterDartTypes(behavior.typesInstantiated));
+    encoder.setElements(
+        THIS_TYPES_INSTANTIATED, filterThisTypes(behavior.typesInstantiated));
     encoder.setStrings(SPECIAL_TYPES_INSTANTIATED,
         filterSpecialTypes(behavior.typesInstantiated));
 
@@ -193,12 +227,20 @@
     behavior.typesReturned
         .addAll(decoder.getTypes(DART_TYPES_RETURNED, isOptional: true));
     behavior.typesReturned.addAll(decoder
+        .getElements(THIS_TYPES_RETURNED, isOptional: true)
+        .map((element) => element.thisType)
+        .toList());
+    behavior.typesReturned.addAll(decoder
         .getStrings(SPECIAL_TYPES_RETURNED, isOptional: true)
         .map(SpecialType.fromName));
 
     behavior.typesInstantiated
         .addAll(decoder.getTypes(DART_TYPES_INSTANTIATED, isOptional: true));
     behavior.typesInstantiated.addAll(decoder
+        .getElements(THIS_TYPES_INSTANTIATED, isOptional: true)
+        .map((element) => element.thisType)
+        .toList());
+    behavior.typesInstantiated.addAll(decoder
         .getStrings(SPECIAL_TYPES_INSTANTIATED, isOptional: true)
         .map(SpecialType.fromName));
 
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 83f6284..74b10ab 100644
--- a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
@@ -8,11 +8,7 @@
 import '../common.dart';
 import '../constants/values.dart'
     show ConstantValue, ConstructedConstantValue, StringConstantValue;
-import '../dart_types.dart'
-    show
-        DartType,
-        DynamicType,
-        FunctionType;
+import '../dart_types.dart' show DartType, DynamicType, FunctionType;
 import '../diagnostics/messages.dart' show MessageKind;
 import '../elements/elements.dart'
     show
@@ -195,9 +191,7 @@
     // TODO(jacobr): consider using codegenWorld.isChecks to determine the
     // range of positional arguments that need to be supported by JavaScript
     // function types.
-    return new FunctionType.synthesized(
-      const DynamicType(),
-      [],
-      new List<DartType>.filled(16, const DynamicType()));
+    return new FunctionType.synthesized(const DynamicType(), [],
+        new List<DartType>.filled(16, const DynamicType()));
   }
 }
diff --git a/pkg/compiler/lib/src/js_backend/native_data.dart b/pkg/compiler/lib/src/js_backend/native_data.dart
index 67b473b..31fe7d6 100644
--- a/pkg/compiler/lib/src/js_backend/native_data.dart
+++ b/pkg/compiler/lib/src/js_backend/native_data.dart
@@ -35,6 +35,10 @@
   Map<MemberElement, NativeBehavior> nativeFieldStoreBehavior =
       <FieldElement, NativeBehavior>{};
 
+  /// Prefix used to escape JS names that are not valid Dart names
+  /// when using JSInterop.
+  static const String _jsInteropEscapePrefix = r'JS$';
+
   /// Returns `true` if [element] is explicitly marked as part of JsInterop.
   bool _isJsInterop(Element element) {
     return jsInteropNames.containsKey(element.declaration);
@@ -93,7 +97,7 @@
     if (jsInteropName != null && jsInteropName.isNotEmpty) {
       return jsInteropName;
     }
-    return element.isLibrary ? 'self' : element.name;
+    return element.isLibrary ? 'self' : getUnescapedJSInteropName(element.name);
   }
 
   /// Computes the name for [element] to use in the generated JavaScript. This
@@ -216,4 +220,12 @@
       FieldElement field, NativeBehavior behavior) {
     nativeFieldStoreBehavior[field] = behavior;
   }
+
+  /// Apply JS$ escaping scheme to convert possible escaped Dart names into
+  /// JS names.
+  String getUnescapedJSInteropName(String name) {
+    return name.startsWith(_jsInteropEscapePrefix)
+        ? name.substring(_jsInteropEscapePrefix.length)
+        : name;
+  }
 }
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 369cec0..e3f74b7 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -150,7 +150,7 @@
   @override
   void registerRtiDependency(Element element, Element dependency) {
     // We're not dealing with typedef for now.
-    if (!element.isClass || !dependency.isClass) return;
+    if (element == null || !element.isClass || !dependency.isClass) return;
     Set<ClassElement> classes =
         rtiDependencies.putIfAbsent(element, () => new Set<ClassElement>());
     classes.add(dependency);
@@ -1049,8 +1049,8 @@
 class TypeCheck {
   final ClassElement cls;
   final Substitution substitution;
-  final int hashCode = (nextHash++) & 0x3fffffff;
-  static int nextHash = 49;
+  final int hashCode = _nextHash = (_nextHash + 100003).toUnsigned(30);
+  static int _nextHash = 0;
 
   TypeCheck(this.cls, this.substitution);
 }
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
index 5bd1cb1..6301e77 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
@@ -1067,9 +1067,28 @@
           var cls = function () {};
           cls.prototype = {'p': {}};
           var object = new cls();
-          return object.__proto__ &&
-                 object.__proto__.p === cls.prototype.p;
-         })();
+          if (!(object.__proto__ && object.__proto__.p === cls.prototype.p))
+            return false;
+    
+          try {
+            // Are we running on a platform where the performance is good?
+            // (i.e. Chrome or d8).
+
+            // Chrome userAgent?
+            if (typeof navigator != "undefined" &&
+                typeof navigator.userAgent == "string" &&
+                navigator.userAgent.indexOf("Chrome/") >= 0) return true;
+
+            // d8 version() looks like "N.N.N.N", jsshell version() like "N".
+            if (typeof version == "function" &&
+                version.length == 0) {
+              var v = version();
+              if (/^\d+\.\d+\.\d+\.\d+$/.test(v)) return true;
+            }
+          } catch(_) {}
+          
+          return false;
+        })();
       ''');
     }
 
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 1f81f6d..efec052 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -345,6 +345,8 @@
       for (Element e in elements) {
         if (e is ClassElement && backend.isJsInterop(e)) {
           e.declaration.forEachMember((_, Element member) {
+            var jsName =
+                backend.nativeData.getUnescapedJSInteropName(member.name);
             if (!member.isInstanceMember) return;
             if (member.isGetter || member.isField || member.isFunction) {
               var selectors =
@@ -354,7 +356,7 @@
                   var stubName = namer.invocationName(selector);
                   if (stubNames.add(stubName.key)) {
                     interceptorClass.callStubs.add(_buildStubMethod(stubName,
-                        js.js('function(obj) { return obj.# }', [member.name]),
+                        js.js('function(obj) { return obj.# }', [jsName]),
                         element: member));
                   }
                 }
@@ -367,10 +369,8 @@
               if (selectors != null && !selectors.isEmpty) {
                 var stubName = namer.setterForElement(member);
                 if (stubNames.add(stubName.key)) {
-                  interceptorClass.callStubs.add(_buildStubMethod(
-                      stubName,
-                      js.js('function(obj, v) { return obj.# = v }',
-                          [member.name]),
+                  interceptorClass.callStubs.add(_buildStubMethod(stubName,
+                      js.js('function(obj, v) { return obj.# = v }', [jsName]),
                       element: member));
                 }
               }
@@ -447,7 +447,7 @@
                   interceptorClass.callStubs.add(_buildStubMethod(
                       stubName,
                       js.js('function(receiver, #) { return receiver.#(#) }',
-                          [parameters, member.name, parameters]),
+                          [parameters, jsName, parameters]),
                       element: member));
                 }
               }
diff --git a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
index ddef40b..c41bfa9 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -133,15 +133,15 @@
         generateFunctionTypeSignature, generateSubstitution, generateTypeCheck);
 
     if (classElement == backend.helpers.jsJavaScriptFunctionClass) {
-        var type = backend.jsInteropAnalysis.buildJsFunctionType();
-        if (type != null) {
-          jsAst.Expression thisAccess = new jsAst.This();
-          RuntimeTypesEncoder rtiEncoder = backend.rtiEncoder;
-          jsAst.Expression encoding =
-              rtiEncoder.getSignatureEncoding(type, thisAccess);
-          jsAst.Name operatorSignature = namer.asName(namer.operatorSignature);
-          result.properties[operatorSignature] = encoding;
-        }
+      var type = backend.jsInteropAnalysis.buildJsFunctionType();
+      if (type != null) {
+        jsAst.Expression thisAccess = new jsAst.This();
+        RuntimeTypesEncoder rtiEncoder = backend.rtiEncoder;
+        jsAst.Expression encoding =
+            rtiEncoder.getSignatureEncoding(type, thisAccess);
+        jsAst.Name operatorSignature = namer.asName(namer.operatorSignature);
+        result.properties[operatorSignature] = encoding;
+      }
     }
     return result;
   }
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 1b7beca..69e3dea 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
@@ -64,13 +64,9 @@
   }
 }
 
-var supportsDirectProtoAccess = (function () {
-  var cls = function () {};
-  cls.prototype = {'p': {}};
-  var object = new cls();
-  return object.__proto__ &&
-         object.__proto__.p === cls.prototype.p;
-})();
+// Only use direct proto access to construct the prototype chain (instead of
+// copying properties) on platforms where we know it works well (Chrome / d8).
+var supportsDirectProtoAccess = #directAccessTestExpression;
 
 var functionsHaveName = (function() {
   function t() {};
@@ -354,6 +350,36 @@
 })()
 ''';
 
+/// An expression that returns `true` if `__proto__` can be assigned to stitch
+/// together a prototype chain, and the performance is good.
+const String directAccessTestExpression = r'''
+  (function () {
+    var cls = function () {};
+    cls.prototype = {'p': {}};
+    var object = new cls();
+    if (!(object.__proto__ && object.__proto__.p === cls.prototype.p))
+      return false;
+    
+    try {
+      // Are we running on a platform where the performance is good?
+      // (i.e. Chrome or d8).
+
+      // Chrome userAgent?
+      if (typeof navigator != "undefined" &&
+          typeof navigator.userAgent == "string" &&
+          navigator.userAgent.indexOf("Chrome/") >= 0) return true;
+      // d8 version() looks like "N.N.N.N", jsshell version() like "N".
+      if (typeof version == "function" &&
+          version.length == 0) {
+        var v = version();
+        if (/^\d+\.\d+\.\d+\.\d+$/.test(v)) return true;
+      }
+    } catch(_) {}
+
+    return false;
+  })()
+''';
+
 /// Deferred fragments (aka 'hunks') are built similarly to the main fragment.
 ///
 /// However, at specific moments they need to contribute their data.
@@ -436,6 +462,7 @@
         program.holders.where((Holder holder) => !holder.isStaticStateHolder);
 
     return js.js.statement(mainBoilerplate, {
+      'directAccessTestExpression': js.js(directAccessTestExpression),
       'typeNameProperty': js.string(ModelEmitter.typeNameProperty),
       'cyclicThrow': backend.emitter
           .staticFunctionAccess(backend.helpers.cyclicThrowHelper),
diff --git a/pkg/compiler/lib/src/library_loader.dart b/pkg/compiler/lib/src/library_loader.dart
index be0cb41..c7c6e86 100644
--- a/pkg/compiler/lib/src/library_loader.dart
+++ b/pkg/compiler/lib/src/library_loader.dart
@@ -548,7 +548,7 @@
             handler.registerDependency(
                 library,
                 new SyntheticImportElement(
-                    library.entryCompilationUnit, Uris.dart_core),
+                    library.entryCompilationUnit, Uris.dart_core, coreLibrary),
                 coreLibrary);
           });
         }
@@ -916,10 +916,9 @@
 class LibraryDependencyNode {
   final LibraryElementX library;
 
-  // TODO(ahe): Remove [hashCodeCounter] and [hashCode] when
-  // VM implementation of Object.hashCode is not slow.
-  final int hashCode = ++hashCodeCounter;
-  static int hashCodeCounter = 0;
+  // Stored identity based hashCode for performance.
+  final int hashCode = _nextHash = (_nextHash + 100019).toUnsigned(30);
+  static int _nextHash = 0;
 
   /**
    * A linked list of the import tags that import [library] mapped to the
diff --git a/pkg/compiler/lib/src/native/native.dart b/pkg/compiler/lib/src/native/native.dart
index c9c60f69..c0d6a86 100644
--- a/pkg/compiler/lib/src/native/native.dart
+++ b/pkg/compiler/lib/src/native/native.dart
@@ -19,6 +19,7 @@
   'html_common',
   'indexed_db',
   'js',
+  'js_util',
   'svg',
   '_native_typed_data',
   'web_audio',
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index ee3370e..c5eefce 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -527,7 +527,7 @@
 
   /// Creates a copy of the [CompilerOptions] where the provided non-null
   /// option values replace existing.
-  CompilerOptions copy(
+  static CompilerOptions copy(CompilerOptions options,
       {entryPoint,
       libraryRoot,
       packageRoot,
@@ -583,71 +583,76 @@
       useStartupEmitter,
       verbose}) {
     return new CompilerOptions._(
-        entryPoint ?? this.entryPoint,
-        libraryRoot ?? this.libraryRoot,
-        packageRoot ?? this.packageRoot,
-        packageConfig ?? this.packageConfig,
-        packagesDiscoveryProvider ?? this.packagesDiscoveryProvider,
-        environment ?? this.environment,
-        allowMockCompilation: allowMockCompilation ?? this.allowMockCompilation,
+        entryPoint ?? options.entryPoint,
+        libraryRoot ?? options.libraryRoot,
+        packageRoot ?? options.packageRoot,
+        packageConfig ?? options.packageConfig,
+        packagesDiscoveryProvider ?? options.packagesDiscoveryProvider,
+        environment ?? options.environment,
+        allowMockCompilation:
+            allowMockCompilation ?? options.allowMockCompilation,
         allowNativeExtensions:
-            allowNativeExtensions ?? this.allowNativeExtensions,
-        analyzeAll: analyzeAll ?? this.analyzeAll,
-        analyzeMain: analyzeMain ?? this.analyzeMain,
-        analyzeOnly: analyzeOnly ?? this.analyzeOnly,
+            allowNativeExtensions ?? options.allowNativeExtensions,
+        analyzeAll: analyzeAll ?? options.analyzeAll,
+        analyzeMain: analyzeMain ?? options.analyzeMain,
+        analyzeOnly: analyzeOnly ?? options.analyzeOnly,
         analyzeSignaturesOnly:
-            analyzeSignaturesOnly ?? this.analyzeSignaturesOnly,
-        buildId: buildId ?? this.buildId,
-        dart2dartMultiFile: dart2dartMultiFile ?? this.dart2dartMultiFile,
-        deferredMapUri: deferredMapUri ?? this.deferredMapUri,
-        fatalWarnings: fatalWarnings ?? this.fatalWarnings,
-        terseDiagnostics: terseDiagnostics ?? this.terseDiagnostics,
-        suppressWarnings: suppressWarnings ?? this.suppressWarnings,
-        suppressHints: suppressHints ?? this.suppressHints,
+            analyzeSignaturesOnly ?? options.analyzeSignaturesOnly,
+        buildId: buildId ?? options.buildId,
+        dart2dartMultiFile: dart2dartMultiFile ?? options.dart2dartMultiFile,
+        deferredMapUri: deferredMapUri ?? options.deferredMapUri,
+        fatalWarnings: fatalWarnings ?? options.fatalWarnings,
+        terseDiagnostics: terseDiagnostics ?? options.terseDiagnostics,
+        suppressWarnings: suppressWarnings ?? options.suppressWarnings,
+        suppressHints: suppressHints ?? options.suppressHints,
         shownPackageWarnings:
-            shownPackageWarnings ?? this._shownPackageWarnings,
-        disableInlining: disableInlining ?? this.disableInlining,
-        disableTypeInference: disableTypeInference ?? this.disableTypeInference,
-        dumpInfo: dumpInfo ?? this.dumpInfo,
-        emitJavaScript: emitJavaScript ?? this.emitJavaScript,
-        enableAssertMessage: enableAssertMessage ?? this.enableAssertMessage,
+            shownPackageWarnings ?? options._shownPackageWarnings,
+        disableInlining: disableInlining ?? options.disableInlining,
+        disableTypeInference:
+            disableTypeInference ?? options.disableTypeInference,
+        dumpInfo: dumpInfo ?? options.dumpInfo,
+        emitJavaScript: emitJavaScript ?? options.emitJavaScript,
+        enableAssertMessage: enableAssertMessage ?? options.enableAssertMessage,
         enableGenericMethodSyntax:
-            enableGenericMethodSyntax ?? this.enableGenericMethodSyntax,
+            enableGenericMethodSyntax ?? options.enableGenericMethodSyntax,
         enableInitializingFormalAccess: enableInitializingFormalAccess ??
-            this.enableInitializingFormalAccess,
+            options.enableInitializingFormalAccess,
         enableExperimentalMirrors:
-            enableExperimentalMirrors ?? this.enableExperimentalMirrors,
-        enableMinification: enableMinification ?? this.enableMinification,
-        enableNativeLiveTypeAnalysis:
-            enableNativeLiveTypeAnalysis ?? this.enableNativeLiveTypeAnalysis,
-        enableTypeAssertions: enableTypeAssertions ?? this.enableTypeAssertions,
-        enableUserAssertions: enableUserAssertions ?? this.enableUserAssertions,
+            enableExperimentalMirrors ?? options.enableExperimentalMirrors,
+        enableMinification: enableMinification ?? options.enableMinification,
+        enableNativeLiveTypeAnalysis: enableNativeLiveTypeAnalysis ??
+            options.enableNativeLiveTypeAnalysis,
+        enableTypeAssertions:
+            enableTypeAssertions ?? options.enableTypeAssertions,
+        enableUserAssertions:
+            enableUserAssertions ?? options.enableUserAssertions,
         generateCodeWithCompileTimeErrors: generateCodeWithCompileTimeErrors ??
-            this.generateCodeWithCompileTimeErrors,
-        generateSourceMap: generateSourceMap ?? this.generateSourceMap,
+            options.generateCodeWithCompileTimeErrors,
+        generateSourceMap: generateSourceMap ?? options.generateSourceMap,
         hasIncrementalSupport:
-            hasIncrementalSupport ?? this.hasIncrementalSupport,
-        outputUri: outputUri ?? this.outputUri,
-        platformConfigUri: platformConfigUri ?? this.platformConfigUri,
-        preserveComments: preserveComments ?? this.preserveComments,
-        preserveUris: preserveUris ?? this.preserveUris,
-        resolutionInputs: resolutionInputs ?? this.resolutionInputs,
-        resolutionOutput: resolutionOutput ?? this.resolutionOutput,
-        resolveOnly: resolveOnly ?? this.resolveOnly,
-        sourceMapUri: sourceMapUri ?? this.sourceMapUri,
-        strips: strips ?? this.strips,
-        testMode: testMode ?? this.testMode,
-        trustJSInteropTypeAnnotations:
-            trustJSInteropTypeAnnotations ?? this.trustJSInteropTypeAnnotations,
-        trustPrimitives: trustPrimitives ?? this.trustPrimitives,
-        trustTypeAnnotations: trustTypeAnnotations ?? this.trustTypeAnnotations,
+            hasIncrementalSupport ?? options.hasIncrementalSupport,
+        outputUri: outputUri ?? options.outputUri,
+        platformConfigUri: platformConfigUri ?? options.platformConfigUri,
+        preserveComments: preserveComments ?? options.preserveComments,
+        preserveUris: preserveUris ?? options.preserveUris,
+        resolutionInputs: resolutionInputs ?? options.resolutionInputs,
+        resolutionOutput: resolutionOutput ?? options.resolutionOutput,
+        resolveOnly: resolveOnly ?? options.resolveOnly,
+        sourceMapUri: sourceMapUri ?? options.sourceMapUri,
+        strips: strips ?? options.strips,
+        testMode: testMode ?? options.testMode,
+        trustJSInteropTypeAnnotations: trustJSInteropTypeAnnotations ??
+            options.trustJSInteropTypeAnnotations,
+        trustPrimitives: trustPrimitives ?? options.trustPrimitives,
+        trustTypeAnnotations:
+            trustTypeAnnotations ?? options.trustTypeAnnotations,
         useContentSecurityPolicy:
-            useContentSecurityPolicy ?? this.useContentSecurityPolicy,
-        useCpsIr: useCpsIr ?? this.useCpsIr,
-        useFrequencyNamer: useFrequencyNamer ?? this.useFrequencyNamer,
-        useNewSourceInfo: useNewSourceInfo ?? this.useNewSourceInfo,
-        useStartupEmitter: useStartupEmitter ?? this.useStartupEmitter,
-        verbose: verbose ?? this.verbose);
+            useContentSecurityPolicy ?? options.useContentSecurityPolicy,
+        useCpsIr: useCpsIr ?? options.useCpsIr,
+        useFrequencyNamer: useFrequencyNamer ?? options.useFrequencyNamer,
+        useNewSourceInfo: useNewSourceInfo ?? options.useNewSourceInfo,
+        useStartupEmitter: useStartupEmitter ?? options.useStartupEmitter,
+        verbose: verbose ?? options.verbose);
   }
 
   /// Returns `true` if warnings and hints are shown for all packages.
diff --git a/pkg/compiler/lib/src/parser/parser.dart b/pkg/compiler/lib/src/parser/parser.dart
index 821fcad..3ac4900 100644
--- a/pkg/compiler/lib/src/parser/parser.dart
+++ b/pkg/compiler/lib/src/parser/parser.dart
@@ -424,13 +424,12 @@
     listener.beginFormalParameters(begin);
     expect('(', token);
     int parameterCount = 0;
-    if (optional(')', token.next)) {
-      listener.endFormalParameters(parameterCount, begin, token.next);
-      return token.next.next;
-    }
     do {
-      ++parameterCount;
       token = token.next;
+      if (optional(')', token)) {
+        break;
+      }
+      ++parameterCount;
       String value = token.stringValue;
       if (identical(value, '[')) {
         token = parseOptionalFormalParameters(token, false);
@@ -495,11 +494,23 @@
     int parameterCount = 0;
     do {
       token = token.next;
+      if (isNamed && optional('}', token)) {
+        break;
+      } else if (!isNamed && optional(']', token)) {
+        break;
+      }
       var type =
           isNamed ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL;
       token = parseFormalParameter(token, type);
       ++parameterCount;
     } while (optional(',', token));
+    if (parameterCount == 0) {
+      listener.reportError(
+          token,
+          isNamed
+              ? MessageKind.EMPTY_NAMED_PARAMETER_LIST
+              : MessageKind.EMPTY_OPTIONAL_PARAMETER_LIST);
+    }
     listener.endOptionalFormalParameters(parameterCount, begin, token);
     if (isNamed) {
       return expect('}', token);
@@ -2565,6 +2576,10 @@
     bool old = mayParseFunctionExpressions;
     mayParseFunctionExpressions = true;
     do {
+      if (optional(')', token.next)) {
+        token = token.next;
+        break;
+      }
       Token colon = null;
       if (optional(':', token.next.next)) {
         token = parseIdentifier(token.next);
diff --git a/pkg/compiler/lib/src/resolution/class_hierarchy.dart b/pkg/compiler/lib/src/resolution/class_hierarchy.dart
index 87c00a8..39fe5e1 100644
--- a/pkg/compiler/lib/src/resolution/class_hierarchy.dart
+++ b/pkg/compiler/lib/src/resolution/class_hierarchy.dart
@@ -5,8 +5,7 @@
 library dart2js.resolution.class_hierarchy;
 
 import '../common.dart';
-import '../common/resolution.dart' show Feature;
-import '../compiler.dart' show Compiler;
+import '../common/resolution.dart' show Feature, Resolution;
 import '../core_types.dart' show CoreClasses, CoreTypes;
 import '../dart_types.dart';
 import '../elements/elements.dart';
@@ -34,13 +33,13 @@
   final TypeDeclarationElement enclosingElement;
   TypeDeclarationElement get element => enclosingElement;
 
-  TypeDefinitionVisitor(Compiler compiler, TypeDeclarationElement element,
+  TypeDefinitionVisitor(Resolution resolution, TypeDeclarationElement element,
       ResolutionRegistry registry)
       : this.enclosingElement = element,
         scope = Scope.buildEnclosingScope(element),
-        super(compiler, registry);
+        super(resolution, registry);
 
-  CoreTypes get coreTypes => compiler.coreTypes;
+  CoreTypes get coreTypes => resolution.coreTypes;
 
   DartType get objectType => coreTypes.objectType;
 
@@ -118,9 +117,9 @@
 class ClassResolverVisitor extends TypeDefinitionVisitor {
   BaseClassElementX get element => enclosingElement;
 
-  ClassResolverVisitor(
-      Compiler compiler, ClassElement classElement, ResolutionRegistry registry)
-      : super(compiler, classElement, registry);
+  ClassResolverVisitor(Resolution resolution, ClassElement classElement,
+      ResolutionRegistry registry)
+      : super(resolution, classElement, registry);
 
   DartType visitClassNode(ClassNode node) {
     if (element == null) {
@@ -212,7 +211,7 @@
           new SynthesizedConstructorElementX.forDefault(superMember, element);
       if (superMember.isMalformed) {
         ErroneousElement erroneousElement = superMember;
-        compiler.registerCompiletimeError(
+        resolution.registerCompileTimeError(
             constructor,
             reporter.createMessage(node, erroneousElement.messageKind,
                 erroneousElement.messageArguments));
@@ -243,7 +242,7 @@
     }
 
     EnumCreator creator =
-        new EnumCreator(reporter, compiler.coreTypes, element);
+        new EnumCreator(reporter, resolution.coreTypes, element);
     creator.createMembers();
     return enumType;
   }
@@ -304,7 +303,7 @@
     String mixinName = mixinType.name;
     MixinApplicationElementX mixinApplication =
         new UnnamedMixinApplicationElementX("${superName}+${mixinName}",
-            element, compiler.idGenerator.getNextFreeId(), node);
+            element, resolution.idGenerator.getNextFreeId(), node);
     // Create synthetic type variables for the mixin application.
     List<DartType> typeVariables = <DartType>[];
     int index = 0;
@@ -360,7 +359,7 @@
 
     if (mixinApplication.supertype != null) {
       // [supertype] is not null if there was a cycle.
-      assert(invariant(node, compiler.compilationFailed));
+      assert(invariant(node, reporter.hasReportedError));
       supertype = mixinApplication.supertype;
       assert(invariant(node, supertype.isObject));
     } else {
@@ -545,7 +544,7 @@
               reporter: reporter, objectType: coreTypes.objectType)
           .createOrderedTypeSet(supertype, cls.interfaces);
     } else {
-      assert(cls == compiler.coreClasses.objectClass);
+      assert(cls == resolution.coreClasses.objectClass);
       cls.allSupertypesAndSelf =
           new OrderedTypeSet.singleton(cls.computeType(resolution));
     }
@@ -553,7 +552,7 @@
 
   isBlackListed(DartType type) {
     LibraryElement lib = element.library;
-    return !identical(lib, compiler.coreLibrary) &&
+    return !identical(lib, resolution.coreLibrary) &&
         !resolution.target.isTargetSpecificLibrary(lib) &&
         (type.isDynamic ||
             type == coreTypes.boolType ||
@@ -569,16 +568,16 @@
   Scope context;
   ClassElement classElement;
 
-  ClassSupertypeResolver(Compiler compiler, ClassElement cls)
+  ClassSupertypeResolver(Resolution resolution, ClassElement cls)
       : context = Scope.buildEnclosingScope(cls),
         this.classElement = cls,
-        super(compiler);
+        super(resolution);
 
-  CoreClasses get coreClasses => compiler.coreClasses;
+  CoreClasses get coreClasses => resolution.coreClasses;
 
   void loadSupertype(ClassElement element, Node from) {
     if (!element.isResolved) {
-      compiler.resolver.loadSupertypes(element, from);
+      resolution.resolver.loadSupertypes(element, from);
       element.ensureResolved(resolution);
     }
   }
diff --git a/pkg/compiler/lib/src/resolution/constructors.dart b/pkg/compiler/lib/src/resolution/constructors.dart
index 90f4716..50f51d1 100644
--- a/pkg/compiler/lib/src/resolution/constructors.dart
+++ b/pkg/compiler/lib/src/resolution/constructors.dart
@@ -5,8 +5,7 @@
 library dart2js.resolution.constructors;
 
 import '../common.dart';
-import '../common/resolution.dart' show Feature;
-import '../compiler.dart' show Compiler;
+import '../common/resolution.dart' show Feature, Resolution;
 import '../constants/constructors.dart'
     show
         GenerativeConstantConstructor,
@@ -476,9 +475,9 @@
   final ResolverVisitor resolver;
   final bool inConstContext;
 
-  ConstructorResolver(Compiler compiler, this.resolver,
+  ConstructorResolver(Resolution resolution, this.resolver,
       {bool this.inConstContext: false})
-      : super(compiler);
+      : super(resolution);
 
   ResolutionRegistry get registry => resolver.registry;
 
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index b12218b..97f59bc 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -6,8 +6,8 @@
 
 import '../common.dart';
 import '../common/names.dart' show Selectors;
-import '../common/resolution.dart' show Feature;
-import '../compiler.dart' show Compiler;
+import '../common/resolution.dart' show Feature, Resolution;
+import '../compile_time_constants.dart';
 import '../constants/constructors.dart'
     show RedirectingFactoryConstantConstructor;
 import '../constants/expressions.dart';
@@ -27,6 +27,7 @@
         ParameterElementX,
         VariableElementX,
         VariableList;
+import '../options.dart';
 import '../tokens/token.dart' show isUserDefinableOperator;
 import '../tree/tree.dart';
 import '../universe/call_structure.dart' show CallStructure;
@@ -112,7 +113,7 @@
 
   bool isPotentiallyMutableTarget(Element target) {
     if (target == null) return false;
-    return (target.isVariable || target.isParameter) &&
+    return (target.isVariable || target.isRegularParameter) &&
         !(target.isFinal || target.isConst);
   }
 
@@ -142,7 +143,7 @@
           r')$');
 
   ResolverVisitor(
-      Compiler compiler, Element element, ResolutionRegistry registry,
+      Resolution resolution, Element element, ResolutionRegistry registry,
       {Scope scope, bool useEnclosingScope: false})
       : this.enclosingElement = element,
         // When the element is a field, we are actually resolving its
@@ -159,7 +160,7 @@
                 : element.buildScope()),
         // The type annotations on a typedef do not imply type checks.
         // TODO(karlklose): clean this up (dartbug.com/8870).
-        inCheckContext = compiler.options.enableTypeAssertions &&
+        inCheckContext = resolution.options.enableTypeAssertions &&
             !element.isLibrary &&
             !element.isTypedef &&
             !element.enclosingElement.isTypedef,
@@ -167,11 +168,13 @@
         constantState = element.isConst
             ? ConstantState.CONSTANT
             : ConstantState.NON_CONSTANT,
-        super(compiler, registry);
+        super(resolution, registry);
 
-  CoreClasses get coreClasses => compiler.coreClasses;
-
-  CoreTypes get coreTypes => compiler.coreTypes;
+  CoreClasses get coreClasses => resolution.coreClasses;
+  CoreTypes get coreTypes => resolution.coreTypes;
+  ConstantEnvironment get constants => resolution.constants;
+  ResolverTask get resolver => resolution.resolver;
+  CompilerOptions get options => resolution.options;
 
   AsyncMarker get currentAsyncMarker {
     if (enclosingElement is FunctionElement) {
@@ -370,11 +373,7 @@
   }
 
   TypeResult visitTypeAnnotation(TypeAnnotation node) {
-    DartType type = resolveTypeAnnotation(node);
-    if (inCheckContext) {
-      registry.registerTypeUse(new TypeUse.checkedModeCheck(type));
-    }
-    return new TypeResult(type);
+    return new TypeResult(resolveTypeAnnotation(node));
   }
 
   bool isNamedConstructor(Send node) => node.receiver != null;
@@ -454,18 +453,16 @@
     addDeferredAction(enclosingElement, () {
       functionSignature.forEachOptionalParameter((ParameterElementX parameter) {
         parameter.constant =
-            compiler.resolver.constantCompiler.compileConstant(parameter);
+            resolver.constantCompiler.compileConstant(parameter);
       });
     });
-    if (inCheckContext) {
-      functionSignature.forEachParameter((ParameterElement element) {
-        registry.registerTypeUse(new TypeUse.checkedModeCheck(element.type));
-      });
-    }
+    functionSignature.forEachParameter((ParameterElement element) {
+      registry.registerTypeUse(new TypeUse.checkedModeCheck(element.type));
+    });
   }
 
   ResolutionResult visitAssert(Assert node) {
-    if (!compiler.options.enableAssertMessage) {
+    if (!options.enableAssertMessage) {
       if (node.hasMessage) {
         reporter.reportErrorMessage(
             node, MessageKind.EXPERIMENTAL_ASSERT_MESSAGE);
@@ -564,7 +561,6 @@
       reporter.reportErrorMessage(node.name,
           MessageKind.NAMED_FUNCTION_EXPRESSION, {'name': node.name});
     }
-    visit(node.returnType);
     String name;
     if (node.name == null) {
       name = "";
@@ -573,9 +569,9 @@
     }
     LocalFunctionElementX function = new LocalFunctionElementX(
         name, node, ElementKind.FUNCTION, Modifiers.EMPTY, enclosingElement);
-    ResolverTask.processAsyncMarker(compiler, function, registry);
+    ResolverTask.processAsyncMarker(resolution, function, registry);
     function.functionSignature = SignatureResolver.analyze(
-        compiler,
+        resolution,
         scope,
         node.typeVariables,
         node.parameters,
@@ -880,7 +876,7 @@
   /// Compute the [AccessSemantics] corresponding to a local access of [target].
   AccessSemantics computeLocalAccessSemantics(
       Spannable node, LocalElement target) {
-    if (target.isParameter) {
+    if (target.isRegularParameter) {
       if (target.isFinal || target.isConst) {
         return new StaticAccess.finalParameter(target);
       } else {
@@ -2017,7 +2013,7 @@
   ResolutionResult handleConstantTypeLiteralUpdate(SendSet node, Name name,
       TypeDeclarationElement element, DartType type, ConstantAccess semantics) {
     // TODO(johnniwinther): Remove this when all constants are evaluated.
-    compiler.resolver.constantCompiler.evaluate(semantics.constant);
+    resolver.constantCompiler.evaluate(semantics.constant);
 
     ErroneousElement error;
     if (node.isIfNullAssignment) {
@@ -2560,7 +2556,7 @@
   ResolutionResult handleLocalUpdate(Send node, Name name, Element element) {
     AccessSemantics semantics;
     ErroneousElement error;
-    if (element.isParameter) {
+    if (element.isRegularParameter) {
       if (element.isFinal) {
         error = reportAndCreateErroneousElement(node.selector, name.text,
             MessageKind.UNDEFINED_STATIC_SETTER_BUT_GETTER, {'name': name});
@@ -2569,7 +2565,7 @@
         semantics = new StaticAccess.parameter(element);
       }
     } else if (element.isInitializingFormal &&
-        compiler.options.enableInitializingFormalAccess) {
+        options.enableInitializingFormalAccess) {
       error = reportAndCreateErroneousElement(node.selector, name.text,
           MessageKind.UNDEFINED_STATIC_SETTER_BUT_GETTER, {'name': name});
       semantics = new StaticAccess.finalParameter(element);
@@ -2627,12 +2623,12 @@
     // of parse errors to make [element] erroneous. Fix this!
     member.computeType(resolution);
 
-    if (member == compiler.mirrorSystemGetNameFunction &&
-        !compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) {
+    if (member == resolution.mirrorSystemGetNameFunction &&
+        !resolution.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) {
       reporter
           .reportHintMessage(node.selector, MessageKind.STATIC_FUNCTION_BLOAT, {
-        'class': compiler.mirrorSystemClass.name,
-        'name': compiler.mirrorSystemGetNameFunction.name
+        'class': resolution.mirrorSystemClass.name,
+        'name': resolution.mirrorSystemGetNameFunction.name
       });
     }
 
@@ -2658,7 +2654,7 @@
             registry.registerStaticUse(
                 new StaticUse.staticInvoke(semantics.element, callStructure));
             handleForeignCall(node, semantics.element, callStructure);
-            if (method == compiler.identicalFunction &&
+            if (method == resolution.identicalFunction &&
                 argumentsResult.isValidAsConstant) {
               result = new ConstantResult(
                   node,
@@ -3028,7 +3024,7 @@
   // TODO(johnniwinther): Move this to the backend resolution callbacks.
   void handleForeignCall(
       Send node, Element target, CallStructure callStructure) {
-    if (target != null && compiler.backend.isForeign(target)) {
+    if (target != null && resolution.target.isForeign(target)) {
       registry.registerForeignCall(node, target, callStructure, this);
     }
   }
@@ -3577,7 +3573,7 @@
   }
 
   ResolutionResult visitYield(Yield node) {
-    if (!compiler.backend.supportsAsyncAwait) {
+    if (!resolution.target.supportsAsyncAwait) {
       reporter.reportErrorMessage(
           node.yieldToken, MessageKind.ASYNC_AWAIT_NOT_SUPPORTED);
     } else {
@@ -3608,11 +3604,8 @@
     ConstructorResult result =
         resolveRedirectingFactory(node, inConstContext: isConstConstructor);
     ConstructorElement redirectionTarget = result.element;
-    constructor.immediateRedirectionTarget = redirectionTarget;
-
-    if (result.isDeferred) {
-      constructor.redirectionDeferredPrefix = result.prefix;
-    }
+    constructor.setImmediateRedirectionTarget(
+        redirectionTarget, result.isDeferred ? result.prefix : null);
 
     registry.setRedirectingTargetConstructor(node, redirectionTarget);
     switch (result.kind) {
@@ -3621,7 +3614,7 @@
         // Register a post process to check for cycles in the redirection chain
         // and set the actual generative constructor at the end of the chain.
         addDeferredAction(constructor, () {
-          compiler.resolver.resolveRedirectionChain(constructor, node);
+          resolver.resolveRedirectionChain(constructor, node);
         });
         break;
       case ConstructorResultKind.ABSTRACT:
@@ -3659,7 +3652,7 @@
         .subst(type.typeArguments, targetClass.typeVariables);
     FunctionType constructorType = constructor.computeType(resolution);
     bool isSubtype =
-        compiler.types.isSubtype(targetConstructorType, constructorType);
+        resolution.types.isSubtype(targetConstructorType, constructorType);
     if (!isSubtype) {
       reporter.reportWarningMessage(node, MessageKind.NOT_ASSIGNABLE,
           {'fromType': targetConstructorType, 'toType': constructorType});
@@ -3684,7 +3677,7 @@
     registry.registerTypeUse(new TypeUse.instantiation(redirectionTarget
         .enclosingClass.thisType
         .subst(type.typeArguments, targetClass.typeVariables)));
-    if (enclosingElement == compiler.symbolConstructor) {
+    if (enclosingElement == resolution.symbolConstructor) {
       registry.registerFeature(Feature.SYMBOL_CONSTRUCTOR);
     }
     if (isValidAsConstant) {
@@ -3718,7 +3711,7 @@
   }
 
   ResolutionResult visitAwait(Await node) {
-    if (!compiler.backend.supportsAsyncAwait) {
+    if (!resolution.target.supportsAsyncAwait) {
       reporter.reportErrorMessage(
           node.awaitToken, MessageKind.ASYNC_AWAIT_NOT_SUPPORTED);
     } else {
@@ -3740,7 +3733,7 @@
     }
     VariableList variables = new VariableList.node(node, type);
     VariableDefinitionsVisitor visitor =
-        new VariableDefinitionsVisitor(compiler, node, this, variables);
+        new VariableDefinitionsVisitor(resolution, node, this, variables);
 
     Modifiers modifiers = node.modifiers;
     void reportExtraModifier(String modifier) {
@@ -3773,7 +3766,7 @@
     }
     if (node.metadata != null) {
       variables.metadataInternal =
-          compiler.resolver.resolveMetadata(enclosingElement, node);
+          resolver.resolveMetadata(enclosingElement, node);
     }
     visitor.visit(node.definitions);
     return const NoneResult();
@@ -3893,11 +3886,11 @@
     if (node.isConst) {
       bool isValidAsConstant = !isInvalid && constructor.isConst;
 
-      if (constructor == compiler.symbolConstructor) {
+      if (constructor == resolution.symbolConstructor) {
         Node argumentNode = node.send.arguments.head;
-        ConstantExpression constant = compiler.resolver.constantCompiler
+        ConstantExpression constant = resolver.constantCompiler
             .compileNode(argumentNode, registry.mapping);
-        ConstantValue name = compiler.constants.getConstantValue(constant);
+        ConstantValue name = resolution.constants.getConstantValue(constant);
         if (!name.isString) {
           DartType type = name.getType(coreTypes);
           reporter.reportErrorMessage(
@@ -3909,8 +3902,8 @@
             registry.registerConstSymbol(nameString);
           }
         }
-      } else if (constructor == compiler.mirrorsUsedConstructor) {
-        compiler.mirrorUsageAnalyzerTask.validate(node, registry.mapping);
+      } else if (constructor == resolution.mirrorsUsedConstructor) {
+        resolution.mirrorUsageAnalyzerTask.validate(node, registry.mapping);
       }
 
       analyzeConstantDeferred(node);
@@ -3969,8 +3962,9 @@
       analyzeConstantDeferred(node, onAnalyzed: onAnalyzed);
     } else {
       // Not constant.
-      if (constructor == compiler.symbolConstructor &&
-          !compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) {
+      if (constructor == resolution.symbolConstructor &&
+          !resolution.mirrorUsageAnalyzerTask
+              .hasMirrorUsage(enclosingElement)) {
         reporter.reportHintMessage(node.newToken, MessageKind.NON_CONST_BLOAT,
             {'name': coreClasses.symbolClass.name});
       }
@@ -4001,15 +3995,15 @@
   }
 
   void analyzeConstant(Node node, {enforceConst: true}) {
-    ConstantExpression constant = compiler.resolver.constantCompiler
+    ConstantExpression constant = resolver.constantCompiler
         .compileNode(node, registry.mapping, enforceConst: enforceConst);
 
     if (constant == null) {
-      assert(invariant(node, compiler.compilationFailed));
+      assert(invariant(node, reporter.hasReportedError));
       return;
     }
 
-    ConstantValue value = compiler.constants.getConstantValue(constant);
+    ConstantValue value = resolution.constants.getConstantValue(constant);
     if (value.isMap) {
       checkConstMapKeysDontOverrideEquals(node, value);
     }
@@ -4050,13 +4044,13 @@
    * [:null:], if there is no corresponding constructor, class or library.
    */
   ConstructorResult resolveConstructor(NewExpression node) {
-    return node.accept(
-        new ConstructorResolver(compiler, this, inConstContext: node.isConst));
+    return node.accept(new ConstructorResolver(resolution, this,
+        inConstContext: node.isConst));
   }
 
   ConstructorResult resolveRedirectingFactory(RedirectingFactoryBody node,
       {bool inConstContext: false}) {
-    return node.accept(new ConstructorResolver(compiler, this,
+    return node.accept(new ConstructorResolver(resolution, this,
         inConstContext: inConstContext));
   }
 
@@ -4065,9 +4059,7 @@
     DartType type = typeResolver.resolveTypeAnnotation(this, node,
         malformedIsError: malformedIsError,
         deferredIsMalformed: deferredIsMalformed);
-    if (inCheckContext) {
-      registry.registerTypeUse(new TypeUse.checkedModeCheck(type));
-    }
+    registry.registerTypeUse(new TypeUse.checkedModeCheck(type));
     return type;
   }
 
@@ -4245,7 +4237,7 @@
   }
 
   ResolutionResult visitAsyncForIn(AsyncForIn node) {
-    if (!compiler.backend.supportsAsyncAwait) {
+    if (!resolution.target.supportsAsyncAwait) {
       reporter.reportErrorMessage(
           node.awaitToken, MessageKind.ASYNC_AWAIT_NOT_SUPPORTED);
     } else {
@@ -4333,7 +4325,7 @@
       }
     } else {
       // The selector may only be null if we reported an error.
-      assert(invariant(declaration, compiler.compilationFailed));
+      assert(invariant(declaration, reporter.hasReportedError));
     }
     if (loopVariable != null) {
       // loopVariable may be null if it could not be resolved.
@@ -4496,7 +4488,7 @@
         assert(invariant(node, constant != null,
             message: 'No constant computed for $node'));
 
-        ConstantValue value = compiler.constants.getConstantValue(constant);
+        ConstantValue value = resolution.constants.getConstantValue(constant);
         DartType caseType = value.getType(coreTypes); //typeOfConstant(value);
 
         if (firstCaseType == null) {
diff --git a/pkg/compiler/lib/src/resolution/registry.dart b/pkg/compiler/lib/src/resolution/registry.dart
index e52b185..753d9a7 100644
--- a/pkg/compiler/lib/src/resolution/registry.dart
+++ b/pkg/compiler/lib/src/resolution/registry.dart
@@ -8,7 +8,7 @@
 import '../common/backend_api.dart'
     show Backend, ForeignResolver, NativeRegistry;
 import '../common/resolution.dart'
-    show Feature, ListLiteralUse, MapLiteralUse, ResolutionImpact;
+    show Feature, ListLiteralUse, MapLiteralUse, ResolutionImpact, Target;
 import '../common/registry.dart' show Registry;
 import '../compiler.dart' show Compiler;
 import '../constants/expressions.dart';
@@ -160,20 +160,17 @@
 /// [Backend], [World] and [Enqueuer].
 // TODO(johnniwinther): Split this into an interface and implementation class.
 class ResolutionRegistry extends Registry {
-  final Compiler compiler;
+  final Target target;
   final TreeElementMapping mapping;
   final _ResolutionWorldImpact worldImpact;
 
-  ResolutionRegistry(Compiler compiler, TreeElementMapping mapping)
-      : this.compiler = compiler,
-        this.mapping = mapping,
+  ResolutionRegistry(this.target, TreeElementMapping mapping)
+      : this.mapping = mapping,
         this.worldImpact =
             new _ResolutionWorldImpact(mapping.analyzedElement.toString());
 
   bool get isForResolution => true;
 
-  Backend get backend => compiler.backend;
-
   String toString() => 'ResolutionRegistry for ${mapping.analyzedElement}';
 
   //////////////////////////////////////////////////////////////////////////////
@@ -364,7 +361,7 @@
 
   void registerForeignCall(Node node, Element element,
       CallStructure callStructure, ResolverVisitor visitor) {
-    var nativeData = backend.resolveForeignCall(node, element, callStructure,
+    var nativeData = target.resolveForeignCall(node, element, callStructure,
         new ForeignResolutionResolver(visitor, this));
     if (nativeData != null) {
       // Split impact from resolution result.
@@ -390,7 +387,7 @@
   }
 
   ClassElement defaultSuperclass(ClassElement element) {
-    return backend.defaultSuperclass(element);
+    return target.defaultSuperclass(element);
   }
 
   void registerInstantiation(InterfaceType type) {
diff --git a/pkg/compiler/lib/src/resolution/resolution.dart b/pkg/compiler/lib/src/resolution/resolution.dart
index f775190..619f748 100644
--- a/pkg/compiler/lib/src/resolution/resolution.dart
+++ b/pkg/compiler/lib/src/resolution/resolution.dart
@@ -9,10 +9,9 @@
 import '../common.dart';
 import '../common/names.dart' show Identifiers;
 import '../common/resolution.dart'
-    show Feature, ParsingContext, Resolution, ResolutionImpact;
-import '../common/tasks.dart' show CompilerTask;
+    show Feature, ParsingContext, Resolution, ResolutionImpact, Target;
+import '../common/tasks.dart' show CompilerTask, Measurer;
 import '../compile_time_constants.dart' show ConstantCompiler;
-import '../compiler.dart' show Compiler;
 import '../constants/expressions.dart'
     show
         ConstantExpression,
@@ -36,6 +35,8 @@
         ParameterMetadataAnnotation,
         SetterElementX,
         TypedefElementX;
+import '../enqueue.dart';
+import '../options.dart';
 import '../tokens/token.dart'
     show
         isBinaryOperator,
@@ -48,36 +49,35 @@
 import '../universe/use.dart' show StaticUse, TypeUse;
 import '../universe/world_impact.dart' show WorldImpact;
 import '../util/util.dart' show Link, Setlet;
+import '../world.dart';
 import 'class_hierarchy.dart';
 import 'class_members.dart' show MembersCreator;
 import 'constructors.dart';
 import 'members.dart';
 import 'registry.dart';
 import 'resolution_result.dart';
-import 'scope.dart' show MutableScope;
 import 'signatures.dart';
 import 'tree_elements.dart';
 import 'typedefs.dart';
 
 class ResolverTask extends CompilerTask {
   final ConstantCompiler constantCompiler;
-  final Compiler compiler;
+  final Resolution resolution;
+  final World world;
 
-  ResolverTask(Compiler compiler, this.constantCompiler)
-      : compiler = compiler,
-        super(compiler.measurer);
+  ResolverTask(
+      this.resolution, this.constantCompiler, this.world, Measurer measurer)
+      : super(measurer);
 
   String get name => 'Resolver';
 
-  DiagnosticReporter get reporter => compiler.reporter;
-
-  Resolution get resolution => compiler.resolution;
-
-  ParsingContext get parsingContext => compiler.parsingContext;
-
-  CoreClasses get coreClasses => compiler.coreClasses;
-
-  CoreTypes get coreTypes => compiler.coreTypes;
+  DiagnosticReporter get reporter => resolution.reporter;
+  Target get target => resolution.target;
+  CoreTypes get coreTypes => resolution.coreTypes;
+  CoreClasses get coreClasses => resolution.coreClasses;
+  ParsingContext get parsingContext => resolution.parsingContext;
+  CompilerOptions get options => resolution.options;
+  ResolutionEnqueuer get enqueuer => resolution.enqueuer;
 
   ResolutionImpact resolve(Element element) {
     return measure(() {
@@ -115,7 +115,7 @@
         return processMetadata(resolveTypedef(typdef));
       }
 
-      compiler.unimplemented(element, "resolve($element)");
+      reporter.internalError(element, "resolve($element) not implemented.");
     });
   }
 
@@ -142,15 +142,14 @@
     }
   }
 
-  static void processAsyncMarker(Compiler compiler,
+  static void processAsyncMarker(Resolution resolution,
       BaseFunctionElementX element, ResolutionRegistry registry) {
-    DiagnosticReporter reporter = compiler.reporter;
-    Resolution resolution = compiler.resolution;
-    CoreClasses coreClasses = compiler.coreClasses;
+    DiagnosticReporter reporter = resolution.reporter;
+    CoreClasses coreClasses = resolution.coreClasses;
     FunctionExpression functionExpression = element.node;
     AsyncModifier asyncModifier = functionExpression.asyncModifier;
     if (asyncModifier != null) {
-      if (!compiler.backend.supportsAsyncAwait) {
+      if (!resolution.target.supportsAsyncAwait) {
         reporter.reportErrorMessage(functionExpression.asyncModifier,
             MessageKind.ASYNC_AWAIT_NOT_SUPPORTED);
       } else {
@@ -207,7 +206,7 @@
   bool _isNativeClassOrExtendsNativeClass(ClassElement classElement) {
     assert(classElement != null);
     while (classElement != null) {
-      if (compiler.backend.isNative(classElement)) return true;
+      if (target.isNative(classElement)) return true;
       classElement = classElement.superclass;
     }
     return false;
@@ -239,7 +238,7 @@
       ResolutionRegistry registry = visitor.registry;
       registry.defineFunction(tree, element);
       visitor.setupFunction(tree, element); // Modifies the scope.
-      processAsyncMarker(compiler, element, registry);
+      processAsyncMarker(resolution, element, registry);
 
       if (element.isGenerativeConstructor) {
         // Even if there is no initializer list we still have to do the
@@ -248,7 +247,7 @@
             new InitializerResolver(visitor, element, tree);
         FunctionElement redirection = resolver.resolveInitializers(
             enableInitializingFormalAccess:
-                compiler.options.enableInitializingFormalAccess);
+                options.enableInitializingFormalAccess);
         if (redirection != null) {
           resolveRedirectingConstructor(resolver, tree, element, redirection);
         }
@@ -257,8 +256,7 @@
             tree, MessageKind.FUNCTION_WITH_INITIALIZER);
       }
 
-      if (!compiler.options.analyzeSignaturesOnly ||
-          tree.isRedirectingFactory) {
+      if (!options.analyzeSignaturesOnly || tree.isRedirectingFactory) {
         // We need to analyze the redirecting factory bodies to ensure that
         // we can analyze compile-time constants.
         visitor.visit(tree.body);
@@ -274,7 +272,7 @@
       if (enclosingClass != null) {
         // TODO(johnniwinther): Find another way to obtain mixin uses.
         Iterable<MixinApplicationElement> mixinUses =
-            compiler.world.allMixinUsesOf(enclosingClass);
+            world.allMixinUsesOf(enclosingClass);
         ClassElement mixin = enclosingClass;
         for (MixinApplicationElement mixinApplication in mixinUses) {
           checkMixinSuperUses(resolutionTree, mixinApplication, mixin);
@@ -298,7 +296,7 @@
   WorldImpact resolveMethodElement(FunctionElementX element) {
     assert(invariant(element, element.isDeclaration));
     return reporter.withCurrentElement(element, () {
-      if (compiler.enqueuer.resolution.hasBeenProcessed(element)) {
+      if (enqueuer.hasBeenProcessed(element)) {
         // TODO(karlklose): Remove the check for [isConstructor]. [elememts]
         // should never be non-null, not even for constructors.
         assert(invariant(element, element.isConstructor,
@@ -309,7 +307,7 @@
       if (element.isSynthesized) {
         if (element.isGenerativeConstructor) {
           ResolutionRegistry registry =
-              new ResolutionRegistry(compiler, _ensureTreeElements(element));
+              new ResolutionRegistry(this.target, _ensureTreeElements(element));
           ConstructorElement constructor = element.asFunctionElement();
           ConstructorElement target = constructor.definingConstructor;
           // Ensure the signature of the synthesized element is
@@ -331,7 +329,7 @@
         element.computeType(resolution);
         FunctionElementX implementation = element;
         if (element.isExternal) {
-          implementation = compiler.backend.resolveExternalFunction(element);
+          implementation = target.resolveExternalFunction(element);
         }
         return resolveMethodElementImplementation(
             implementation, implementation.node);
@@ -346,8 +344,8 @@
   /// This method should only be used by this library (or tests of
   /// this library).
   ResolverVisitor visitorFor(Element element, {bool useEnclosingScope: false}) {
-    return new ResolverVisitor(compiler, element,
-        new ResolutionRegistry(compiler, _ensureTreeElements(element)),
+    return new ResolverVisitor(resolution, element,
+        new ResolutionRegistry(target, _ensureTreeElements(element)),
         useEnclosingScope: useEnclosingScope);
   }
 
@@ -448,11 +446,11 @@
 
   void resolveRedirectionChain(ConstructorElement constructor, Spannable node) {
     ConstructorElement target = constructor;
-    InterfaceType targetType;
-    List<Element> seen = new List<Element>();
+    DartType targetType;
+    List<ConstructorElement> seen = new List<ConstructorElement>();
     bool isMalformed = false;
     // Follow the chain of redirections and check for cycles.
-    while (target.isRedirectingFactory || target.isPatched) {
+    while (target.isRedirectingFactory) {
       if (target.hasEffectiveTarget) {
         // We found a constructor that already has been processed.
         // TODO(johnniwinther): Should `effectiveTargetType` be part of the
@@ -466,12 +464,7 @@
         break;
       }
 
-      Element nextTarget;
-      if (target.isPatched) {
-        nextTarget = target.patch;
-      } else {
-        nextTarget = target.immediateRedirectionTarget;
-      }
+      Element nextTarget = target.immediateRedirectionTarget;
 
       if (seen.contains(nextTarget)) {
         reporter.reportErrorMessage(
@@ -503,16 +496,14 @@
     // substitution of the target type with respect to the factory type.
     while (!seen.isEmpty) {
       ConstructorElementX factory = seen.removeLast();
-      TreeElements treeElements = factory.treeElements;
-      assert(invariant(node, treeElements != null,
-          message: 'No TreeElements cached for $factory.'));
-      if (!factory.isPatched) {
-        FunctionExpression functionNode = factory.node;
-        RedirectingFactoryBody redirectionNode = functionNode.body;
-        DartType factoryType = treeElements.getType(redirectionNode);
-        if (!factoryType.isDynamic) {
-          targetType = targetType.substByContext(factoryType);
-        }
+      ResolvedAst resolvedAst = factory.resolvedAst;
+      assert(invariant(node, resolvedAst != null,
+          message: 'No ResolvedAst for $factory.'));
+      FunctionExpression functionNode = resolvedAst.node;
+      RedirectingFactoryBody redirectionNode = resolvedAst.body;
+      DartType factoryType = resolvedAst.elements.getType(redirectionNode);
+      if (!factoryType.isDynamic) {
+        targetType = targetType.substByContext(factoryType);
       }
       factory.setEffectiveTarget(target, targetType, isMalformed: isMalformed);
     }
@@ -545,7 +536,7 @@
         // TODO(ahe): Cache the node in cls.
         cls
             .parseNode(parsingContext)
-            .accept(new ClassSupertypeResolver(compiler, cls));
+            .accept(new ClassSupertypeResolver(resolution, cls));
         if (cls.supertypeLoadState != STATE_DONE) {
           cls.supertypeLoadState = STATE_DONE;
         }
@@ -610,8 +601,8 @@
   TreeElements resolveClass(BaseClassElementX element) {
     return _resolveTypeDeclaration(element, () {
       // TODO(johnniwinther): Store the mapping in the resolution enqueuer.
-      ResolutionRegistry registry =
-          new ResolutionRegistry(compiler, _ensureTreeElements(element));
+      ResolutionRegistry registry = new ResolutionRegistry(
+          resolution.target, _ensureTreeElements(element));
       resolveClassInternal(element, registry);
       return element.treeElements;
     });
@@ -637,10 +628,10 @@
                 loadSupertypes(element, tree);
 
                 ClassResolverVisitor visitor =
-                    new ClassResolverVisitor(compiler, element, registry);
+                    new ClassResolverVisitor(resolution, element, registry);
                 visitor.visit(tree);
                 element.resolutionState = STATE_DONE;
-                compiler.onClassResolved(element);
+                resolution.onClassResolved(element);
                 pendingClassesToBePostProcessed.add(element);
               }));
       if (element.isPatched) {
@@ -671,8 +662,8 @@
     for (MetadataAnnotation metadata in element.implementation.metadata) {
       metadata.ensureResolved(resolution);
       ConstantValue value =
-          compiler.constants.getConstantValue(metadata.constant);
-      if (!element.isProxy && compiler.isProxyConstant(value)) {
+          resolution.constants.getConstantValue(metadata.constant);
+      if (!element.isProxy && resolution.isProxyConstant(value)) {
         element.isProxy = true;
       }
     }
@@ -760,7 +751,7 @@
         // mixin application has been performed.
         // TODO(johnniwinther): Obtain the [TreeElements] for [member]
         // differently.
-        if (compiler.enqueuer.resolution.hasBeenProcessed(member)) {
+        if (resolution.enqueuer.hasBeenProcessed(member)) {
           if (member.resolvedAst.kind == ResolvedAstKind.PARSED) {
             checkMixinSuperUses(
                 member.resolvedAst.elements, mixinApplication, mixin);
@@ -1009,13 +1000,14 @@
     return reporter.withCurrentElement(element, () {
       FunctionExpression node = element.parseNode(parsingContext);
       return measure(() => SignatureResolver.analyze(
-          compiler,
+          resolution,
           element.enclosingElement.buildScope(),
           node.typeVariables,
           node.parameters,
           node.returnType,
           element,
-          new ResolutionRegistry(compiler, _ensureTreeElements(element)),
+          new ResolutionRegistry(
+              resolution.target, _ensureTreeElements(element)),
           defaultValuesError: defaultValuesError,
           createRealParameters: true));
     });
@@ -1023,17 +1015,17 @@
 
   WorldImpact resolveTypedef(TypedefElementX element) {
     if (element.isResolved) return const ResolutionImpact();
-    compiler.world.allTypedefs.add(element);
+    world.allTypedefs.add(element);
     return _resolveTypeDeclaration(element, () {
-      ResolutionRegistry registry =
-          new ResolutionRegistry(compiler, _ensureTreeElements(element));
+      ResolutionRegistry registry = new ResolutionRegistry(
+          resolution.target, _ensureTreeElements(element));
       return reporter.withCurrentElement(element, () {
         return measure(() {
           assert(element.resolutionState == STATE_NOT_STARTED);
           element.resolutionState = STATE_STARTED;
           Typedef node = element.parseNode(parsingContext);
           TypedefResolverVisitor visitor =
-              new TypedefResolverVisitor(compiler, element, registry);
+              new TypedefResolverVisitor(resolution, element, registry);
           visitor.visit(node);
           element.resolutionState = STATE_DONE;
           return registry.worldImpact;
diff --git a/pkg/compiler/lib/src/resolution/resolution_common.dart b/pkg/compiler/lib/src/resolution/resolution_common.dart
index 819c292..53d3c69 100644
--- a/pkg/compiler/lib/src/resolution/resolution_common.dart
+++ b/pkg/compiler/lib/src/resolution/resolution_common.dart
@@ -6,22 +6,18 @@
 
 import '../common.dart';
 import '../common/resolution.dart' show Resolution;
-import '../compiler.dart' show Compiler;
 import '../elements/elements.dart';
 import '../tree/tree.dart';
-
 import 'registry.dart' show ResolutionRegistry;
 import 'scope.dart' show Scope;
 import 'type_resolver.dart' show TypeResolver;
 
 class CommonResolverVisitor<R> extends Visitor<R> {
-  final Compiler compiler;
+  final Resolution resolution;
 
-  CommonResolverVisitor(Compiler this.compiler);
+  CommonResolverVisitor(this.resolution);
 
-  DiagnosticReporter get reporter => compiler.reporter;
-
-  Resolution get resolution => compiler.resolution;
+  DiagnosticReporter get reporter => resolution.reporter;
 
   R visitNode(Node node) {
     return reporter.internalError(
@@ -34,7 +30,7 @@
   R visit(Node node) => (node == null) ? null : node.accept(this);
 
   void addDeferredAction(Element element, void action()) {
-    compiler.enqueuer.resolution.addDeferredAction(element, action);
+    resolution.enqueuer.addDeferredAction(element, action);
   }
 }
 
@@ -52,9 +48,9 @@
   /// The current scope of the visitor.
   Scope get scope;
 
-  MappingVisitor(Compiler compiler, ResolutionRegistry this.registry)
-      : typeResolver = new TypeResolver(compiler),
-        super(compiler);
+  MappingVisitor(Resolution resolution, this.registry)
+      : typeResolver = new TypeResolver(resolution),
+        super(resolution);
 
   AsyncMarker get currentAsyncMarker => AsyncMarker.SYNC;
 
diff --git a/pkg/compiler/lib/src/resolution/send_structure.dart b/pkg/compiler/lib/src/resolution/send_structure.dart
index 4b6d187..b26087e 100644
--- a/pkg/compiler/lib/src/resolution/send_structure.dart
+++ b/pkg/compiler/lib/src/resolution/send_structure.dart
@@ -1504,7 +1504,7 @@
   IndexSetIfNullStructure(this.semantics);
 
   @override
-  SendStructureKind get kind => SendStructureKind.INDEX_SET;
+  SendStructureKind get kind => SendStructureKind.INDEX_SET_IF_NULL;
 
   R dispatch(SemanticSendVisitor<R, A> visitor, Send node, A arg) {
     switch (semantics.kind) {
diff --git a/pkg/compiler/lib/src/resolution/signatures.dart b/pkg/compiler/lib/src/resolution/signatures.dart
index d3f3264..eff4988 100644
--- a/pkg/compiler/lib/src/resolution/signatures.dart
+++ b/pkg/compiler/lib/src/resolution/signatures.dart
@@ -5,7 +5,7 @@
 library dart2js.resolution.signatures;
 
 import '../common.dart';
-import '../compiler.dart' show Compiler;
+import '../common/resolution.dart';
 import '../dart_types.dart';
 import '../elements/elements.dart';
 import '../elements/modelx.dart'
@@ -40,15 +40,19 @@
   bool optionalParametersAreNamed = false;
   VariableDefinitions currentDefinitions;
 
-  SignatureResolver(Compiler compiler, FunctionTypedElement enclosingElement,
-      Scope scope, ResolutionRegistry registry,
-      {this.defaultValuesError, this.createRealParameters})
+  SignatureResolver(
+      Resolution resolution,
+      FunctionTypedElement enclosingElement,
+      Scope scope,
+      ResolutionRegistry registry,
+      {this.defaultValuesError,
+      this.createRealParameters})
       : this.scope = scope,
         this.enclosingElement = enclosingElement,
         this.resolver = new ResolverVisitor(
-            compiler, enclosingElement, registry,
+            resolution, enclosingElement, registry,
             scope: scope),
-        super(compiler, registry);
+        super(resolution, registry);
 
   bool get defaultValuesAllowed => defaultValuesError == null;
 
@@ -93,7 +97,7 @@
     FormalElementX element = definition.accept(this);
     if (currentDefinitions.metadata != null) {
       element.metadataInternal =
-          compiler.resolver.resolveMetadata(element, node);
+          resolution.resolver.resolveMetadata(element, node);
     }
     currentDefinitions = null;
     return element;
@@ -111,7 +115,7 @@
       [VariableElement fieldElement]) {
     void computeFunctionType(FunctionExpression functionExpression) {
       FunctionSignature functionSignature = SignatureResolver.analyze(
-          compiler,
+          resolution,
           scope,
           functionExpression.typeVariables,
           functionExpression.parameters,
@@ -290,7 +294,7 @@
    * the parameters will only implement [FormalElement].
    */
   static FunctionSignature analyze(
-      Compiler compiler,
+      Resolution resolution,
       Scope scope,
       NodeList typeVariables,
       NodeList formalParameters,
@@ -300,7 +304,7 @@
       {MessageKind defaultValuesError,
       bool createRealParameters: false,
       bool isFunctionExpression: false}) {
-    DiagnosticReporter reporter = compiler.reporter;
+    DiagnosticReporter reporter = resolution.reporter;
 
     List<DartType> createTypeVariables(NodeList typeVariableNodes) {
       if (typeVariableNodes == null) return const <DartType>[];
@@ -329,7 +333,7 @@
     List<DartType> typeVariableTypes = createTypeVariables(typeVariables);
     scope = new FunctionSignatureBuildingScope(scope, typeVariableTypes);
     SignatureResolver visitor = new SignatureResolver(
-        compiler, element, scope, registry,
+        resolution, element, scope, registry,
         defaultValuesError: defaultValuesError,
         createRealParameters: createRealParameters);
     List<Element> parameters = const <Element>[];
@@ -341,7 +345,7 @@
           // reported. In the case of parse errors, it is possible that there
           // are formal parameters, but something else in the method failed to
           // parse. So we suppress the message about missing formals.
-          assert(invariant(element, compiler.compilationFailed));
+          assert(invariant(element, reporter.hasReportedError));
         } else {
           reporter.reportErrorMessage(element, MessageKind.MISSING_FORMALS);
         }
@@ -366,9 +370,7 @@
       returnType = element.enclosingClass.thisType;
       // Because there is no type annotation for the return type of
       // this element, we explicitly add one.
-      if (compiler.options.enableTypeAssertions) {
-        registry.registerTypeUse(new TypeUse.checkedModeCheck(returnType));
-      }
+      registry.registerTypeUse(new TypeUse.checkedModeCheck(returnType));
     } else {
       AsyncMarker asyncMarker = AsyncMarker.SYNC;
       if (isFunctionExpression) {
@@ -382,13 +384,13 @@
           returnType = visitor.resolveReturnType(returnNode);
           break;
         case AsyncMarker.SYNC_STAR:
-          returnType = compiler.coreTypes.iterableType();
+          returnType = resolution.coreTypes.iterableType();
           break;
         case AsyncMarker.ASYNC:
-          returnType = compiler.coreTypes.futureType();
+          returnType = resolution.coreTypes.futureType();
           break;
         case AsyncMarker.ASYNC_STAR:
-          returnType = compiler.coreTypes.streamType();
+          returnType = resolution.coreTypes.streamType();
           break;
       }
     }
diff --git a/pkg/compiler/lib/src/resolution/tree_elements.dart b/pkg/compiler/lib/src/resolution/tree_elements.dart
index 1e52fca..974981c 100644
--- a/pkg/compiler/lib/src/resolution/tree_elements.dart
+++ b/pkg/compiler/lib/src/resolution/tree_elements.dart
@@ -139,7 +139,7 @@
   /// Map from nodes to native data.
   Map<Node, dynamic> _nativeData;
 
-  final int hashCode = ++_hashCodeCounter;
+  final int hashCode = _hashCodeCounter = (_hashCodeCounter + 1).toUnsigned(30);
   static int _hashCodeCounter = 0;
 
   TreeElementMapping(this.analyzedElement);
diff --git a/pkg/compiler/lib/src/resolution/type_resolver.dart b/pkg/compiler/lib/src/resolution/type_resolver.dart
index 9837a09..c1dbcfb 100644
--- a/pkg/compiler/lib/src/resolution/type_resolver.dart
+++ b/pkg/compiler/lib/src/resolution/type_resolver.dart
@@ -6,8 +6,6 @@
 
 import '../common.dart';
 import '../common/resolution.dart' show Feature, Resolution;
-import '../compiler.dart' show Compiler;
-import '../dart_backend/dart_backend.dart' show DartBackend;
 import '../dart_types.dart';
 import '../elements/elements.dart'
     show
@@ -18,25 +16,24 @@
         ErroneousElement,
         PrefixElement,
         TypedefElement,
-        TypeDeclarationElement,
         TypeVariableElement;
 import '../elements/modelx.dart' show ErroneousElementX;
+import '../resolution/resolution.dart';
 import '../tree/tree.dart';
 import '../util/util.dart' show Link;
-
 import 'members.dart' show lookupInScope;
 import 'registry.dart' show ResolutionRegistry;
 import 'resolution_common.dart' show MappingVisitor;
 import 'scope.dart' show Scope;
 
 class TypeResolver {
-  final Compiler compiler;
+  final Resolution resolution;
 
-  TypeResolver(this.compiler);
+  TypeResolver(this.resolution);
 
-  DiagnosticReporter get reporter => compiler.reporter;
-
-  Resolution get resolution => compiler.resolution;
+  ResolverTask get resolver => resolution.resolver;
+  DiagnosticReporter get reporter => resolution.reporter;
+  Types get types => resolution.types;
 
   /// Tries to resolve the type name as an element.
   Element resolveTypeName(
@@ -50,12 +47,7 @@
         // The receiver is a prefix. Lookup in the imported members.
         PrefixElement prefix = prefixElement;
         element = prefix.lookupLocalMember(typeName.source);
-        // TODO(17260, sigurdm): The test for DartBackend is there because
-        // dart2dart outputs malformed types with prefix.
-        if (element != null &&
-            prefix.isDeferred &&
-            deferredIsMalformed &&
-            compiler.backend is! DartBackend) {
+        if (element != null && prefix.isDeferred && deferredIsMalformed) {
           element = new ErroneousElementX(MessageKind.DEFERRED_TYPE_ANNOTATION,
               {'node': typeName}, element.name, element);
         }
@@ -167,7 +159,7 @@
         ClassElement cls = element;
         // TODO(johnniwinther): [ensureClassWillBeResolvedInternal] should imply
         // [computeType].
-        compiler.resolver.ensureClassWillBeResolvedInternal(cls);
+        resolver.ensureClassWillBeResolvedInternal(cls);
         cls.computeType(resolution);
         List<DartType> arguments = <DartType>[];
         bool hasTypeArgumentMismatch =
@@ -240,7 +232,7 @@
   void checkTypeVariableBounds(TypeAnnotation node, GenericType type) {
     void checkTypeVariableBound(_, DartType typeArgument,
         TypeVariableType typeVariable, DartType bound) {
-      if (!compiler.types.isSubtype(typeArgument, bound)) {
+      if (!types.isSubtype(typeArgument, bound)) {
         reporter.reportWarningMessage(
             node, MessageKind.INVALID_TYPE_VARIABLE_BOUND, {
           'typeVariable': typeVariable,
@@ -250,9 +242,8 @@
         });
       }
     }
-    ;
 
-    compiler.types.checkTypeVariableBounds(type, checkTypeVariableBound);
+    types.checkTypeVariableBounds(type, checkTypeVariableBound);
   }
 
   /**
diff --git a/pkg/compiler/lib/src/resolution/typedefs.dart b/pkg/compiler/lib/src/resolution/typedefs.dart
index cee72df..7f18141 100644
--- a/pkg/compiler/lib/src/resolution/typedefs.dart
+++ b/pkg/compiler/lib/src/resolution/typedefs.dart
@@ -4,8 +4,10 @@
 
 library dart2js.resolution.typedefs;
 
+import 'dart:developer';
+
 import '../common.dart';
-import '../compiler.dart' show Compiler;
+import '../common/resolution.dart';
 import '../dart_types.dart';
 import '../elements/elements.dart'
     show FunctionSignature, TypedefElement, TypeVariableElement;
@@ -21,9 +23,9 @@
 class TypedefResolverVisitor extends TypeDefinitionVisitor {
   TypedefElementX get element => enclosingElement;
 
-  TypedefResolverVisitor(Compiler compiler, TypedefElement typedefElement,
+  TypedefResolverVisitor(Resolution resolution, TypedefElement typedefElement,
       ResolutionRegistry registry)
-      : super(compiler, typedefElement, registry);
+      : super(resolution, typedefElement, registry);
 
   visitTypedef(Typedef node) {
     element.computeType(resolution);
@@ -31,7 +33,7 @@
     resolveTypeVariableBounds(node.typeParameters);
 
     FunctionSignature signature = SignatureResolver.analyze(
-        compiler,
+        resolution,
         scope,
         null /* typeVariables */,
         node.formals,
@@ -67,7 +69,7 @@
   Link<TypeVariableElement> seenTypeVariables =
       const Link<TypeVariableElement>();
 
-  TypedefCyclicVisitor(this.reporter, TypedefElement this.element);
+  TypedefCyclicVisitor(this.reporter, this.element);
 
   visitType(DartType type, _) {
     // Do nothing.
@@ -115,7 +117,9 @@
       seenTypedefs = seenTypedefs.prepend(typedefElement);
       seenTypedefsCount++;
       type.visitChildren(this, null);
-      typedefElement.aliasCache.accept(this, null);
+      if (!typedefElement.isMalformed) {
+        typedefElement.aliasCache.accept(this, null);
+      }
       seenTypedefs = seenTypedefs.tail;
       seenTypedefsCount--;
     }
diff --git a/pkg/compiler/lib/src/resolution/variables.dart b/pkg/compiler/lib/src/resolution/variables.dart
index c5609a8..28d5372 100644
--- a/pkg/compiler/lib/src/resolution/variables.dart
+++ b/pkg/compiler/lib/src/resolution/variables.dart
@@ -5,7 +5,7 @@
 library dart2js.resolution.variables;
 
 import '../common.dart';
-import '../compiler.dart' show Compiler;
+import '../common/resolution.dart';
 import '../elements/modelx.dart' show LocalVariableElementX, VariableList;
 import '../tree/tree.dart';
 import '../universe/use.dart' show TypeUse;
@@ -22,8 +22,8 @@
   VariableList variables;
 
   VariableDefinitionsVisitor(
-      Compiler compiler, this.definitions, this.resolver, this.variables)
-      : super(compiler) {}
+      Resolution resolution, this.definitions, this.resolver, this.variables)
+      : super(resolution);
 
   ResolutionRegistry get registry => resolver.registry;
 
@@ -45,7 +45,7 @@
     // The variable is initialized to null.
     // TODO(johnniwinther): Register a feature instead.
     registry.registerTypeUse(
-        new TypeUse.instantiation(compiler.coreTypes.nullType));
+        new TypeUse.instantiation(resolution.coreTypes.nullType));
     if (definitions.modifiers.isConst) {
       if (resolver.inLoopVariable) {
         reporter.reportErrorMessage(node, MessageKind.CONST_LOOP_VARIABLE);
@@ -68,9 +68,9 @@
       resolver.defineLocalVariable(link.head, element);
       resolver.addToScope(element);
       if (definitions.modifiers.isConst) {
-        compiler.enqueuer.resolution.addDeferredAction(element, () {
+        addDeferredAction(element, () {
           element.constant =
-              compiler.resolver.constantCompiler.compileConstant(element);
+              resolution.resolver.constantCompiler.compileConstant(element);
         });
       }
     }
diff --git a/pkg/compiler/lib/src/serialization/element_serialization.dart b/pkg/compiler/lib/src/serialization/element_serialization.dart
index d51c67a..3a63bbc 100644
--- a/pkg/compiler/lib/src/serialization/element_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/element_serialization.dart
@@ -12,7 +12,11 @@
 import '../diagnostics/messages.dart';
 import '../elements/elements.dart';
 import '../elements/modelx.dart'
-    show DeferredLoaderGetterElementX, ErroneousElementX;
+    show
+        DeferredLoaderGetterElementX,
+        ErroneousElementX,
+        WarnOnUseElementX,
+        WrappedMessage;
 import 'constant_serialization.dart';
 import 'keys.dart';
 import 'modelz.dart';
@@ -55,6 +59,7 @@
   PREFIX,
   DEFERRED_LOAD_LIBRARY,
   LOCAL_VARIABLE,
+  WARN_ON_USE,
   EXTERNAL_LIBRARY,
   EXTERNAL_LIBRARY_MEMBER,
   EXTERNAL_CLASS_MEMBER,
@@ -84,6 +89,7 @@
   const ImportSerializer(),
   const ExportSerializer(),
   const LocalVariableSerializer(),
+  const WarnOnUseSerializer(),
 ];
 
 /// Interface for a function that can serialize a set of element kinds.
@@ -216,12 +222,7 @@
     encoder.setElement(Key.ENCLOSING, element.enclosingElement);
     encoder.setString(Key.NAME, element.name);
     encoder.setEnum(Key.MESSAGE_KIND, element.messageKind);
-    if (element.messageArguments.isNotEmpty) {
-      MapEncoder mapEncoder = encoder.createMap(Key.ARGUMENTS);
-      element.messageArguments.forEach((String key, var value) {
-        mapEncoder.setString(key, Message.convertToString(value));
-      });
-    }
+    serializeMessageArguments(encoder, Key.ARGUMENTS, element.messageArguments);
   }
 }
 
@@ -292,8 +293,52 @@
     encoder.setElements(Key.IMPORTS, getImports(element));
     encoder.setElements(Key.EXPORTS, element.exports);
 
-    encoder.setElements(Key.IMPORT_SCOPE, getImportedElements(element));
+    List<Element> importedElements = getImportedElements(element);
+    encoder.setElements(Key.IMPORT_SCOPE, importedElements);
     encoder.setElements(Key.EXPORT_SCOPE, getExportedElements(element));
+
+    Map<Element, Iterable<ImportElement>> importsForMap =
+        <Element, Iterable<ImportElement>>{};
+
+    /// Map imports for [importedElement] in importsForMap.
+    ///
+    /// Imports are mapped to [AbstractFieldElement] which are not serialized
+    /// so we use getter (or setter if there is no getter) as the key.
+    void addImportsForElement(Element importedElement) {
+      Element key = importedElement;
+      if (importedElement.isDeferredLoaderGetter) {
+        // Use [importedElement].
+      } else if (importedElement.isGetter) {
+        GetterElement getter = importedElement;
+        importedElement = getter.abstractField;
+      } else if (importedElement.isSetter) {
+        SetterElement setter = importedElement;
+        if (setter.getter != null) {
+          return;
+        }
+        importedElement = setter.abstractField;
+      }
+      importsForMap.putIfAbsent(
+          key, () => element.getImportsFor(importedElement));
+    }
+
+    for (ImportElement import in getImports(element)) {
+      if (import.prefix != null) {
+        Set<Element> importedElements = new Set<Element>();
+        import.prefix.forEachLocalMember(
+            SerializerUtil.flattenElements(importedElements));
+        importedElements.forEach(addImportsForElement);
+      }
+    }
+    importedElements.forEach(addImportsForElement);
+
+    ListEncoder importsForEncoder = encoder.createList(Key.IMPORTS_FOR);
+    importsForMap
+        .forEach((Element importedElement, Iterable<ImportElement> imports) {
+      ObjectEncoder objectEncoder = importsForEncoder.createObject();
+      objectEncoder.setElement(Key.ELEMENT, importedElement);
+      objectEncoder.setElements(Key.IMPORTS, imports);
+    });
   }
 }
 
@@ -454,6 +499,8 @@
                 .computeEffectiveTargetType(element.enclosingClass.thisType));
         encoder.setElement(Key.IMMEDIATE_REDIRECTION_TARGET,
             element.immediateRedirectionTarget);
+        encoder.setBool(Key.EFFECTIVE_TARGET_IS_MALFORMED,
+            element.isEffectiveTargetMalformed);
         if (element.redirectionDeferredPrefix != null) {
           encoder.setElement(Key.PREFIX, element.redirectionDeferredPrefix);
         }
@@ -544,6 +591,8 @@
     if (element.isFunction) {
       encoder.setBool(Key.IS_OPERATOR, element.isOperator);
       encoder.setEnum(Key.ASYNC_MARKER, element.asyncMarker);
+    } else if (element.isGetter) {
+      encoder.setEnum(Key.ASYNC_MARKER, element.asyncMarker);
     }
     SerializerUtil.serializeParentRelation(element, encoder);
     encoder.setBool(Key.IS_EXTERNAL, element.isExternal);
@@ -554,6 +603,7 @@
       encoder.setElement(
           Key.EXECUTABLE_CONTEXT, localFunction.executableContext);
     }
+    encoder.setTypes(Key.TYPE_VARIABLES, element.typeVariables);
   }
 }
 
@@ -605,7 +655,7 @@
   const ParameterSerializer();
 
   SerializedElementKind getSerializedKind(Element element) {
-    if (element.isParameter) {
+    if (element.isRegularParameter) {
       return SerializedElementKind.PARAMETER;
     } else if (element.isInitializingFormal) {
       return SerializedElementKind.INITIALIZING_FORMAL;
@@ -721,6 +771,9 @@
     encoder.setElement(Key.LIBRARY, element.library);
     encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
     encoder.setBool(Key.IS_DEFERRED, element.isDeferred);
+    Set<Element> members = new Set<Element>();
+    element.forEachLocalMember(SerializerUtil.flattenElements(members));
+    encoder.setElements(Key.MEMBERS, members);
     if (element.isDeferred) {
       encoder.setElement(Key.IMPORT, element.deferredImport);
       encoder.setElement(Key.GETTER, element.loadLibrary);
@@ -744,6 +797,25 @@
   }
 }
 
+class WarnOnUseSerializer implements ElementSerializer {
+  const WarnOnUseSerializer();
+
+  SerializedElementKind getSerializedKind(Element element) {
+    if (element.isWarnOnUse) {
+      return SerializedElementKind.WARN_ON_USE;
+    }
+    return null;
+  }
+
+  void serialize(WarnOnUseElementX element, ObjectEncoder encoder,
+      SerializedElementKind kind) {
+    encoder.setElement(Key.ENCLOSING, element.enclosingElement);
+    encoder.setElement(Key.ELEMENT, element.wrappedElement);
+    serializeWrappedMessage(encoder, Key.WARNING, element.warning);
+    serializeWrappedMessage(encoder, Key.INFO, element.info);
+  }
+}
+
 /// Utility class for deserializing [Element]s.
 ///
 /// This is used by the [Deserializer].
@@ -762,13 +834,8 @@
         String name = decoder.getString(Key.NAME);
         MessageKind messageKind =
             decoder.getEnum(Key.MESSAGE_KIND, MessageKind.values);
-        Map<String, String> arguments = <String, String>{};
-        MapDecoder mapDecoder = decoder.getMap(Key.ARGUMENTS, isOptional: true);
-        if (mapDecoder != null) {
-          mapDecoder.forEachKey((String key) {
-            arguments[key] = mapDecoder.getString(key);
-          });
-        }
+        Map<String, String> arguments =
+            deserializeMessageArguments(decoder, Key.ARGUMENTS);
         return new ErroneousElementX(messageKind, arguments, name, enclosing);
       case SerializedElementKind.LIBRARY:
         return new LibraryElementZ(decoder);
@@ -839,6 +906,13 @@
         return new DeferredLoaderGetterElementX(decoder.getElement(Key.PREFIX));
       case SerializedElementKind.LOCAL_VARIABLE:
         return new LocalVariableElementZ(decoder);
+      case SerializedElementKind.WARN_ON_USE:
+        Element enclosing = decoder.getElement(Key.ENCLOSING);
+        Element element = decoder.getElement(Key.ELEMENT);
+        WrappedMessage warning =
+            deserializeWrappedMessage(decoder, Key.WARNING);
+        WrappedMessage info = deserializeWrappedMessage(decoder, Key.INFO);
+        return new WarnOnUseElementX(warning, info, enclosing, element);
       case SerializedElementKind.EXTERNAL_LIBRARY:
       case SerializedElementKind.EXTERNAL_LIBRARY_MEMBER:
       case SerializedElementKind.EXTERNAL_CLASS_MEMBER:
diff --git a/pkg/compiler/lib/src/serialization/equivalence.dart b/pkg/compiler/lib/src/serialization/equivalence.dart
index a7c08b5..6cb175c 100644
--- a/pkg/compiler/lib/src/serialization/equivalence.dart
+++ b/pkg/compiler/lib/src/serialization/equivalence.dart
@@ -516,6 +516,20 @@
             element1, element2, 'name', element1.name, element2.name) &&
         visit(element1.library, element2.library);
   }
+
+  @override
+  bool visitErroneousElement(
+      ErroneousElement element1, ErroneousElement element2) {
+    return strategy.test(element1, element2, 'messageKind',
+        element1.messageKind, element2.messageKind);
+  }
+
+  @override
+  bool visitWarnOnUseElement(
+      WarnOnUseElement element1, WarnOnUseElement element2) {
+    return strategy.testElements(element1, element2, 'wrappedElement',
+        element1.wrappedElement, element2.wrappedElement);
+  }
 }
 
 /// Visitor that checks for equivalence of [DartType]s.
@@ -562,7 +576,9 @@
   @override
   bool visitTypeVariableType(TypeVariableType type, TypeVariableType other) {
     return strategy.testElements(
-        type, other, 'element', type.element, other.element);
+            type, other, 'element', type.element, other.element) &&
+        strategy.test(type, other, 'is MethodTypeVariableType',
+            type is MethodTypeVariableType, other is MethodTypeVariableType);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/serialization/keys.dart b/pkg/compiler/lib/src/serialization/keys.dart
index 2c70168..0fa501a 100644
--- a/pkg/compiler/lib/src/serialization/keys.dart
+++ b/pkg/compiler/lib/src/serialization/keys.dart
@@ -29,6 +29,8 @@
   static const Key DYNAMIC_USES = const Key('dynamic-uses');
   static const Key EFFECTIVE_TARGET = const Key('effectiveTarget');
   static const Key EFFECTIVE_TARGET_TYPE = const Key('effectiveTargetType');
+  static const Key EFFECTIVE_TARGET_IS_MALFORMED =
+      const Key('effectiveTargetIsMalformed');
   static const Key ELEMENT = const Key('element');
   static const Key ELEMENTS = const Key('elements');
   static const Key ENCLOSING = const Key('enclosing');
@@ -49,9 +51,11 @@
   static const Key IMPACTS = const Key('impacts');
   static const Key IMPORT = const Key('import');
   static const Key IMPORTS = const Key('imports');
+  static const Key IMPORTS_FOR = const Key('importsFor');
   static const Key IMPORT_SCOPE = const Key('import-scope');
-  static const Key INTERFACES = const Key('interfaces');
   static const Key INDEX = const Key('index');
+  static const Key INFO = const Key('info');
+  static const Key INTERFACES = const Key('interfaces');
   static const Key IS_ABSTRACT = const Key('isAbstract');
   static const Key IS_BREAK_TARGET = const Key('isBreakTarget');
   static const Key IS_CONST = const Key('isConst');
@@ -61,6 +65,8 @@
   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_METHOD_TYPE_VARIABLE_TYPE =
+      const Key('isMethodTypeVariableType');
   static const Key IS_NAMED = const Key('isNamed');
   static const Key IS_OPERATOR = const Key('isOperator');
   static const Key IS_OPTIONAL = const Key('isOptional');
@@ -111,6 +117,7 @@
   static const Key SEMANTICS = const Key('semantics');
   static const Key SEND_STRUCTURE = const Key('sendStructure');
   static const Key SETTER = const Key('setter');
+  static const Key SOURCE_SPAN = const Key('sourceSpan');
   static const Key STATIC_USES = const Key('static-uses');
   static const Key SUB_KIND = const Key('subKind');
   static const Key SUPERTYPE = const Key('supertype');
@@ -128,6 +135,7 @@
   static const Key URI = const Key('uri');
   static const Key VALUE = const Key('value');
   static const Key VALUES = const Key('values');
+  static const Key WARNING = const Key('warning');
 
   final String name;
 
diff --git a/pkg/compiler/lib/src/serialization/modelz.dart b/pkg/compiler/lib/src/serialization/modelz.dart
index 4c932f3..55ab23e 100644
--- a/pkg/compiler/lib/src/serialization/modelz.dart
+++ b/pkg/compiler/lib/src/serialization/modelz.dart
@@ -196,7 +196,7 @@
     String setterName = '$name,=';
     bool hasSetterId = members.containsKey(setterName);
     Element element;
-    Element setterElement;
+    SetterElement setterElement;
     if (!hasId && !hasSetterId) {
       _lookupCache[name] = null;
       return null;
@@ -236,7 +236,12 @@
     Map<String, Element> setters = <String, Element>{};
     for (Element element in elements) {
       String name = element.name;
-      if (element.isGetter) {
+      if (element.isDeferredLoaderGetter) {
+        // Store directly.
+        // TODO(johnniwinther): Should modelx be normalized to put `loadLibrary`
+        // in an [AbstractFieldElement] instead?
+        _lookupMap[name] = element;
+      } else if (element.isGetter) {
         accessorNames.add(name);
         getters[name] = element;
         // Inserting [element] here to ensure insert order of [name].
@@ -329,7 +334,18 @@
   final GetterElementZ getter;
   final SetterElementZ setter;
 
-  AbstractFieldElementZ(this.name, this.getter, this.setter) {
+  factory AbstractFieldElementZ(
+      String name, GetterElement getter, SetterElement setter) {
+    if (getter?.abstractField != null) {
+      return getter.abstractField;
+    } else if (setter?.abstractField != null) {
+      return setter.abstractField;
+    } else {
+      return new AbstractFieldElementZ._(name, getter, setter);
+    }
+  }
+
+  AbstractFieldElementZ._(this.name, this.getter, this.setter) {
     if (getter != null) {
       getter.abstractField = this;
       getter.setter = setter;
@@ -393,6 +409,7 @@
   List<ExportElement> _exports;
   ListedContainer _exportsMap;
   ListedContainer _importsMap;
+  Map<Element, List<ImportElement>> _importsFor;
 
   LibraryElementZ(ObjectDecoder decoder) : super(decoder);
 
@@ -492,7 +509,28 @@
 
   void _ensureImports() {
     if (_importsMap == null) {
-      _importsMap = new ListedContainer(_decoder.getElements(Key.IMPORT_SCOPE));
+      _importsMap = new ListedContainer(
+          _decoder.getElements(Key.IMPORT_SCOPE, isOptional: true));
+      _importsFor = <Element, List<ImportElement>>{};
+
+      ListDecoder importsDecoder = _decoder.getList(Key.IMPORTS_FOR);
+      for (int index = 0; index < importsDecoder.length; index++) {
+        ObjectDecoder objectDecoder = importsDecoder.getObject(index);
+        Element key = objectDecoder.getElement(Key.ELEMENT);
+        List<ImportElement> imports =
+            objectDecoder.getElements(Key.IMPORTS, isOptional: true);
+
+        // Imports are mapped to [AbstractFieldElement] which are not serialized
+        // so we use getter (or setter if there is no getter) as the key.
+        Element importedElement = key;
+        if (key.isDeferredLoaderGetter) {
+          // Use as [importedElement].
+        } else if (key.isAccessor) {
+          AccessorElement accessor = key;
+          importedElement = accessor.abstractField;
+        }
+        _importsFor[importedElement] = imports;
+      }
     }
   }
 
@@ -504,9 +542,8 @@
 
   @override
   Iterable<ImportElement> getImportsFor(Element element) {
-    // TODO(johnniwinther): Serialize this to support deferred access to
-    // serialized entities.
-    return <ImportElement>[];
+    _ensureImports();
+    return _importsFor[element] ?? const <ImportElement>[];
   }
 
   String toString() {
@@ -788,6 +825,8 @@
           namedParameterTypes.add(parameter.type);
         }
       }
+      List<DartType> typeVariables =
+          _decoder.getTypes(Key.TYPE_VARIABLES, isOptional: true);
 
       FunctionType type = new FunctionType(
           this,
@@ -797,6 +836,7 @@
           namedParameters,
           namedParameterTypes);
       _functionSignature = new FunctionSignatureX(
+          typeVariables: typeVariables,
           requiredParameters: requiredParameters,
           requiredParameterCount: requiredParameterCount,
           optionalParameters: optionalParameters,
@@ -1295,9 +1335,10 @@
 }
 
 class RedirectingFactoryConstructorElementZ extends ConstructorElementZ {
-  InterfaceType _effectiveTargetType;
+  DartType _effectiveTargetType;
   ConstructorElement _immediateRedirectionTarget;
   PrefixElement _redirectionDeferredPrefix;
+  bool _effectiveTargetIsMalformed;
 
   RedirectingFactoryConstructorElementZ(ObjectDecoder decoder) : super(decoder);
 
@@ -1314,12 +1355,20 @@
       if (_effectiveTarget == null) {
         _effectiveTarget = this;
         _effectiveTargetType = enclosingClass.thisType;
+        _effectiveTargetIsMalformed = false;
       } else {
         _effectiveTargetType = _decoder.getType(Key.EFFECTIVE_TARGET_TYPE);
+        _effectiveTargetIsMalformed =
+            _decoder.getBool(Key.EFFECTIVE_TARGET_IS_MALFORMED);
       }
     }
   }
 
+  bool get isEffectiveTargetMalformed {
+    _ensureEffectiveTarget();
+    return _effectiveTargetIsMalformed;
+  }
+
   @override
   ConstructorElement get effectiveTarget {
     _ensureEffectiveTarget();
@@ -1327,7 +1376,7 @@
   }
 
   @override
-  InterfaceType computeEffectiveTargetType(InterfaceType newType) {
+  DartType computeEffectiveTargetType(InterfaceType newType) {
     _ensureEffectiveTarget();
     return _effectiveTargetType.substByContext(newType);
   }
@@ -1497,6 +1546,8 @@
 
 abstract class MemberElementMixin
     implements DeserializedElementZ, MemberElement {
+  final List<FunctionElement> nestedClosures = <FunctionElement>[];
+
   @override
   MemberElement get memberContext => this;
 
@@ -1504,10 +1555,12 @@
   Name get memberName => new Name(name, library);
 
   @override
-  List<FunctionElement> get nestedClosures => <FunctionElement>[];
+  bool get isInjected => _decoder.getBool(Key.IS_INJECTED);
 
   @override
-  bool get isInjected => _decoder.getBool(Key.IS_INJECTED);
+  void forgetElement() {
+    nestedClosures.clear();
+  }
 }
 
 abstract class FieldElementZ extends DeserializedElementZ
@@ -1634,6 +1687,9 @@
   Element get enclosingElement => executableContext;
 
   @override
+  Element get enclosingClass => memberContext.enclosingClass;
+
+  @override
   ExecutableElement get executableContext {
     if (_executableContext == null) {
       _executableContext = _decoder.getElement(Key.EXECUTABLE_CONTEXT);
@@ -1712,7 +1768,9 @@
   bool get isAbstract => _decoder.getBool(Key.IS_ABSTRACT);
 
   @override
-  AsyncMarker get asyncMarker => AsyncMarker.SYNC;
+  AsyncMarker get asyncMarker {
+    return _decoder.getEnum(Key.ASYNC_MARKER, AsyncMarker.values);
+  }
 }
 
 class TopLevelGetterElementZ extends GetterElementZ with LibraryMemberMixin {
@@ -1871,7 +1929,7 @@
 class TypeVariableElementZ extends DeserializedElementZ
     with AnalyzableElementMixin, AstElementMixinZ, TypedElementMixin
     implements TypeVariableElement {
-  TypeDeclarationElement _typeDeclaration;
+  GenericElement _typeDeclaration;
   TypeVariableType _type;
   DartType _bound;
   Name _memberName;
@@ -1908,7 +1966,7 @@
   int get index => _decoder.getInt(Key.INDEX);
 
   @override
-  TypeDeclarationElement get typeDeclaration {
+  GenericElement get typeDeclaration {
     if (_typeDeclaration == null) {
       _typeDeclaration = _decoder.getElement(Key.TYPE_DECLARATION);
     }
@@ -2259,12 +2317,16 @@
   bool _isDeferred;
   ImportElement _deferredImport;
   GetterElement _loadLibrary;
+  ListedContainer _members;
 
   PrefixElementZ(ObjectDecoder decoder) : super(decoder);
 
   @override
   accept(ElementVisitor visitor, arg) => visitor.visitPrefixElement(this, arg);
 
+  @override
+  bool get isTopLevel => false;
+
   void _ensureDeferred() {
     if (_isDeferred == null) {
       _isDeferred = _decoder.getBool(Key.IS_DEFERRED);
@@ -2295,9 +2357,23 @@
   @override
   ElementKind get kind => ElementKind.PREFIX;
 
+  void _ensureMembers() {
+    if (_members == null) {
+      _members = new ListedContainer(
+          _decoder.getElements(Key.MEMBERS, isOptional: true));
+    }
+  }
+
   @override
   Element lookupLocalMember(String memberName) {
-    return _unsupported('lookupLocalMember');
+    _ensureMembers();
+    return _members.lookup(memberName);
+  }
+
+  @override
+  void forEachLocalMember(void f(Element member)) {
+    _ensureMembers();
+    _members.forEach(f);
   }
 }
 
diff --git a/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart b/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart
index b5d6cae..bce66ac 100644
--- a/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart
@@ -166,21 +166,25 @@
         serializeLabelDefinition(labelDefinition, list.createObject());
       }
     }
+
     if (element is FunctionElement) {
-      FunctionElement function = element;
-      function.functionSignature.forEachParameter((ParameterElement parameter) {
-        ParameterElement parameterImpl = parameter.implementation;
-        // TODO(johnniwinther): Should we support element->node mapping as well?
-        getNodeDataEncoder(parameterImpl.node)
-            .setElement(PARAMETER_NODE, parameter);
-        if (parameter.initializer != null) {
-          getNodeDataEncoder(parameterImpl.initializer)
-              .setElement(PARAMETER_INITIALIZER, parameter);
-        }
-      });
+      serializeParameterNodes(element);
     }
   }
 
+  void serializeParameterNodes(FunctionElement function) {
+    function.functionSignature.forEachParameter((ParameterElement parameter) {
+      ParameterElement parameterImpl = parameter.implementation;
+      // TODO(johnniwinther): Should we support element->node mapping as well?
+      getNodeDataEncoder(parameterImpl.node)
+          .setElement(PARAMETER_NODE, parameter);
+      if (parameter.initializer != null) {
+        getNodeDataEncoder(parameterImpl.initializer)
+            .setElement(PARAMETER_INITIALIZER, parameter);
+      }
+    });
+  }
+
   /// Serialize [target] into [encoder].
   void serializeJumpTarget(JumpTarget jumpTarget, ObjectEncoder encoder) {
     encoder.setElement(Key.EXECUTABLE_CONTEXT, jumpTarget.executableContext);
@@ -318,6 +322,7 @@
     if (function != null && function.isFunction && function.isLocal) {
       // Mark root nodes of local functions; these need their own ResolvedAst.
       getNodeDataEncoder(node).setElement(Key.FUNCTION, function);
+      serializeParameterNodes(function);
     }
   }
 }
diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart
index 1b97c3d..4230ca0 100644
--- a/pkg/compiler/lib/src/serialization/serialization.dart
+++ b/pkg/compiler/lib/src/serialization/serialization.dart
@@ -692,6 +692,7 @@
         /// Helper used to check that external references are serialized by
         /// the right kind.
         bool verifyElement(var found, var expected) {
+          if (found == null) return false;
           found = found.declaration;
           if (found == expected) return true;
           if (found.isAbstractField && expected.isGetter) {
diff --git a/pkg/compiler/lib/src/serialization/serialization_util.dart b/pkg/compiler/lib/src/serialization/serialization_util.dart
index 1e40000..4883adb 100644
--- a/pkg/compiler/lib/src/serialization/serialization_util.dart
+++ b/pkg/compiler/lib/src/serialization/serialization_util.dart
@@ -7,7 +7,9 @@
 import '../common.dart';
 import '../constants/expressions.dart';
 import '../dart_types.dart';
+import '../diagnostics/messages.dart';
 import '../elements/elements.dart';
+import '../elements/modelx.dart' show WrappedMessage;
 import '../resolution/access_semantics.dart';
 import '../resolution/operators.dart';
 import '../resolution/send_structure.dart';
@@ -526,3 +528,63 @@
   }
   return element;
 }
+
+void serializeMessageArguments(
+    ObjectEncoder encoder, Key key, Map<String, dynamic> messageArguments) {
+  if (messageArguments.isNotEmpty) {
+    MapEncoder mapEncoder = encoder.createMap(Key.ARGUMENTS);
+    messageArguments.forEach((String key, var value) {
+      mapEncoder.setString(key, Message.convertToString(value));
+    });
+  }
+}
+
+Map<String, String> deserializeMessageArguments(
+    ObjectDecoder decoder, Key key) {
+  Map<String, String> arguments = <String, String>{};
+  MapDecoder mapDecoder = decoder.getMap(key, isOptional: true);
+  if (mapDecoder != null) {
+    mapDecoder.forEachKey((String key) {
+      arguments[key] = mapDecoder.getString(key);
+    });
+  }
+  return arguments;
+}
+
+void serializeSourceSpan(ObjectEncoder encoder, SourceSpan sourceSpan) {
+  encoder.setUri(Key.URI, sourceSpan.uri, sourceSpan.uri);
+  encoder.setInt(Key.OFFSET, sourceSpan.begin);
+  encoder.setInt(Key.LENGTH, sourceSpan.end - sourceSpan.begin);
+}
+
+SourceSpan deserializeSourceSpan(ObjectDecoder decoder) {
+  Uri uri = decoder.getUri(Key.URI);
+  int offset = decoder.getInt(Key.OFFSET);
+  int length = decoder.getInt(Key.LENGTH);
+  return new SourceSpan(uri, offset, offset + length);
+}
+
+void serializeWrappedMessage(
+    ObjectEncoder encoder, Key key, WrappedMessage message) {
+  ObjectEncoder object = encoder.createObject(key);
+  if (message.sourceSpan != null) {
+    serializeSourceSpan(
+        object.createObject(Key.SOURCE_SPAN), message.sourceSpan);
+  }
+  object.setEnum(Key.KIND, message.messageKind);
+  serializeMessageArguments(object, Key.ARGUMENTS, message.messageArguments);
+}
+
+WrappedMessage deserializeWrappedMessage(ObjectDecoder decoder, Key key) {
+  ObjectDecoder object = decoder.getObject(key);
+  SourceSpan sourceSpan;
+  ObjectDecoder sourceSpanDecoder =
+      object.getObject(Key.SOURCE_SPAN, isOptional: true);
+  if (sourceSpanDecoder != null) {
+    sourceSpan = deserializeSourceSpan(sourceSpanDecoder);
+  }
+  MessageKind messageKind = object.getEnum(Key.KIND, MessageKind.values);
+  Map<String, dynamic> messageArguments =
+      deserializeMessageArguments(object, Key.ARGUMENTS);
+  return new WrappedMessage(sourceSpan, messageKind, messageArguments);
+}
diff --git a/pkg/compiler/lib/src/serialization/type_serialization.dart b/pkg/compiler/lib/src/serialization/type_serialization.dart
index 24a46ae..ed94ade 100644
--- a/pkg/compiler/lib/src/serialization/type_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/type_serialization.dart
@@ -5,6 +5,7 @@
 library dart2js.serialization.types;
 
 import '../dart_types.dart';
+import '../elements/elements.dart';
 import 'serialization.dart';
 import 'keys.dart';
 
@@ -24,6 +25,8 @@
 
   void visitTypeVariableType(TypeVariableType type, ObjectEncoder encoder) {
     encoder.setElement(Key.ELEMENT, type.element);
+    encoder.setBool(
+        Key.IS_METHOD_TYPE_VARIABLE_TYPE, type is MethodTypeVariableType);
   }
 
   void visitFunctionType(FunctionType type, ObjectEncoder encoder) {
@@ -76,7 +79,11 @@
             decoder.getStrings(Key.NAMED_PARAMETERS, isOptional: true),
             decoder.getTypes(Key.NAMED_PARAMETER_TYPES, isOptional: true));
       case TypeKind.TYPE_VARIABLE:
-        return new TypeVariableType(decoder.getElement(Key.ELEMENT));
+        TypeVariableElement element = decoder.getElement(Key.ELEMENT);
+        if (decoder.getBool(Key.IS_METHOD_TYPE_VARIABLE_TYPE)) {
+          return new MethodTypeVariableType(element);
+        }
+        return new TypeVariableType(element);
       case TypeKind.TYPEDEF:
         return new TypedefType(decoder.getElement(Key.ELEMENT),
             decoder.getTypes(Key.TYPE_ARGUMENTS, isOptional: true));
diff --git a/pkg/compiler/lib/src/source_file_provider.dart b/pkg/compiler/lib/src/source_file_provider.dart
index 57bc9d3..2e2c7aa 100644
--- a/pkg/compiler/lib/src/source_file_provider.dart
+++ b/pkg/compiler/lib/src/source_file_provider.dart
@@ -168,9 +168,6 @@
   @override
   void report(var code, Uri uri, int begin, int end, String message,
       api.Diagnostic kind) {
-    // TODO(ahe): Remove this when source map is handled differently.
-    if (identical(kind.name, 'source map')) return;
-
     if (isAborting) return;
     isAborting = (kind == api.Diagnostic.CRASH);
 
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index 7607077..7148581 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -82,6 +82,10 @@
   final String name;
   final ExecutableElement executableContext;
 
+  // Avoid slow Object.hashCode.
+  final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30);
+  static int _nextHashCode = 0;
+
   SyntheticLocal(this.name, this.executableContext);
 
   toString() => 'SyntheticLocal($name)';
@@ -283,7 +287,7 @@
         (LocalVariableElement from, BoxFieldElement to) {
       // The [from] can only be a parameter for function-scopes and not
       // loop scopes.
-      if (from.isParameter && !element.isGenerativeConstructorBody) {
+      if (from.isRegularParameter && !element.isGenerativeConstructorBody) {
         // Now that the redirection is set up, the update to the local will
         // write the parameter value into the box.
         // Store the captured parameter in the box. Get the current value
@@ -1746,7 +1750,8 @@
   }
 
   HGraph buildCheckedSetter(VariableElement field) {
-    openFunction(field, field.node);
+    ResolvedAst resolvedAst = field.resolvedAst;
+    openFunction(field, resolvedAst.node);
     HInstruction thisInstruction = localsHandler.readThis();
     // Use dynamic type because the type computed by the inferrer is
     // narrowed to the type annotation.
@@ -5614,14 +5619,15 @@
       var filteredArguments = <HInstruction>[];
       var parameterNameMap = new Map<String, js.Expression>();
       params.orderedForEachParameter((ParameterElement parameter) {
-        // TODO(jacobr): throw if parameter names do not match names of property
-        // names in the class.
+        // TODO(jacobr): consider throwing if parameter names do not match
+        // names of properties in the class.
         assert(parameter.isNamed);
         HInstruction argument = arguments[i];
         if (argument != null) {
           filteredArguments.add(argument);
-          parameterNameMap[parameter.name] =
-              new js.InterpolatedExpression(positions++);
+          var jsName =
+              backend.nativeData.getUnescapedJSInteropName(parameter.name);
+          parameterNameMap[jsName] = new js.InterpolatedExpression(positions++);
         }
         i++;
       });
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index e1eee00c..d89f9de 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -450,7 +450,33 @@
           node.element = element;
         }
       }
+      return node;
     }
+
+    // Replace method calls through fields with a closure call on the value of
+    // the field. This usually removes the demand for the call-through stub and
+    // makes the field load available to further optimization, e.g. LICM.
+
+    if (element != null &&
+        element.isField &&
+        element.name == node.selector.name) {
+      if (!backend.isNative(element) && !node.isCallOnInterceptor(compiler)) {
+        HInstruction receiver = node.getDartReceiver(compiler);
+        TypeMask type =
+            TypeMaskFactory.inferredTypeForElement(element, compiler);
+        HInstruction load = new HFieldGet(element, receiver, type);
+        node.block.addBefore(node, load);
+        Selector callSelector = new Selector.callClosureFrom(node.selector);
+        List<HInstruction> inputs = <HInstruction>[load]
+          ..addAll(node.inputs.skip(node.isInterceptedCall ? 2 : 1));
+        HInstruction closureCall =
+            new HInvokeClosure(callSelector, inputs, node.instructionType)
+              ..sourceInformation = node.sourceInformation;
+        node.block.addAfter(load, closureCall);
+        return closureCall;
+      }
+    }
+
     return node;
   }
 
diff --git a/pkg/compiler/lib/src/tree/nodes.dart b/pkg/compiler/lib/src/tree/nodes.dart
index d2e9d96..1885e0d 100644
--- a/pkg/compiler/lib/src/tree/nodes.dart
+++ b/pkg/compiler/lib/src/tree/nodes.dart
@@ -295,10 +295,10 @@
  * "Token".
  */
 abstract class Node extends NullTreeElementMixin implements Spannable {
-  final int hashCode;
+  final int hashCode = _HASH_COUNTER = (_HASH_COUNTER + 1).toUnsigned(30);
   static int _HASH_COUNTER = 0;
 
-  Node() : hashCode = ++_HASH_COUNTER;
+  Node();
 
   accept(Visitor visitor);
 
diff --git a/pkg/compiler/lib/src/tree/unparser.dart b/pkg/compiler/lib/src/tree/unparser.dart
index 37838eb..12d4141 100644
--- a/pkg/compiler/lib/src/tree/unparser.dart
+++ b/pkg/compiler/lib/src/tree/unparser.dart
@@ -260,6 +260,7 @@
       write(' ');
     }
     unparseFunctionName(node.name);
+    visit(node.typeVariables);
     visit(node.parameters);
     if (node.initializers != null) {
       space();
diff --git a/pkg/compiler/lib/src/typechecker.dart b/pkg/compiler/lib/src/typechecker.dart
index 69137ab..be25edf 100644
--- a/pkg/compiler/lib/src/typechecker.dart
+++ b/pkg/compiler/lib/src/typechecker.dart
@@ -683,7 +683,7 @@
       assert(invariant(
           node,
           element.isVariable ||
-              element.isParameter ||
+              element.isRegularParameter ||
               element.isField ||
               (element.isInitializingFormal &&
                   compiler.options.enableInitializingFormalAccess),
@@ -772,7 +772,7 @@
     }
     if (receiverElement != null &&
         (receiverElement.isVariable ||
-            receiverElement.isParameter ||
+            receiverElement.isRegularParameter ||
             (receiverElement.isInitializingFormal &&
                 compiler.options.enableInitializingFormalAccess))) {
       Link<TypePromotion> typePromotions = typePromotionsMap[receiverElement];
@@ -1070,7 +1070,7 @@
       // foo() where foo is a method in the same class.
       return createResolvedAccess(node, name, element);
     } else if (element.isVariable ||
-        element.isParameter ||
+        element.isRegularParameter ||
         element.isField ||
         element.isInitializingFormal) {
       // foo() where foo is a field in the same class.
@@ -1091,7 +1091,7 @@
 
   ElementAccess createPromotedAccess(Element element) {
     if (element.isVariable ||
-        element.isParameter ||
+        element.isRegularParameter ||
         (element.isInitializingFormal &&
             compiler.options.enableInitializingFormalAccess)) {
       TypePromotion typePromotion = getKnownTypePromotion(element);
@@ -1230,7 +1230,7 @@
 
         if (variable != null &&
             (variable.isVariable ||
-                variable.isParameter ||
+                variable.isRegularParameter ||
                 (variable.isInitializingFormal &&
                     compiler.options.enableInitializingFormalAccess))) {
           DartType knownType = getKnownType(variable);
@@ -1742,7 +1742,7 @@
 
   DartType visitAwait(Await node) {
     DartType expressionType = analyze(node.expression);
-    if (compiler.backend.supportsAsyncAwait) {
+    if (resolution.target.supportsAsyncAwait) {
       return types.flatten(expressionType);
     } else {
       return const DynamicType();
@@ -1869,7 +1869,7 @@
   visitAsyncForIn(AsyncForIn node) {
     DartType elementType = computeForInElementType(node);
     DartType expressionType = analyze(node.expression);
-    if (compiler.backend.supportsAsyncAwait) {
+    if (resolution.target.supportsAsyncAwait) {
       DartType streamOfDynamic = coreTypes.streamType();
       if (!types.isAssignable(expressionType, streamOfDynamic)) {
         reportMessage(node.expression, MessageKind.NOT_ASSIGNABLE,
diff --git a/pkg/js/CHANGELOG.md b/pkg/js/CHANGELOG.md
index 4ef2ebc..d9695c3 100644
--- a/pkg/js/CHANGELOG.md
+++ b/pkg/js/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 0.6.1
+* Add js_util library of utility methods to efficiently manipulate typed
+  JavaScript interop objects in cases where the member name is not known
+  statically.
+
 ## 0.6.0
 
  * Version 0.6.0 is a complete rewrite of `package:js`.
diff --git a/pkg/js/lib/js_util.dart b/pkg/js/lib/js_util.dart
new file mode 100644
index 0000000..1e47e5d
--- /dev/null
+++ b/pkg/js/lib/js_util.dart
@@ -0,0 +1,8 @@
+// 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.
+
+/// Allows interoperability with Javascript APIs.
+library js_util;
+
+export 'dart:js_util';
diff --git a/pkg/js/pubspec.yaml b/pkg/js/pubspec.yaml
index 7555876..03cecdb 100644
--- a/pkg/js/pubspec.yaml
+++ b/pkg/js/pubspec.yaml
@@ -1,10 +1,10 @@
 name: js
-version: 0.6.0
+version: 0.6.1
 authors:
 - Dart Team <misc@dartlang.org>
 description: Access JavaScript from Dart.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/js
 environment:
-  sdk: '>=1.13.0 <2.0.0'
+  sdk: '>=1.19.0-dev.0.0 <2.0.0'
 dev_dependencies:
   browser: '^0.10.0+2'
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 81fe4d1..9e10464 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -27,15 +27,9 @@
 
 [ $runtime == vm && $system == windows]
 analysis_server/test/analysis/get_errors_test: Skip # runtime error, Issue 22180
-analysis_server/test/context_manager_test: RuntimeError # Issue 26828
 analysis_server/test/integration/analysis/analysis_options_test: RuntimeError # Issue 24796
 analyzer/test/generated/all_the_rest_test: Fail # Issue 21772
 analyzer/test/generated/source_factory_test: RuntimeError # Issue 26828
-analyzer/test/src/context/builder_test: RuntimeError # Issue 26828
-analyzer/test/src/summary/linker_test: RuntimeError # Issue 26828
-analyzer/test/src/summary/prelinker_test: RuntimeError # Issue 26828
-analyzer/test/src/summary/summarize_elements_strong_test: RuntimeError # Issue 26828
-analyzer/test/src/summary/summarize_elements_test: RuntimeError # Issue 26828
 
 [ $compiler == dart2js ]
 analysis_server/test/integration: SkipByDesign # Analysis server integration tests don't make sense to run under dart2js, since the code under test always runs in the Dart vm as a subprocess.
diff --git a/pkg/pkgbuild.status b/pkg/pkgbuild.status
index 2f7a6bd..9d1dfee 100644
--- a/pkg/pkgbuild.status
+++ b/pkg/pkgbuild.status
@@ -2,8 +2,6 @@
 # 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.
 
-third_party/pkg/scheduled_test: Fail # Issue 26585
-
 [ $use_public_packages ]
 pkg/compiler: SkipByDesign # js_ast is not published
 
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index e6794ec..499fc42 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -77,11 +77,6 @@
       defines += ["DART_PRECOMPILED_RUNTIME"]
     }
   } else if (dart_runtime_mode == "profile") {
-    if (dart_debug) {
-      print("Debug and profile mode are mutually exclusive.")
-    }
-    assert(!dart_debug)
-
     if (!dart_experimental_interpreter) {
       defines += ["DART_PRECOMPILED_RUNTIME"]
     }
@@ -156,7 +151,7 @@
     ]
   }
 
-  if (is_asan) {
+  if (defined(is_asan) && is_asan) {
     ldflags = [
       "-Wl,-u_sanitizer_options_link_helper",
       "-fsanitize=address",
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index bff1387..610115a 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -5,7 +5,12 @@
 
 declare_args() {
   dart_io_support = false
-  dart_boringssl_path = "../../third_party/boringssl"
+
+  # TODO(zra, jamesr): Remove this check once we start building boringssl for
+  # the fuchsia port.
+  if (!defined(is_fuchsia) || !is_fuchsia) {
+    dart_boringssl_path = "../../third_party/boringssl"
+  }
 }
 
 
@@ -133,6 +138,7 @@
   set_sources_assignment_filter(["*_test.cc", "*_test.h"])
   sources = [
     "log_android.cc",
+    "log_fuchsia.cc",
     "log_linux.cc",
     "log_macos.cc",
     "log_win.cc",
@@ -207,6 +213,13 @@
   ]
 }
 
+io_impl_sources_gypi =
+    exec_script("../../tools/gypi_to_gn.py",
+                [ rebase_path("io_impl_sources.gypi") ],
+                "scope",
+                [ "io_impl_sources.gypi" ])
+
+if (!defined(is_fuchsia) || (current_toolchain == host_toolchain)) {
 
 executable("gen_snapshot") {
   configs += ["..:dart_config",
@@ -244,24 +257,6 @@
   ]
 }
 
-
-source_set("libdart_embedder_noio") {
-  configs += ["..:dart_config",
-              "..:dart_product_config",
-              "..:dart_precompiled_runtime_config"]
-  deps = [
-    "..:libdart",
-    "../vm:libdart_platform",
-  ]
-}
-
-io_impl_sources_gypi =
-    exec_script("../../tools/gypi_to_gn.py",
-                [ rebase_path("io_impl_sources.gypi") ],
-                "scope",
-                [ "io_impl_sources.gypi" ])
-
-
 # A source set for the implementation of 'dart:io' library
 # (without secure sockets) suitable for linking with gen_snapshot.
 source_set("gen_snapshot_dart_io") {
@@ -303,6 +298,19 @@
   ]
 }
 
+}  # current_toolchain == host_toolchain
+
+source_set("libdart_embedder_noio") {
+  configs += ["..:dart_config",
+              "..:dart_product_config",
+              "..:dart_precompiled_runtime_config"]
+  deps = [
+    "..:libdart",
+    "../vm:libdart_platform",
+  ]
+}
+
+
 # A source set for the implementation of 'dart:io' library
 # (without secure sockets).
 source_set("embedded_dart_io") {
@@ -329,6 +337,10 @@
     libs = [
       "Security.framework",
     ]
+  } else if (defined(is_fuchsia) && is_fuchsia) {
+    defines = [
+      "DART_IO_SECURE_SOCKET_DISABLED"
+    ]
   } else {
     deps = [
       rebase_path(dart_boringssl_path, "."),
@@ -349,9 +361,147 @@
     "log_win.cc",
     "log.h",
   ]
+  if (is_linux) {
+    sources += [ "../../third_party/root_certificates/root_certificates.cc"]
+  }
 
   include_dirs = [
     "..",
     "//third_party"
   ]
 }
+
+
+action("generate_snapshot_bin") {
+  deps = [
+    "../bin:gen_snapshot($host_toolchain)",
+  ]
+
+  vm_isolate_snapshot = "$target_gen_dir/vm_isolate_snapshot.bin"
+  isolate_snapshot = "$target_gen_dir/isolate_snapshot.bin"
+  gen_snapshot_stamp_file = "$target_gen_dir/gen_snapshot.stamp"
+  outputs = [
+    vm_isolate_snapshot,
+    isolate_snapshot,
+    gen_snapshot_stamp_file,
+  ]
+
+  gen_snapshot_dir =
+      get_label_info("../bin:gen_snapshot($host_toolchain)", "root_out_dir")
+
+  script = rebase_path("../tools/create_snapshot_bin.py")
+  args = [
+    "--executable",
+    rebase_path("$gen_snapshot_dir/gen_snapshot"),
+    "--vm_output_bin",
+    rebase_path(vm_isolate_snapshot, root_build_dir),
+    "--output_bin",
+    rebase_path(isolate_snapshot, root_build_dir),
+    "--target_os",
+    current_os,
+    "--timestamp_file",
+    rebase_path(gen_snapshot_stamp_file, root_build_dir),
+  ]
+}
+
+
+action("generate_snapshot_file") {
+  deps = [
+    ":generate_snapshot_bin",
+  ]
+
+  snapshot_in_cc_file = "snapshot_in.cc"
+  inputs = [
+    "../tools/create_snapshot_file.py",
+    snapshot_in_cc_file,
+    "$target_gen_dir/vm_isolate_snapshot.bin",
+    "$target_gen_dir/isolate_snapshot.bin",
+  ]
+  output = "$root_gen_dir/dart_snapshot.cc"
+  outputs = [
+    output,
+  ]
+
+  script = "../tools/create_snapshot_file.py"
+  args = [
+    "--vm_input_bin",
+    rebase_path("$target_gen_dir/vm_isolate_snapshot.bin"),
+    "--input_bin",
+    rebase_path("$target_gen_dir/isolate_snapshot.bin"),
+    "--input_cc",
+    rebase_path(snapshot_in_cc_file),
+    "--output",
+    rebase_path(output),
+  ]
+}
+
+
+source_set("dart_snapshot_cc") {
+  sources = [
+    "$root_gen_dir/dart_snapshot.cc",
+  ]
+
+  deps = [
+    ":generate_snapshot_file",
+  ]
+}
+
+if (defined(is_fuchsia) && is_fuchsia) {
+  executable("fuchsia_test") {
+    configs += ["..:dart_config",
+                "..:dart_product_config",
+                "..:dart_precompiled_runtime_config"]
+    sources = [
+      "fuchsia_test.cc",
+      "log_fuchsia.cc",
+    ]
+
+    include_dirs = [
+      "..",
+      "../include"
+    ]
+
+    deps = [
+      ":dart_snapshot_cc",
+      ":libdart_embedder_noio",
+    ]
+  }
+
+  copy("hello_fuchsia") {
+    sources = [ "../tests/vm/dart/hello_fuchsia_test.dart" ]
+    outputs = [ "$root_out_dir/hello_fuchsia.dart" ]
+  }
+
+  executable("dart_no_observatory") {
+    configs += ["..:dart_config",
+                "..:dart_product_config",
+                "..:dart_precompiled_runtime_config",]
+    deps = [
+      ":hello_fuchsia",
+      ":gen_resources_cc",
+      ":embedded_dart_io",
+      ":libdart_builtin",
+      "../vm:libdart_platform",
+      "..:libdart",
+      ":dart_snapshot_cc",
+      "//third_party/zlib",
+    ]
+
+    defines = [
+      "NO_OBSERVATORY",
+    ]
+
+    sources = [
+      "main.cc",
+      "observatory_assets_empty.cc",
+      "vmservice_impl.cc",
+      "vmservice_impl.h",
+      "$target_gen_dir/resources_gen.cc",
+    ]
+
+    include_dirs = [
+      "..",
+      "//third_party",
+    ]
+  }
+}  # defined(is_fuchsia) && is_fuchsia
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index 2d04720..43b5915 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -11,6 +11,7 @@
     'html_cc_file': '<(gen_source_dir)/html_gen.cc',
     'html_common_cc_file': '<(gen_source_dir)/html_common_gen.cc',
     'js_cc_file': '<(gen_source_dir)/js_gen.cc',
+    'js_util_cc_file': '<(gen_source_dir)/js_util_gen.cc',
     'blink_cc_file': '<(gen_source_dir)/blink_gen.cc',
     'indexeddb_cc_file': '<(gen_source_dir)/indexeddb_gen.cc',
     'cached_patches_cc_file': '<(gen_source_dir)/cached_patches_gen.cc',
@@ -234,6 +235,38 @@
       ]
     },
     {
+      'target_name': 'generate_js_util_cc_file',
+      'type': 'none',
+      'toolsets':['host'],
+      'sources': [
+      '../../sdk/lib/js_util/dartium/js_util_dartium.dart',
+      ],
+      'actions': [
+      {
+        'action_name': 'generate_js_util_cc',
+        'inputs': [
+        '../tools/gen_library_src_paths.py',
+        '<(builtin_in_cc_file)',
+        '<@(_sources)',
+        ],
+        'outputs': [
+        '<(js_util_cc_file)',
+        ],
+        'action': [
+        'python',
+        'tools/gen_library_src_paths.py',
+        '--output', '<(js_util_cc_file)',
+        '--input_cc', '<(builtin_in_cc_file)',
+        '--include', 'bin/builtin.h',
+        '--var_name', 'dart::bin::Builtin::js_util_source_paths_',
+        '--library_name', 'dart:js_util',
+        '<@(_sources)',
+        ],
+        'message': 'Generating ''<(js_util_cc_file)'' file.'
+      },
+      ]
+    },
+    {
       'target_name': 'generate_blink_cc_file',
       'type': 'none',
       'toolsets':['host'],
@@ -500,6 +533,7 @@
         'generate_html_cc_file#host',
         'generate_html_common_cc_file#host',
         'generate_js_cc_file#host',
+        'generate_js_util_cc_file#host',
         'generate_blink_cc_file#host',
         'generate_indexeddb_cc_file#host',
         'generate_cached_patches_cc_file#host',
@@ -682,6 +716,10 @@
           'defines': [
             'DART_IO_SECURE_SOCKET_DISABLED'
           ],
+        }, {
+          'sources': [
+            '../../third_party/root_certificates/root_certificates.cc',
+          ],
         }],
         ['OS=="win"', {
           'sources/' : [
@@ -758,6 +796,10 @@
           'defines': [
             'DART_IO_SECURE_SOCKET_DISABLED'
           ],
+        }, {
+          'sources': [
+            '../../third_party/root_certificates/root_certificates.cc',
+          ],
         }],
         ['OS != "mac" and dart_io_support==1 and dart_io_secure_socket==1', {
           'dependencies': [
@@ -818,6 +860,10 @@
           'defines': [
             'DART_IO_SECURE_SOCKET_DISABLED',
           ],
+        }, {
+          'sources': [
+            '../../third_party/root_certificates/root_certificates.cc',
+          ],
         }],
         ['OS != "mac" and dart_io_support==1 and dart_io_secure_socket==1', {
           'dependencies': [
@@ -1058,20 +1104,6 @@
       ]
     },
     {
-      'target_name': 'fuchsia_test',
-      'type': 'executable',
-      'dependencies': [
-        'libdart_nosnapshot',
-      ],
-      'include_dirs': [
-        '..',
-        '../include',
-      ],
-      'sources': [
-        'fuchsia_test.cc',
-      ],
-    },
-    {
       # dart binary with a snapshot of corelibs built in.
       'target_name': 'dart',
       'type': 'executable',
@@ -1264,6 +1296,7 @@
         '<(html_cc_file)',
         '<(html_common_cc_file)',
         '<(js_cc_file)',
+        '<(js_util_cc_file)',
         '<(blink_cc_file)',
         '<(indexeddb_cc_file)',
         '<(cached_patches_cc_file)',
diff --git a/runtime/bin/builtin.cc b/runtime/bin/builtin.cc
index c26a762..04fb060 100644
--- a/runtime/bin/builtin.cc
+++ b/runtime/bin/builtin.cc
@@ -24,6 +24,7 @@
   { "dart:html", html_source_paths_, NULL, NULL, true },
   { "dart:html_common", html_common_source_paths_, NULL, NULL, true},
   { "dart:js", js_source_paths_, NULL, NULL, true},
+  { "dart:js_util", js_util_source_paths_, NULL, NULL, true},
   { "dart:_blink", blink_source_paths_, NULL, NULL, true },
   { "dart:indexed_db", indexeddb_source_paths_, NULL, NULL, true },
   { "cached_patches.dart", cached_patches_source_paths_, NULL, NULL, true },
diff --git a/runtime/bin/builtin.h b/runtime/bin/builtin.h
index 5029cf1..d90223a 100644
--- a/runtime/bin/builtin.h
+++ b/runtime/bin/builtin.h
@@ -74,6 +74,7 @@
   static const char* html_source_paths_[];
   static const char* html_common_source_paths_[];
   static const char* js_source_paths_[];
+  static const char* js_util_source_paths_[];
   static const char* blink_source_paths_[];
   static const char* indexeddb_source_paths_[];
   static const char* cached_patches_source_paths_[];
diff --git a/runtime/bin/builtin_impl_sources.gypi b/runtime/bin/builtin_impl_sources.gypi
index f775ffc..2e6ae0c 100644
--- a/runtime/bin/builtin_impl_sources.gypi
+++ b/runtime/bin/builtin_impl_sources.gypi
@@ -10,6 +10,7 @@
     'crypto.cc',
     'crypto.h',
     'crypto_android.cc',
+    'crypto_fuchsia.cc',
     'crypto_linux.cc',
     'crypto_macos.cc',
     'crypto_win.cc',
@@ -19,6 +20,7 @@
     'directory.cc',
     'directory.h',
     'directory_android.cc',
+    'directory_fuchsia.cc',
     'directory_linux.cc',
     'directory_macos.cc',
     'directory_unsupported.cc',
@@ -27,6 +29,7 @@
     'extensions.h',
     'extensions.cc',
     'extensions_android.cc',
+    'extensions_fuchsia.cc',
     'extensions_linux.cc',
     'extensions_macos.cc',
     'extensions_win.cc',
@@ -37,6 +40,7 @@
     'file.cc',
     'file.h',
     'file_android.cc',
+    'file_fuchsia.cc',
     'file_linux.cc',
     'file_macos.cc',
     'file_support.cc',
@@ -53,6 +57,8 @@
     'thread.h',
     'thread_android.cc',
     'thread_android.h',
+    'thread_fuchsia.cc',
+    'thread_fuchsia.h',
     'thread_linux.cc',
     'thread_linux.h',
     'thread_macos.cc',
@@ -61,6 +67,7 @@
     'thread_win.h',
     'utils.h',
     'utils_android.cc',
+    'utils_fuchsia.cc',
     'utils_linux.cc',
     'utils_macos.cc',
     'utils_win.cc',
diff --git a/runtime/bin/crypto_fuchsia.cc b/runtime/bin/crypto_fuchsia.cc
new file mode 100644
index 0000000..9423f7c
--- /dev/null
+++ b/runtime/bin/crypto_fuchsia.cc
@@ -0,0 +1,31 @@
+// 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.
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_FUCHSIA)
+
+#include "bin/crypto.h"
+
+namespace dart {
+namespace bin {
+
+bool Crypto::GetRandomBytes(intptr_t count, uint8_t* buffer) {
+  uint32_t num;
+  intptr_t read = 0;
+  while (read < count) {
+    if (rand_r(&num) != 0) {
+      return false;
+    }
+    for (int i = 0; i < 4 && read < count; i++) {
+      buffer[read] = num >> (i * 8);
+      read++;
+    }
+  }
+  return true;
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // defined(TARGET_OS_FUCHSIA)
diff --git a/runtime/bin/directory.cc b/runtime/bin/directory.cc
index a9b2331..ccf5918 100644
--- a/runtime/bin/directory.cc
+++ b/runtime/bin/directory.cc
@@ -14,6 +14,8 @@
 namespace dart {
 namespace bin {
 
+char* Directory::system_temp_path_override_ = NULL;
+
 void FUNCTION_NAME(Directory_Current)(Dart_NativeArguments args) {
   const char* current = Directory::Current();
   if (current != NULL) {
@@ -187,6 +189,17 @@
 }
 
 
+void Directory::SetSystemTemp(const char* path) {
+  if (system_temp_path_override_ != NULL) {
+    free(system_temp_path_override_);
+    system_temp_path_override_ = NULL;
+  }
+  if (path != NULL) {
+    system_temp_path_override_ = strdup(path);
+  }
+}
+
+
 CObject* Directory::CreateRequest(const CObjectArray& request) {
   if ((request.Length() == 1) && request[0]->IsString()) {
     CObjectString path(request[0]);
diff --git a/runtime/bin/directory.h b/runtime/bin/directory.h
index f455710..ee1f389 100644
--- a/runtime/bin/directory.h
+++ b/runtime/bin/directory.h
@@ -274,6 +274,8 @@
   static const char* Current();
   static const char* SystemTemp();
   static const char* CreateTemp(const char* path);
+  // Set the system temporary directory.
+  static void SetSystemTemp(const char* path);
   static bool SetCurrent(const char* path);
   static bool Create(const char* path);
   static bool Delete(const char* path, bool recursive);
@@ -290,6 +292,7 @@
   static CObject* RenameRequest(const CObjectArray& request);
 
  private:
+  static char* system_temp_path_override_;
   DISALLOW_ALLOCATION();
   DISALLOW_IMPLICIT_CONSTRUCTORS(Directory);
 };
diff --git a/runtime/bin/directory_android.cc b/runtime/bin/directory_android.cc
index 95f42da..75ca974 100644
--- a/runtime/bin/directory_android.cc
+++ b/runtime/bin/directory_android.cc
@@ -403,6 +403,9 @@
 
 
 const char* Directory::SystemTemp() {
+  if (Directory::system_temp_path_override_ != NULL) {
+    return DartUtils::ScopedCopyCString(Directory::system_temp_path_override_);
+  }
   // Android does not have a /tmp directory. A partial substitute,
   // suitable for bring-up work and tests, is to create a tmp
   // directory in /data/local/tmp.
diff --git a/runtime/bin/directory_fuchsia.cc b/runtime/bin/directory_fuchsia.cc
new file mode 100644
index 0000000..a1387b0
--- /dev/null
+++ b/runtime/bin/directory_fuchsia.cc
@@ -0,0 +1,154 @@
+// 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.
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_FUCHSIA)
+
+#include "bin/directory.h"
+
+#include <errno.h>  // NOLINT
+#include <stdlib.h>  // NOLINT
+#include <string.h>  // NOLINT
+#include <unistd.h>  // NOLINT
+
+namespace dart {
+namespace bin {
+
+PathBuffer::PathBuffer() : length_(0) {
+  data_ = calloc(PATH_MAX + 1, sizeof(char));  // NOLINT
+}
+
+
+PathBuffer::~PathBuffer() {
+  free(data_);
+}
+
+
+bool PathBuffer::AddW(const wchar_t* name) {
+  UNREACHABLE();
+  return false;
+}
+
+
+char* PathBuffer::AsString() const {
+  return reinterpret_cast<char*>(data_);
+}
+
+
+wchar_t* PathBuffer::AsStringW() const {
+  UNREACHABLE();
+  return NULL;
+}
+
+
+const char* PathBuffer::AsScopedString() const {
+  return DartUtils::ScopedCopyCString(AsString());
+}
+
+
+bool PathBuffer::Add(const char* name) {
+  const intptr_t name_length = strnlen(name, PATH_MAX + 1);
+  if (name_length == 0) {
+    errno = EINVAL;
+    return false;
+  }
+  char* data = AsString();
+  int written = snprintf(data + length_,
+                         PATH_MAX - length_,
+                         "%s",
+                         name);
+  data[PATH_MAX] = '\0';
+  if ((written <= (PATH_MAX - length_)) &&
+      (written > 0) &&
+      (static_cast<size_t>(written) == strnlen(name, PATH_MAX + 1))) {
+    length_ += written;
+    return true;
+  } else {
+    errno = ENAMETOOLONG;
+    return false;
+  }
+}
+
+
+void PathBuffer::Reset(intptr_t new_length) {
+  length_ = new_length;
+  AsString()[length_] = '\0';
+}
+
+
+ListType DirectoryListingEntry::Next(DirectoryListing* listing) {
+  UNIMPLEMENTED();
+  return kListError;
+}
+
+
+DirectoryListingEntry::~DirectoryListingEntry() {
+  UNIMPLEMENTED();
+}
+
+
+void DirectoryListingEntry::ResetLink() {
+  UNIMPLEMENTED();
+}
+
+
+Directory::ExistsResult Directory::Exists(const char* dir_name) {
+  UNIMPLEMENTED();
+  return UNKNOWN;
+}
+
+
+char* Directory::CurrentNoScope() {
+  return getcwd(NULL, 0);
+}
+
+
+const char* Directory::Current() {
+  char buffer[PATH_MAX];
+  if (getcwd(buffer, PATH_MAX) == NULL) {
+    return NULL;
+  }
+  return DartUtils::ScopedCopyCString(buffer);
+}
+
+
+bool Directory::SetCurrent(const char* path) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+bool Directory::Create(const char* dir_name) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+const char* Directory::SystemTemp() {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+const char* Directory::CreateTemp(const char* prefix) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+bool Directory::Delete(const char* dir_name, bool recursive) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+bool Directory::Rename(const char* path, const char* new_path) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // defined(TARGET_OS_LINUX)
diff --git a/runtime/bin/embedded_dart_io.cc b/runtime/bin/embedded_dart_io.cc
index 9e38f02..8b1b7fb 100644
--- a/runtime/bin/embedded_dart_io.cc
+++ b/runtime/bin/embedded_dart_io.cc
@@ -4,6 +4,7 @@
 
 #include "bin/embedded_dart_io.h"
 
+#include "bin/directory.h"
 #include "bin/eventhandler.h"
 #include "bin/utils.h"
 #include "bin/thread.h"
@@ -18,5 +19,10 @@
   EventHandler::Start();
 }
 
+
+void SetSystemTempDirectory(const char* system_temp) {
+  Directory::SetSystemTemp(system_temp);
+}
+
 }  // namespace bin
 }  // namespace dart
diff --git a/runtime/bin/embedded_dart_io.h b/runtime/bin/embedded_dart_io.h
index a5b069d..56dbba8 100644
--- a/runtime/bin/embedded_dart_io.h
+++ b/runtime/bin/embedded_dart_io.h
@@ -11,6 +11,10 @@
 // Bootstraps 'dart:io'.
 void BootstrapDartIo();
 
+// Lets dart:io know where the system temporary directory is located.
+// Currently only wired up on Android.
+void SetSystemTempDirectory(const char* system_temp);
+
 // Tells the system whether to capture Stdout events.
 void SetCaptureStdout(bool value);
 
diff --git a/runtime/bin/eventhandler.h b/runtime/bin/eventhandler.h
index 34f6c65..ab5b590 100644
--- a/runtime/bin/eventhandler.h
+++ b/runtime/bin/eventhandler.h
@@ -605,6 +605,8 @@
 // The event handler delegation class is OS specific.
 #if defined(TARGET_OS_ANDROID)
 #include "bin/eventhandler_android.h"
+#elif defined(TARGET_OS_FUCHSIA)
+#include "bin/eventhandler_fuchsia.h"
 #elif defined(TARGET_OS_LINUX)
 #include "bin/eventhandler_linux.h"
 #elif defined(TARGET_OS_MACOS)
diff --git a/runtime/bin/eventhandler_fuchsia.cc b/runtime/bin/eventhandler_fuchsia.cc
new file mode 100644
index 0000000..69c2190
--- /dev/null
+++ b/runtime/bin/eventhandler_fuchsia.cc
@@ -0,0 +1,172 @@
+// 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.
+
+#if !defined(DART_IO_DISABLED)
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_FUCHSIA)
+
+#include "bin/eventhandler.h"
+#include "bin/eventhandler_fuchsia.h"
+
+#include <magenta/syscalls.h>
+#include <runtime/status.h>
+
+#include "bin/thread.h"
+#include "bin/utils.h"
+
+namespace dart {
+namespace bin {
+
+EventHandlerImplementation::EventHandlerImplementation() {
+  mx_status_t status = mx_message_pipe_create(interrupt_handles_, 0);
+  if (status != NO_ERROR) {
+    FATAL1("mx_message_pipe_create failed: %s\n", mx_strstatus(status));
+  }
+}
+
+
+EventHandlerImplementation::~EventHandlerImplementation() {
+  mx_status_t status = mx_handle_close(interrupt_handles_[0]);
+  if (status != NO_ERROR) {
+    FATAL1("mx_handle_close failed: %s\n", mx_strstatus(status));
+  }
+  status = mx_handle_close(interrupt_handles_[1]);
+  if (status != NO_ERROR) {
+    FATAL1("mx_handle_close failed: %s\n", mx_strstatus(status));
+  }
+}
+
+
+void EventHandlerImplementation::WakeupHandler(intptr_t id,
+                                               Dart_Port dart_port,
+                                               int64_t data) {
+  InterruptMessage msg;
+  msg.id = id;
+  msg.dart_port = dart_port;
+  msg.data = data;
+
+  mx_status_t status =
+    mx_message_write(interrupt_handles_[1], &msg, sizeof(msg), NULL, 0, 0);
+  if (status != NO_ERROR) {
+    FATAL1("mx_message_write failed: %s\n", mx_strstatus(status));
+  }
+}
+
+
+void EventHandlerImplementation::HandleInterruptFd() {
+  InterruptMessage msg;
+  uint32_t bytes = kInterruptMessageSize;
+  mx_status_t status;
+  while (true) {
+    status = mx_message_read(
+        interrupt_handles_[0], &msg, &bytes, NULL, NULL, 0);
+    if (status != NO_ERROR) {
+      break;
+    }
+    ASSERT(bytes == kInterruptMessageSize);
+    if (msg.id == kTimerId) {
+      timeout_queue_.UpdateTimeout(msg.dart_port, msg.data);
+    } else if (msg.id == kShutdownId) {
+      shutdown_ = true;
+    } else {
+      UNIMPLEMENTED();
+    }
+  }
+  // status == ERR_BAD_STATE when we try to read and there are no messages
+  // available, so it is an error if we get here and status != ERR_BAD_STATE.
+  if (status != ERR_BAD_STATE) {
+    FATAL1("mx_message_read failed: %s\n", mx_strstatus(status));
+  }
+}
+
+
+void EventHandlerImplementation::HandleEvents() {
+  // TODO(zra): Handle events from other handles. At the moment we are only
+  // interrupted when there is a message on interrupt_handles_[0].
+  HandleInterruptFd();
+}
+
+
+int64_t EventHandlerImplementation::GetTimeout() const {
+  if (!timeout_queue_.HasTimeout()) {
+    return kInfinityTimeout;
+  }
+  int64_t millis = timeout_queue_.CurrentTimeout() -
+      TimerUtils::GetCurrentMonotonicMillis();
+  return (millis < 0) ? 0 : millis;
+}
+
+
+void EventHandlerImplementation::HandleTimeout() {
+  if (timeout_queue_.HasTimeout()) {
+    int64_t millis = timeout_queue_.CurrentTimeout() -
+        TimerUtils::GetCurrentMonotonicMillis();
+    if (millis <= 0) {
+      DartUtils::PostNull(timeout_queue_.CurrentPort());
+      timeout_queue_.RemoveCurrent();
+    }
+  }
+}
+
+
+void EventHandlerImplementation::Poll(uword args) {
+  EventHandler* handler = reinterpret_cast<EventHandler*>(args);
+  EventHandlerImplementation* handler_impl = &handler->delegate_;
+  ASSERT(handler_impl != NULL);
+
+  while (!handler_impl->shutdown_) {
+    int64_t millis = handler_impl->GetTimeout();
+    ASSERT((millis == kInfinityTimeout) || (millis >= 0));
+
+    mx_time_t timeout =
+        millis * kMicrosecondsPerMillisecond * kNanosecondsPerMicrosecond;
+    mx_signals_state_t signals_state;
+    mx_status_t status = mx_handle_wait_one(
+        handler_impl->interrupt_handles_[0],
+        MX_SIGNAL_READABLE | MX_SIGNAL_PEER_CLOSED,
+        timeout,
+        &signals_state);
+    if ((status != NO_ERROR) && (status != ERR_TIMED_OUT)) {
+      FATAL1("mx_handle_wait_one failed: %s\n", mx_strstatus(status));
+    } else {
+      handler_impl->HandleTimeout();
+      if ((signals_state.satisfied & MX_SIGNAL_READABLE) != 0) {
+        handler_impl->HandleEvents();
+      }
+      if ((signals_state.satisfied & MX_SIGNAL_PEER_CLOSED) != 0) {
+        FATAL("EventHandlerImplementation::Poll: Unexpected peer closed\n");
+      }
+    }
+  }
+  handler->NotifyShutdownDone();
+}
+
+
+void EventHandlerImplementation::Start(EventHandler* handler) {
+  int result = Thread::Start(&EventHandlerImplementation::Poll,
+                             reinterpret_cast<uword>(handler));
+  if (result != 0) {
+    FATAL1("Failed to start event handler thread %d", result);
+  }
+}
+
+
+void EventHandlerImplementation::Shutdown() {
+  SendData(kShutdownId, 0, 0);
+}
+
+
+void EventHandlerImplementation::SendData(intptr_t id,
+                                          Dart_Port dart_port,
+                                          int64_t data) {
+  WakeupHandler(id, dart_port, data);
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // defined(TARGET_OS_FUCHSIA)
+
+#endif  // !defined(DART_IO_DISABLED)
diff --git a/runtime/bin/eventhandler_fuchsia.h b/runtime/bin/eventhandler_fuchsia.h
new file mode 100644
index 0000000..0130992
--- /dev/null
+++ b/runtime/bin/eventhandler_fuchsia.h
@@ -0,0 +1,44 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef BIN_EVENTHANDLER_FUCHSIA_H_
+#define BIN_EVENTHANDLER_FUCHSIA_H_
+
+#if !defined(BIN_EVENTHANDLER_H_)
+#error Do not include eventhandler_fuchsia.h directly; use eventhandler.h instead.
+#endif
+
+#include <magenta/syscalls.h>
+
+namespace dart {
+namespace bin {
+
+class EventHandlerImplementation {
+ public:
+  EventHandlerImplementation();
+  ~EventHandlerImplementation();
+
+  void SendData(intptr_t id, Dart_Port dart_port, int64_t data);
+  void Start(EventHandler* handler);
+  void Shutdown();
+
+ private:
+  int64_t GetTimeout() const;
+  void HandleEvents();
+  void HandleTimeout();
+  void WakeupHandler(intptr_t id, Dart_Port dart_port, int64_t data);
+  void HandleInterruptFd();
+  static void Poll(uword args);
+
+  TimeoutQueue timeout_queue_;
+  bool shutdown_;
+  mx_handle_t interrupt_handles_[2];
+
+  DISALLOW_COPY_AND_ASSIGN(EventHandlerImplementation);
+};
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // BIN_EVENTHANDLER_FUCHSIA_H_
diff --git a/runtime/bin/extensions_fuchsia.cc b/runtime/bin/extensions_fuchsia.cc
new file mode 100644
index 0000000..d474672
--- /dev/null
+++ b/runtime/bin/extensions_fuchsia.cc
@@ -0,0 +1,38 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_FUCHSIA)
+
+#include "bin/extensions.h"
+#include <dlfcn.h>  // NOLINT
+
+namespace dart {
+namespace bin {
+
+const char* kPrecompiledLibraryName = "libprecompiled.so";
+const char* kPrecompiledInstructionsSymbolName = "_kInstructionsSnapshot";
+const char* kPrecompiledDataSymbolName = "_kDataSnapshot";
+
+void* Extensions::LoadExtensionLibrary(const char* library_file) {
+  return dlopen(library_file, RTLD_LAZY);
+}
+
+void* Extensions::ResolveSymbol(void* lib_handle, const char* symbol) {
+  dlerror();
+  return dlsym(lib_handle, symbol);
+}
+
+Dart_Handle Extensions::GetError() {
+  const char* err_str = dlerror();
+  if (err_str != NULL) {
+    return Dart_NewApiError(err_str);
+  }
+  return Dart_Null();
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // defined(TARGET_OS_FUCHSIA)
diff --git a/runtime/bin/file_fuchsia.cc b/runtime/bin/file_fuchsia.cc
new file mode 100644
index 0000000..fdc2623
--- /dev/null
+++ b/runtime/bin/file_fuchsia.cc
@@ -0,0 +1,452 @@
+// 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.
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_FUCHSIA)
+
+#include "bin/file.h"
+
+#include <errno.h>  // NOLINT
+#include <fcntl.h>  // NOLINT
+#include <libgen.h>  // NOLINT
+#include <sys/mman.h>  // NOLINT
+#include <sys/stat.h>  // NOLINT
+#include <sys/types.h>  // NOLINT
+#include <unistd.h>  // NOLINT
+
+#include "bin/builtin.h"
+#include "bin/log.h"
+#include "platform/signal_blocker.h"
+#include "platform/utils.h"
+
+namespace dart {
+namespace bin {
+
+class FileHandle {
+ public:
+  explicit FileHandle(int fd) : fd_(fd) { }
+  ~FileHandle() { }
+  int fd() const { return fd_; }
+  void set_fd(int fd) { fd_ = fd; }
+
+ private:
+  int fd_;
+
+  DISALLOW_COPY_AND_ASSIGN(FileHandle);
+};
+
+
+File::~File() {
+  if (!IsClosed()) {
+    Close();
+  }
+  delete handle_;
+}
+
+
+void File::Close() {
+  ASSERT(handle_->fd() >= 0);
+  if (handle_->fd() == STDOUT_FILENO) {
+    // If stdout, redirect fd to /dev/null.
+    int null_fd = NO_RETRY_EXPECTED(open("/dev/null", O_WRONLY));
+    ASSERT(null_fd >= 0);
+    VOID_NO_RETRY_EXPECTED(dup2(null_fd, handle_->fd()));
+    VOID_NO_RETRY_EXPECTED(close(null_fd));
+  } else {
+    int err = NO_RETRY_EXPECTED(close(handle_->fd()));
+    if (err != 0) {
+      const int kBufferSize = 1024;
+      char error_buf[kBufferSize];
+      Log::PrintErr("%s\n", Utils::StrError(errno, error_buf, kBufferSize));
+    }
+  }
+  handle_->set_fd(kClosedFd);
+}
+
+
+intptr_t File::GetFD() {
+  return handle_->fd();
+}
+
+
+bool File::IsClosed() {
+  return handle_->fd() == kClosedFd;
+}
+
+
+void* File::MapExecutable(intptr_t* len) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+int64_t File::Read(void* buffer, int64_t num_bytes) {
+  ASSERT(handle_->fd() >= 0);
+  return NO_RETRY_EXPECTED(read(handle_->fd(), buffer, num_bytes));
+}
+
+
+int64_t File::Write(const void* buffer, int64_t num_bytes) {
+  ASSERT(handle_->fd() >= 0);
+  return NO_RETRY_EXPECTED(write(handle_->fd(), buffer, num_bytes));
+}
+
+
+int64_t File::Position() {
+  ASSERT(handle_->fd() >= 0);
+  return NO_RETRY_EXPECTED(lseek(handle_->fd(), 0, SEEK_CUR));
+}
+
+
+bool File::SetPosition(int64_t position) {
+  ASSERT(handle_->fd() >= 0);
+  return NO_RETRY_EXPECTED(lseek(handle_->fd(), position, SEEK_SET)) >= 0;
+}
+
+
+bool File::Truncate(int64_t length) {
+  ASSERT(handle_->fd() >= 0);
+  return NO_RETRY_EXPECTED(ftruncate(handle_->fd(), length) != -1);
+}
+
+
+bool File::Flush() {
+  ASSERT(handle_->fd() >= 0);
+  return NO_RETRY_EXPECTED(fsync(handle_->fd())) != -1;
+}
+
+
+bool File::Lock(File::LockType lock, int64_t start, int64_t end) {
+  ASSERT(handle_->fd() >= 0);
+  ASSERT((end == -1) || (end > start));
+  struct flock fl;
+  switch (lock) {
+    case File::kLockUnlock:
+      fl.l_type = F_UNLCK;
+      break;
+    case File::kLockShared:
+    case File::kLockBlockingShared:
+      fl.l_type = F_RDLCK;
+      break;
+    case File::kLockExclusive:
+    case File::kLockBlockingExclusive:
+      fl.l_type = F_WRLCK;
+      break;
+    default:
+      return false;
+  }
+  fl.l_whence = SEEK_SET;
+  fl.l_start = start;
+  fl.l_len = end == -1 ? 0 : end - start;
+  int cmd = F_SETLK;
+  if ((lock == File::kLockBlockingShared) ||
+      (lock == File::kLockBlockingExclusive)) {
+    cmd = F_SETLKW;
+  }
+  return NO_RETRY_EXPECTED(fcntl(handle_->fd(), cmd, &fl)) != -1;
+}
+
+
+int64_t File::Length() {
+  ASSERT(handle_->fd() >= 0);
+  struct stat st;
+  if (NO_RETRY_EXPECTED(fstat(handle_->fd(), &st)) == 0) {
+    return st.st_size;
+  }
+  return -1;
+}
+
+
+File* File::FileOpenW(const wchar_t* system_name, FileOpenMode mode) {
+  UNREACHABLE();
+  return NULL;
+}
+
+
+File* File::ScopedOpen(const char* name, FileOpenMode mode) {
+  // Report errors for non-regular files.
+  struct stat st;
+  if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) {
+    if (!S_ISREG(st.st_mode)) {
+      errno = (S_ISDIR(st.st_mode)) ? EISDIR : ENOENT;
+      return NULL;
+    }
+  }
+  int flags = O_RDONLY;
+  if ((mode & kWrite) != 0) {
+    ASSERT((mode & kWriteOnly) == 0);
+    flags = (O_RDWR | O_CREAT);
+  }
+  if ((mode & kWriteOnly) != 0) {
+    ASSERT((mode & kWrite) == 0);
+    flags = (O_WRONLY | O_CREAT);
+  }
+  if ((mode & kTruncate) != 0) {
+    flags = flags | O_TRUNC;
+  }
+  flags |= O_CLOEXEC;
+  int fd = NO_RETRY_EXPECTED(open(name, flags, 0666));
+  if (fd < 0) {
+    return NULL;
+  }
+  if ((((mode & kWrite) != 0) && ((mode & kTruncate) == 0)) ||
+      (((mode & kWriteOnly) != 0) && ((mode & kTruncate) == 0))) {
+    int64_t position = lseek(fd, 0, SEEK_END);
+    if (position < 0) {
+      return NULL;
+    }
+  }
+  return new File(new FileHandle(fd));
+}
+
+
+File* File::Open(const char* path, FileOpenMode mode) {
+  // ScopedOpen doesn't actually need a scope.
+  return ScopedOpen(path, mode);
+}
+
+
+File* File::OpenStdio(int fd) {
+  return ((fd < 0) || (2 < fd)) ? NULL : new File(new FileHandle(fd));
+}
+
+
+bool File::Exists(const char* name) {
+  struct stat st;
+  if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) {
+    return S_ISREG(st.st_mode);
+  } else {
+    return false;
+  }
+}
+
+
+bool File::Create(const char* name) {
+  int fd = NO_RETRY_EXPECTED(open(name, O_RDONLY | O_CREAT | O_CLOEXEC, 0666));
+  if (fd < 0) {
+    return false;
+  }
+  return (close(fd) == 0);
+}
+
+
+bool File::CreateLink(const char* name, const char* target) {
+  return NO_RETRY_EXPECTED(symlink(target, name)) == 0;
+}
+
+
+bool File::Delete(const char* name) {
+  File::Type type = File::GetType(name, true);
+  if (type == kIsFile) {
+    return NO_RETRY_EXPECTED(unlink(name)) == 0;
+  } else if (type == kIsDirectory) {
+    errno = EISDIR;
+  } else {
+    errno = ENOENT;
+  }
+  return false;
+}
+
+
+bool File::DeleteLink(const char* name) {
+  File::Type type = File::GetType(name, false);
+  if (type == kIsLink) {
+    return NO_RETRY_EXPECTED(unlink(name)) == 0;
+  }
+  errno = EINVAL;
+  return false;
+}
+
+
+bool File::Rename(const char* old_path, const char* new_path) {
+  File::Type type = File::GetType(old_path, true);
+  if (type == kIsFile) {
+    return NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0;
+  } else if (type == kIsDirectory) {
+    errno = EISDIR;
+  } else {
+    errno = ENOENT;
+  }
+  return false;
+}
+
+
+bool File::RenameLink(const char* old_path, const char* new_path) {
+  File::Type type = File::GetType(old_path, false);
+  if (type == kIsLink) {
+    return NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0;
+  } else if (type == kIsDirectory) {
+    errno = EISDIR;
+  } else {
+    errno = EINVAL;
+  }
+  return false;
+}
+
+
+bool File::Copy(const char* old_path, const char* new_path) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+int64_t File::LengthFromPath(const char* name) {
+  struct stat st;
+  if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) {
+    return st.st_size;
+  }
+  return -1;
+}
+
+
+void File::Stat(const char* name, int64_t* data) {
+  struct stat st;
+  if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) {
+    if (S_ISREG(st.st_mode)) {
+      data[kType] = kIsFile;
+    } else if (S_ISDIR(st.st_mode)) {
+      data[kType] = kIsDirectory;
+    } else if (S_ISLNK(st.st_mode)) {
+      data[kType] = kIsLink;
+    } else {
+      data[kType] = kDoesNotExist;
+    }
+    data[kCreatedTime] = static_cast<int64_t>(st.st_ctime) * 1000;
+    data[kModifiedTime] = static_cast<int64_t>(st.st_mtime) * 1000;
+    data[kAccessedTime] = static_cast<int64_t>(st.st_atime) * 1000;
+    data[kMode] = st.st_mode;
+    data[kSize] = st.st_size;
+  } else {
+    data[kType] = kDoesNotExist;
+  }
+}
+
+
+time_t File::LastModified(const char* name) {
+  struct stat st;
+  if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) {
+    return st.st_mtime;
+  }
+  return -1;
+}
+
+
+const char* File::LinkTarget(const char* pathname) {
+  struct stat link_stats;
+  if (lstat(pathname, &link_stats) != 0) {
+    return NULL;
+  }
+  if (!S_ISLNK(link_stats.st_mode)) {
+    errno = ENOENT;
+    return NULL;
+  }
+  size_t target_size = link_stats.st_size;
+  char* target_name = DartUtils::ScopedCString(target_size + 1);
+  ASSERT(target_name != NULL);
+  size_t read_size = readlink(pathname, target_name, target_size + 1);
+  if (read_size != target_size) {
+    return NULL;
+  }
+  target_name[target_size] = '\0';
+  return target_name;
+}
+
+
+bool File::IsAbsolutePath(const char* pathname) {
+  return ((pathname != NULL) && (pathname[0] == '/'));
+}
+
+
+const char* File::GetCanonicalPath(const char* pathname) {
+  char* abs_path = NULL;
+  if (pathname != NULL) {
+    char* resolved_path = DartUtils::ScopedCString(PATH_MAX + 1);
+    ASSERT(resolved_path != NULL);
+    do {
+      abs_path = realpath(pathname, resolved_path);
+    } while ((abs_path == NULL) && (errno == EINTR));
+    ASSERT((abs_path == NULL) || IsAbsolutePath(abs_path));
+    ASSERT((abs_path == NULL) || (abs_path == resolved_path));
+  }
+  return abs_path;
+}
+
+
+const char* File::PathSeparator() {
+  return "/";
+}
+
+
+const char* File::StringEscapedPathSeparator() {
+  return "/";
+}
+
+
+File::StdioHandleType File::GetStdioHandleType(int fd) {
+  ASSERT((0 <= fd) && (fd <= 2));
+  struct stat buf;
+  int result = fstat(fd, &buf);
+  if (result == -1) {
+    const int kBufferSize = 1024;
+    char error_message[kBufferSize];
+    Utils::StrError(errno, error_message, kBufferSize);
+    FATAL2("Failed stat on file descriptor %d: %s", fd, error_message);
+  }
+  if (S_ISCHR(buf.st_mode)) {
+    return kTerminal;
+  }
+  if (S_ISFIFO(buf.st_mode)) {
+    return kPipe;
+  }
+  if (S_ISSOCK(buf.st_mode)) {
+    return kSocket;
+  }
+  if (S_ISREG(buf.st_mode)) {
+    return kFile;
+  }
+  return kOther;
+}
+
+
+File::Type File::GetType(const char* pathname, bool follow_links) {
+  struct stat entry_info;
+  int stat_success;
+  if (follow_links) {
+    stat_success = NO_RETRY_EXPECTED(stat(pathname, &entry_info));
+  } else {
+    stat_success = NO_RETRY_EXPECTED(lstat(pathname, &entry_info));
+  }
+  if (stat_success == -1) {
+    return File::kDoesNotExist;
+  }
+  if (S_ISDIR(entry_info.st_mode)) {
+    return File::kIsDirectory;
+  }
+  if (S_ISREG(entry_info.st_mode)) {
+    return File::kIsFile;
+  }
+  if (S_ISLNK(entry_info.st_mode)) {
+    return File::kIsLink;
+  }
+  return File::kDoesNotExist;
+}
+
+
+File::Identical File::AreIdentical(const char* file_1, const char* file_2) {
+  struct stat file_1_info;
+  struct stat file_2_info;
+  if ((NO_RETRY_EXPECTED(lstat(file_1, &file_1_info)) == -1) ||
+      (NO_RETRY_EXPECTED(lstat(file_2, &file_2_info)) == -1)) {
+    return File::kError;
+  }
+  return ((file_1_info.st_ino == file_2_info.st_ino) &&
+          (file_1_info.st_dev == file_2_info.st_dev)) ?
+      File::kIdentical :
+      File::kDifferent;
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // defined(TARGET_OS_FUCHSIA)
diff --git a/runtime/bin/file_system_watcher_fuchsia.cc b/runtime/bin/file_system_watcher_fuchsia.cc
new file mode 100644
index 0000000..abfbaa8
--- /dev/null
+++ b/runtime/bin/file_system_watcher_fuchsia.cc
@@ -0,0 +1,60 @@
+// 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.
+
+#if !defined(DART_IO_DISABLED)
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_FUCHSIA)
+
+#include "bin/file_system_watcher.h"
+
+namespace dart {
+namespace bin {
+
+Dart_Handle FileSystemWatcher::ReadEvents(intptr_t id, intptr_t path_id) {
+  UNIMPLEMENTED();
+  return DartUtils::NewDartOSError();
+}
+
+
+intptr_t FileSystemWatcher::GetSocketId(intptr_t id, intptr_t path_id) {
+  UNIMPLEMENTED();
+  return -1;
+}
+
+
+bool FileSystemWatcher::IsSupported() {
+  return false;
+}
+
+
+void FileSystemWatcher::UnwatchPath(intptr_t id, intptr_t path_id) {
+  UNIMPLEMENTED();
+}
+
+
+intptr_t FileSystemWatcher::Init() {
+  return 0;
+}
+
+
+void FileSystemWatcher::Close(intptr_t id) {
+  UNIMPLEMENTED();
+}
+
+
+intptr_t FileSystemWatcher::WatchPath(intptr_t id,
+                                      const char* path,
+                                      int events,
+                                      bool recursive) {
+  UNIMPLEMENTED();
+  return -1;
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // defined(TARGET_OS_FUCHSIA)
+
+#endif  // !defined(DART_IO_DISABLED)
diff --git a/runtime/bin/fuchsia_test.cc b/runtime/bin/fuchsia_test.cc
index 802ff31..d063612 100644
--- a/runtime/bin/fuchsia_test.cc
+++ b/runtime/bin/fuchsia_test.cc
@@ -2,23 +2,152 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+#include <dart_api.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 
-#include <dart_api.h>
+#include "bin/log.h"
+#include "platform/assert.h"
 
-int main(void) {
-  fprintf(stderr, "Calling Dart_SetVMFlags\n");
-  fflush(stderr);
-  if (!Dart_SetVMFlags(0, NULL)) {
-    fprintf(stderr, "Failed to set flags\n");
-    fflush(stderr);
-    return -1;
+const char* kBuiltinScript =
+    "_printString(String line) native \"Builtin_PrintString\";\n"
+    "_getPrintClosure() => _printString;\n";
+
+const char* kHelloWorldScript = "main() { print(\"Hello, Fuchsia!\"); }";
+
+namespace dart {
+namespace bin {
+
+// vm_isolate_snapshot_buffer points to a snapshot for the vm isolate if we
+// link in a snapshot otherwise it is initialized to NULL.
+extern const uint8_t* vm_isolate_snapshot_buffer;
+
+// isolate_snapshot_buffer points to a snapshot for an isolate if we link in a
+// snapshot otherwise it is initialized to NULL.
+extern const uint8_t* isolate_snapshot_buffer;
+
+static void Builtin_PrintString(Dart_NativeArguments args) {
+  intptr_t length = 0;
+  uint8_t* chars = NULL;
+  Dart_Handle str = Dart_GetNativeArgument(args, 0);
+  Dart_Handle result = Dart_StringToUTF8(str, &chars, &length);
+  if (Dart_IsError(result)) {
+    Dart_PropagateError(result);
   }
-  fprintf(stderr, "Calling Dart_Initialize\n");
-  fflush(stderr);
+  // Uses fwrite to support printing NUL bytes.
+  intptr_t res = fwrite(chars, 1, length, stdout);
+  ASSERT(res == length);
+  fputs("\n", stdout);
+  fflush(stdout);
+}
+
+static Dart_NativeFunction NativeLookup(Dart_Handle name,
+                                        int argument_count,
+                                        bool* auto_setup_scope) {
+  const char* function_name = NULL;
+  Dart_Handle err = Dart_StringToCString(name, &function_name);
+  DART_CHECK_VALID(err);
+  *auto_setup_scope = true;
+  if (strcmp(function_name, "Builtin_PrintString") == 0) {
+    return reinterpret_cast<Dart_NativeFunction>(Builtin_PrintString);
+  }
+  return NULL;
+}
+
+static const uint8_t* NativeSymbol(Dart_NativeFunction nf) {
+  if (reinterpret_cast<Dart_NativeFunction>(Builtin_PrintString) == nf) {
+    return reinterpret_cast<const uint8_t*>("Builtin_PrintString");
+  }
+  return NULL;
+}
+
+static Dart_Handle PrepareBuiltinLibrary(const char* script) {
+  Log::Print("Creating builtin library uri\n");
+  Dart_Handle builtin_uri = Dart_NewStringFromCString("builtin_uri");
+  DART_CHECK_VALID(builtin_uri);
+
+  Log::Print("Creating builtin library script string\n");
+  Dart_Handle builtin_script = Dart_NewStringFromCString(script);
+  DART_CHECK_VALID(builtin_script);
+
+  Log::Print("Loading builtin library\n");
+  Dart_Handle status = Dart_LoadLibrary(builtin_uri, builtin_script, 0, 0);
+  DART_CHECK_VALID(status);
+
+  Log::Print("Looking up builtin library\n");
+  Dart_Handle builtin_library = Dart_LookupLibrary(builtin_uri);
+  DART_CHECK_VALID(builtin_library);
+
+  Log::Print("Setting up native resolver for builtin library\n");
+  status = Dart_SetNativeResolver(builtin_library, NativeLookup, NativeSymbol);
+  DART_CHECK_VALID(status);
+
+  return builtin_library;
+}
+
+static Dart_Handle PrepareScriptLibrary(const char* script) {
+  Log::Print("Creating script URI string\n");
+  Dart_Handle script_uri = Dart_NewStringFromCString("script_uri");
+  DART_CHECK_VALID(script_uri);
+
+  Log::Print("Creating script string\n");
+  Dart_Handle script_string = Dart_NewStringFromCString(script);
+  DART_CHECK_VALID(script_string);
+
+  Log::Print("Loading script into new library\n");
+  Dart_Handle status = Dart_LoadLibrary(script_uri, script_string, 0, 0);
+  DART_CHECK_VALID(status);
+
+  Log::Print("Looking up script library\n");
+  Dart_Handle library = Dart_LookupLibrary(script_uri);
+  DART_CHECK_VALID(library);
+
+  return library;
+}
+
+static Dart_Handle LoadInternalLibrary() {
+  Log::Print("Creating internal library uri string\n");
+  Dart_Handle url = Dart_NewStringFromCString("dart:_internal");
+  DART_CHECK_VALID(url);
+
+  Log::Print("Looking up internal library\n");
+  Dart_Handle internal_library = Dart_LookupLibrary(url);
+  DART_CHECK_VALID(internal_library);
+
+  return internal_library;
+}
+
+static void PreparePrintClosure(Dart_Handle builtin_library,
+                                Dart_Handle internal_library) {
+  Log::Print("Creating _getPrintClosure name string\n");
+  Dart_Handle get_print_closure_name =
+      Dart_NewStringFromCString("_getPrintClosure");
+  DART_CHECK_VALID(get_print_closure_name);
+
+  Log::Print("Invoking _getPrintClosure\n");
+  Dart_Handle print_closure = Dart_Invoke(
+      builtin_library, get_print_closure_name, 0, NULL);
+  DART_CHECK_VALID(print_closure);
+
+  Log::Print("Creating _printClosure name string\n");
+  Dart_Handle print_closure_name = Dart_NewStringFromCString("_printClosure");
+  DART_CHECK_VALID(print_closure_name);
+
+  Log::Print("Setting _printClosure to result of _getPrintClosure\n");
+  Dart_Handle status = Dart_SetField(
+      internal_library, print_closure_name, print_closure);
+  DART_CHECK_VALID(status);
+}
+
+int Main() {
+  Log::Print("Calling Dart_SetVMFlags\n");
+  if (!Dart_SetVMFlags(0, NULL)) {
+    FATAL("Failed to set flags\n");
+  }
+  Log::Print("Calling Dart_Initialize\n");
   char* error = Dart_Initialize(
-      NULL, NULL, NULL,
+      vm_isolate_snapshot_buffer, NULL, NULL,
       NULL, NULL, NULL, NULL,
       NULL,
       NULL,
@@ -28,12 +157,63 @@
       NULL,
       NULL);
   if (error != NULL) {
-    fprintf(stderr, "VM initialization failed: %s\n", error);
-    fflush(stderr);
-    free(error);
-    return -1;
+    FATAL1("VM initialization failed: %s\n", error);
   }
-  fprintf(stderr, "Success!\n");
-  fflush(stderr);
+
+  Log::Print("Creating Isolate\n");
+  Dart_Isolate isolate = Dart_CreateIsolate(
+      "script_uri",
+      "main",
+      isolate_snapshot_buffer,
+      NULL,
+      NULL,
+      &error);
+  if (isolate == NULL) {
+    FATAL1("Dart_CreateIsolate failed: %s\n", error);
+  }
+
+  Log::Print("Entering Scope\n");
+  Dart_EnterScope();
+
+  Dart_Handle library = PrepareScriptLibrary(kHelloWorldScript);
+
+  Dart_Handle builtin_library = PrepareBuiltinLibrary(kBuiltinScript);
+
+  Log::Print("Finalizing loading\n");
+  Dart_Handle status = Dart_FinalizeLoading(false);
+  DART_CHECK_VALID(status);
+
+  Dart_Handle internal_library = LoadInternalLibrary();
+
+  PreparePrintClosure(builtin_library, internal_library);
+
+  Log::Print("Creating main string\n");
+  Dart_Handle main_name = Dart_NewStringFromCString("main");
+  DART_CHECK_VALID(main_name);
+
+  Log::Print("---- Invoking main() ----\n");
+  status = Dart_Invoke(library, main_name, 0, NULL);
+  DART_CHECK_VALID(status);
+  Log::Print("---- main() returned ----\n");
+
+  Log::Print("Exiting Scope\n");
+  Dart_ExitScope();
+  Log::Print("Shutting down the isolate\n");
+  Dart_ShutdownIsolate();
+
+  Log::Print("Calling Dart_Cleanup\n");
+  error = Dart_Cleanup();
+  if (error != NULL) {
+    FATAL1("VM Cleanup failed: %s\n", error);
+  }
+
+  Log::Print("Success!\n");
   return 0;
 }
+
+}  // namespace bin
+}  // namespace dart
+
+int main(void) {
+  return dart::bin::Main();
+}
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index cc8bb06..d75a347 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -1169,7 +1169,10 @@
   CHECK_RESULT(result);
   ASSERT(Dart_IsServiceIsolate(isolate));
   // Load embedder specific bits and return. Will not start http server.
-  if (!VmService::Setup("127.0.0.1", -1, false /* running_precompiled */)) {
+  if (!VmService::Setup("127.0.0.1",
+                        -1,
+                        false /* running_precompiled */,
+                        false /* server dev mode */)) {
     *error = strdup(VmService::GetErrorMessage());
     return NULL;
   }
@@ -1201,6 +1204,7 @@
   }
 
   Thread::InitOnce();
+  Loader::InitOnce();
   DartUtils::SetOriginalWorkingDirectory();
   // Start event handler.
   TimerUtils::InitOnce();
diff --git a/runtime/bin/io_impl_sources.gypi b/runtime/bin/io_impl_sources.gypi
index c0de4c23..1e5a1a4 100644
--- a/runtime/bin/io_impl_sources.gypi
+++ b/runtime/bin/io_impl_sources.gypi
@@ -10,6 +10,8 @@
     'eventhandler.h',
     'eventhandler_android.cc',
     'eventhandler_android.h',
+    'eventhandler_fuchsia.cc',
+    'eventhandler_fuchsia.h',
     'eventhandler_linux.cc',
     'eventhandler_linux.h',
     'eventhandler_macos.cc',
@@ -20,6 +22,7 @@
     'file_system_watcher.cc',
     'file_system_watcher.h',
     'file_system_watcher_android.cc',
+    'file_system_watcher_fuchsia.cc',
     'file_system_watcher_linux.cc',
     'file_system_watcher_macos.cc',
     'file_system_watcher_unsupported.cc',
@@ -35,6 +38,7 @@
     'platform.cc',
     'platform.h',
     'platform_android.cc',
+    'platform_fuchsia.cc',
     'platform_linux.cc',
     'platform_macos.cc',
     'platform_unsupported.cc',
@@ -42,12 +46,12 @@
     'process.cc',
     'process.h',
     'process_android.cc',
+    'process_fuchsia.cc',
     'process_linux.cc',
     'process_macos.cc',
     'process_unsupported.cc',
     'process_win.cc',
     'reference_counting.h',
-    '../../third_party/root_certificates/root_certificates.cc',
     'root_certificates_unsupported.cc',
     'secure_socket.h',
     'secure_socket_boringssl.cc',
@@ -61,6 +65,8 @@
     'socket.h',
     'socket_android.cc',
     'socket_android.h',
+    'socket_fuchsia.cc',
+    'socket_fuchsia.h',
     'socket_linux.cc',
     'socket_linux.h',
     'socket_macos.cc',
@@ -71,6 +77,7 @@
     'stdio.cc',
     'stdio.h',
     'stdio_android.cc',
+    'stdio_fuchsia.cc',
     'stdio_linux.cc',
     'stdio_macos.cc',
     'stdio_unsupported.cc',
diff --git a/runtime/bin/loader.cc b/runtime/bin/loader.cc
index 6a99a4e..cf6f4ec 100644
--- a/runtime/bin/loader.cc
+++ b/runtime/bin/loader.cc
@@ -661,7 +661,12 @@
 }
 
 
-Mutex Loader::loader_infos_lock_;
+void Loader::InitOnce() {
+  loader_infos_lock_ = new Mutex();
+}
+
+
+Mutex* Loader::loader_infos_lock_;
 Loader::LoaderInfo* Loader::loader_infos_ = NULL;
 intptr_t Loader::loader_infos_length_ = 0;
 intptr_t Loader::loader_infos_capacity_ = 0;
@@ -672,7 +677,7 @@
 // correct loader.
 // This happens whenever an isolate begins loading.
 void Loader::AddLoader(Dart_Port port, IsolateData* isolate_data) {
-  MutexLocker ml(&loader_infos_lock_);
+  MutexLocker ml(loader_infos_lock_);
   ASSERT(LoaderForLocked(port) == NULL);
   if (loader_infos_length_ == loader_infos_capacity_) {
     // Grow to an initial capacity or double in size.
@@ -700,7 +705,7 @@
 // Remove |port| from the map.
 // This happens once an isolate has finished loading.
 void Loader::RemoveLoader(Dart_Port port) {
-  MutexLocker ml(&loader_infos_lock_);
+  MutexLocker ml(loader_infos_lock_);
   const intptr_t index = LoaderIndexFor(port);
   ASSERT(index >= 0);
   const intptr_t last = loader_infos_length_ - 1;
@@ -733,14 +738,14 @@
 
 
 Loader* Loader::LoaderFor(Dart_Port port) {
-  MutexLocker ml(&loader_infos_lock_);
+  MutexLocker ml(loader_infos_lock_);
   return LoaderForLocked(port);
 }
 
 
 void Loader::NativeMessageHandler(Dart_Port dest_port_id,
                                   Dart_CObject* message) {
-  MutexLocker ml(&loader_infos_lock_);
+  MutexLocker ml(loader_infos_lock_);
   Loader* loader = LoaderForLocked(dest_port_id);
   if (loader == NULL) {
     return;
diff --git a/runtime/bin/loader.h b/runtime/bin/loader.h
index 034138e..97e87a4 100644
--- a/runtime/bin/loader.h
+++ b/runtime/bin/loader.h
@@ -37,6 +37,8 @@
     return error_;
   }
 
+  static void InitOnce();
+
  private:
   // The port assigned to our native message handler.
   Dart_Port port_;
@@ -124,7 +126,7 @@
   };
 
   // The map of active loaders.
-  static Mutex loader_infos_lock_;
+  static Mutex* loader_infos_lock_;
   static LoaderInfo* loader_infos_;
   static intptr_t loader_infos_length_;
   static intptr_t loader_infos_capacity_;
diff --git a/runtime/bin/log_fuchsia.cc b/runtime/bin/log_fuchsia.cc
new file mode 100644
index 0000000..0c1f7af
--- /dev/null
+++ b/runtime/bin/log_fuchsia.cc
@@ -0,0 +1,28 @@
+// 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.
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_FUCHSIA)
+
+#include "bin/log.h"
+
+#include <stdio.h>  // NOLINT
+
+namespace dart {
+namespace bin {
+
+void Log::VPrint(const char* format, va_list args) {
+  vfprintf(stdout, format, args);
+  fflush(stdout);
+}
+
+void Log::VPrintErr(const char* format, va_list args) {
+  vfprintf(stderr, format, args);
+  fflush(stdout);
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // defined(TARGET_OS_FUCHSIA)
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index a1f859a..89c752b 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -119,7 +119,9 @@
 // The 0 port is a magic value which results in the first available port
 // being allocated.
 static int vm_service_server_port = -1;
-
+// True when we are running in development mode and cross origin security
+// checks are disabled.
+static bool vm_service_dev_mode = false;
 
 // Exit code indicating an API error.
 static const int kApiErrorExitCode = 253;
@@ -130,10 +132,6 @@
 // Exit code indicating a vm restart request.  Never returned to the user.
 static const int kRestartRequestExitCode = 1000;
 
-// Global flag that is used to indicate that the VM should do a clean
-// shutdown.
-static bool do_vm_shutdown = true;
-
 static void ErrorExit(int exit_code, const char* format, ...) {
   va_list arguments;
   va_start(arguments, format);
@@ -153,9 +151,7 @@
     free(error);
   }
 
-  if (do_vm_shutdown) {
-    EventHandler::Stop();
-  }
+  EventHandler::Stop();
   Platform::Exit(exit_code);
 }
 
@@ -393,6 +389,16 @@
 }
 
 
+static bool ProcessDisableServiceOriginCheckOption(
+    const char* option_value, CommandLineOptions* vm_options) {
+  ASSERT(option_value != NULL);
+  Log::PrintErr("WARNING: You are running with the service protocol in an "
+                "insecure mode.\n");
+  vm_service_dev_mode = true;
+  return true;
+}
+
+
 static bool ProcessObserveOption(const char* option_value,
                                  CommandLineOptions* vm_options) {
   ASSERT(option_value != NULL);
@@ -434,45 +440,18 @@
   // Identity reload.
   vm_options->AddArgument("--identity_reload");
   // Start reloading quickly.
-  vm_options->AddArgument("--reload_every=50");
+  vm_options->AddArgument("--reload_every=4");
   // Reload from optimized and unoptimized code.
   vm_options->AddArgument("--reload_every_optimized=false");
   // Reload less frequently as time goes on.
   vm_options->AddArgument("--reload_every_back_off");
-  // Ensure that an isolate has reloaded once.
+  // Ensure that every isolate has reloaded once before exiting.
   vm_options->AddArgument("--check_reloaded");
 
   return true;
 }
 
 
-static bool ProcessShutdownOption(const char* arg,
-                                  CommandLineOptions* vm_options) {
-  ASSERT(arg != NULL);
-  if (*arg == '\0') {
-    do_vm_shutdown = true;
-    vm_options->AddArgument("--shutdown");
-    return true;
-  }
-
-  if ((*arg != '=') && (*arg != ':')) {
-    return false;
-  }
-
-  if (strcmp(arg + 1, "true") == 0) {
-    do_vm_shutdown = true;
-    vm_options->AddArgument("--shutdown");
-    return true;
-  } else if (strcmp(arg + 1, "false") == 0) {
-    do_vm_shutdown = false;
-    vm_options->AddArgument("--no-shutdown");
-    return true;
-  }
-
-  return false;
-}
-
-
 static struct {
   const char* option_name;
   bool (*process)(const char* option, CommandLineOptions* vm_options);
@@ -490,8 +469,8 @@
   // VM specific options to the standalone dart program.
   { "--compile_all", ProcessCompileAllOption },
   { "--enable-vm-service", ProcessEnableVmServiceOption },
+  { "--disable-service-origin-check", ProcessDisableServiceOriginCheckOption },
   { "--observe", ProcessObserveOption },
-  { "--shutdown", ProcessShutdownOption },
   { "--snapshot=", ProcessSnapshotFilenameOption },
   { "--snapshot-kind=", ProcessSnapshotKindOption },
   { "--run-app-snapshot=", ProcessRunAppSnapshotOption },
@@ -766,7 +745,8 @@
     bool skip_library_load = run_app_snapshot;
     if (!VmService::Setup(vm_service_server_ip,
                           vm_service_server_port,
-                          skip_library_load)) {
+                          skip_library_load,
+                          vm_service_dev_mode)) {
       *error = strdup(VmService::GetErrorMessage());
       return NULL;
     }
@@ -1131,7 +1111,7 @@
   }
   DartUtils::CloseFile(file);
   if (concat != NULL) {
-    delete concat;
+    delete[] concat;
   }
 }
 
@@ -1160,7 +1140,7 @@
     Platform::Exit(kErrorExitCode);
   }
   if (concat != NULL) {
-    delete concat;
+    delete[] concat;
   }
 }
 
@@ -1377,9 +1357,7 @@
       Log::PrintErr("VM cleanup failed: %s\n", error);
       free(error);
     }
-    if (do_vm_shutdown) {
-      EventHandler::Stop();
-    }
+    EventHandler::Stop();
     Platform::Exit((exit_code != 0) ? exit_code : kErrorExitCode);
   }
   delete [] isolate_name;
@@ -1521,7 +1499,7 @@
 
 
 // Observatory assets are only needed in the regular dart binary.
-#if !defined(DART_PRECOMPILER)
+#if !defined(DART_PRECOMPILER) && !defined(NO_OBSERVATORY)
 extern unsigned int observatory_assets_archive_len;
 extern const uint8_t* observatory_assets_archive;
 
@@ -1610,7 +1588,7 @@
 
 void main(int argc, char** argv) {
   char* script_name;
-  const int EXTRA_VM_ARGUMENTS = 2;
+  const int EXTRA_VM_ARGUMENTS = 8;
   CommandLineOptions vm_options(argc + EXTRA_VM_ARGUMENTS);
   CommandLineOptions dart_options(argc);
   bool print_flags_seen = false;
@@ -1653,6 +1631,8 @@
 
   Thread::InitOnce();
 
+  Loader::InitOnce();
+
   if (!DartUtils::SetOriginalWorkingDirectory()) {
     OSError err;
     fprintf(stderr, "Error determining current directory: %s\n", err.message());
@@ -1717,9 +1697,7 @@
       DartUtils::EntropySource,
       GetVMServiceAssetsArchiveCallback);
   if (error != NULL) {
-    if (do_vm_shutdown) {
-      EventHandler::Stop();
-    }
+    EventHandler::Stop();
     fprintf(stderr, "VM initialization failed: %s\n", error);
     fflush(stderr);
     free(error);
@@ -1744,9 +1722,7 @@
     Log::PrintErr("VM cleanup failed: %s\n", error);
     free(error);
   }
-  if (do_vm_shutdown) {
-    EventHandler::Stop();
-  }
+  EventHandler::Stop();
 
   // Free copied argument strings if converted.
   if (argv_converted) {
diff --git a/runtime/bin/platform_fuchsia.cc b/runtime/bin/platform_fuchsia.cc
new file mode 100644
index 0000000..ace3c37
--- /dev/null
+++ b/runtime/bin/platform_fuchsia.cc
@@ -0,0 +1,75 @@
+// 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.
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_FUCHSIA)
+
+#include "bin/platform.h"
+
+#include <runtime/sysinfo.h>
+#include <string.h>  // NOLINT
+#include <unistd.h>  // NOLINT
+
+#include "bin/fdutils.h"
+#include "bin/file.h"
+
+namespace dart {
+namespace bin {
+
+const char* Platform::executable_name_ = NULL;
+char* Platform::resolved_executable_name_ = NULL;
+int Platform::script_index_ = 1;
+char** Platform::argv_ = NULL;
+
+bool Platform::Initialize() {
+  return true;
+}
+
+
+int Platform::NumberOfProcessors() {
+  return mxr_get_nprocs();
+}
+
+
+const char* Platform::OperatingSystem() {
+  return "fuchsia";
+}
+
+
+const char* Platform::LibraryPrefix() {
+  return "lib";
+}
+
+
+const char* Platform::LibraryExtension() {
+  return "so";
+}
+
+
+bool Platform::LocalHostname(char *buffer, intptr_t buffer_length) {
+  return gethostname(buffer, buffer_length) == 0;
+}
+
+
+char** Platform::Environment(intptr_t* count) {
+  char** result =
+      reinterpret_cast<char**>(Dart_ScopeAllocate(1 * sizeof(*result)));
+  result[0] = NULL;
+  return result;
+}
+
+
+const char* Platform::ResolveExecutablePath() {
+  return "dart";
+}
+
+
+void Platform::Exit(int exit_code) {
+  exit(exit_code);
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // defined(TARGET_OS_FUCHSIA)
diff --git a/runtime/bin/process_fuchsia.cc b/runtime/bin/process_fuchsia.cc
new file mode 100644
index 0000000..5858800
--- /dev/null
+++ b/runtime/bin/process_fuchsia.cc
@@ -0,0 +1,77 @@
+// 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.
+
+#if !defined(DART_IO_DISABLED)
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_FUCHSIA)
+
+#include "bin/process.h"
+
+#include "bin/lockers.h"
+#include "platform/assert.h"
+
+
+namespace dart {
+namespace bin {
+
+int Process::global_exit_code_ = 0;
+Mutex* Process::global_exit_code_mutex_ = new Mutex();
+
+void Process::TerminateExitCodeHandler() {
+}
+
+intptr_t Process::CurrentProcessId() {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+intptr_t Process::SetSignalHandler(intptr_t signal) {
+  UNIMPLEMENTED();
+  return -1;
+}
+
+
+void Process::ClearSignalHandler(intptr_t signal) {
+  UNIMPLEMENTED();
+}
+
+bool Process::Wait(intptr_t pid,
+                   intptr_t in,
+                   intptr_t out,
+                   intptr_t err,
+                   intptr_t exit_event,
+                   ProcessResult* result) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+bool Process::Kill(intptr_t id, int signal) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+int Process::Start(const char* path,
+                   char* arguments[],
+                   intptr_t arguments_length,
+                   const char* working_directory,
+                   char* environment[],
+                   intptr_t environment_length,
+                   ProcessStartMode mode,
+                   intptr_t* in,
+                   intptr_t* out,
+                   intptr_t* err,
+                   intptr_t* id,
+                   intptr_t* exit_event,
+                   char** os_error_message) {
+  UNIMPLEMENTED();
+  return -1;
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // defined(TARGET_OS_FUCHSIA)
+
+#endif  // !defined(DART_IO_DISABLED)
diff --git a/runtime/bin/socket.h b/runtime/bin/socket.h
index bd8ed4b..0b17706 100644
--- a/runtime/bin/socket.h
+++ b/runtime/bin/socket.h
@@ -13,6 +13,8 @@
 // Declare the OS-specific types ahead of defining the generic class.
 #if defined(TARGET_OS_ANDROID)
 #include "bin/socket_android.h"
+#elif defined(TARGET_OS_FUCHSIA)
+#include "bin/socket_fuchsia.h"
 #elif defined(TARGET_OS_LINUX)
 #include "bin/socket_linux.h"
 #elif defined(TARGET_OS_MACOS)
diff --git a/runtime/bin/socket_fuchsia.cc b/runtime/bin/socket_fuchsia.cc
new file mode 100644
index 0000000..78b5071
--- /dev/null
+++ b/runtime/bin/socket_fuchsia.cc
@@ -0,0 +1,242 @@
+// 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.
+
+#if !defined(DART_IO_DISABLED)
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_FUCHSIA)
+
+#include "bin/socket.h"
+#include "bin/socket_fuchsia.h"
+
+#include "bin/file.h"
+
+namespace dart {
+namespace bin {
+
+SocketAddress::SocketAddress(struct sockaddr* sa) {
+  UNIMPLEMENTED();
+}
+
+
+bool Socket::FormatNumericAddress(const RawAddr& addr, char* address, int len) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+bool Socket::Initialize() {
+  UNIMPLEMENTED();
+  return true;
+}
+
+
+intptr_t Socket::CreateConnect(const RawAddr& addr) {
+  UNIMPLEMENTED();
+  return -1;
+}
+
+
+intptr_t Socket::CreateBindConnect(const RawAddr& addr,
+                                   const RawAddr& source_addr) {
+  UNIMPLEMENTED();
+  return -1;
+}
+
+
+intptr_t Socket::Available(intptr_t fd) {
+  UNIMPLEMENTED();
+  return -1;
+}
+
+
+intptr_t Socket::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
+  UNIMPLEMENTED();
+  return -1;
+}
+
+
+intptr_t Socket::RecvFrom(
+    intptr_t fd, void* buffer, intptr_t num_bytes, RawAddr* addr) {
+  UNIMPLEMENTED();
+  return -1;
+}
+
+
+intptr_t Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) {
+  UNIMPLEMENTED();
+  return -1;
+}
+
+
+intptr_t Socket::SendTo(
+    intptr_t fd, const void* buffer, intptr_t num_bytes, const RawAddr& addr) {
+  UNIMPLEMENTED();
+  return -1;
+}
+
+
+intptr_t Socket::GetPort(intptr_t fd) {
+  UNIMPLEMENTED();
+  return -1;
+}
+
+
+SocketAddress* Socket::GetRemotePeer(intptr_t fd, intptr_t* port) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void Socket::GetError(intptr_t fd, OSError* os_error) {
+  UNIMPLEMENTED();
+}
+
+
+int Socket::GetType(intptr_t fd) {
+  UNIMPLEMENTED();
+  return File::kOther;
+}
+
+
+intptr_t Socket::GetStdioHandle(intptr_t num) {
+  UNIMPLEMENTED();
+  return num;
+}
+
+
+AddressList<SocketAddress>* Socket::LookupAddress(const char* host,
+                                                  int type,
+                                                  OSError** os_error) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+bool Socket::ReverseLookup(const RawAddr& addr,
+                           char* host,
+                           intptr_t host_len,
+                           OSError** os_error) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+bool Socket::ParseAddress(int type, const char* address, RawAddr* addr) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+intptr_t Socket::CreateBindDatagram(const RawAddr& addr, bool reuseAddress) {
+  UNIMPLEMENTED();
+  return -1;
+}
+
+
+bool Socket::ListInterfacesSupported() {
+  return false;
+}
+
+
+AddressList<InterfaceSocketAddress>* Socket::ListInterfaces(
+    int type,
+    OSError** os_error) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+intptr_t ServerSocket::CreateBindListen(const RawAddr& addr,
+                                        intptr_t backlog,
+                                        bool v6_only) {
+  UNIMPLEMENTED();
+  return -1;
+}
+
+
+bool ServerSocket::StartAccept(intptr_t fd) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+intptr_t ServerSocket::Accept(intptr_t fd) {
+  UNIMPLEMENTED();
+  return -1;
+}
+
+
+void Socket::Close(intptr_t fd) {
+  UNIMPLEMENTED();
+}
+
+
+bool Socket::GetNoDelay(intptr_t fd, bool* enabled) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+bool Socket::SetNoDelay(intptr_t fd, bool enabled) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+bool Socket::GetMulticastLoop(intptr_t fd, intptr_t protocol, bool* enabled) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+bool Socket::SetMulticastLoop(intptr_t fd, intptr_t protocol, bool enabled) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+bool Socket::GetMulticastHops(intptr_t fd, intptr_t protocol, int* value) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+bool Socket::SetMulticastHops(intptr_t fd, intptr_t protocol, int value) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+bool Socket::GetBroadcast(intptr_t fd, bool* enabled) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+bool Socket::SetBroadcast(intptr_t fd, bool enabled) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+bool Socket::JoinMulticast(
+    intptr_t fd, const RawAddr& addr, const RawAddr&, int interfaceIndex) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+bool Socket::LeaveMulticast(
+    intptr_t fd, const RawAddr& addr, const RawAddr&, int interfaceIndex) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // defined(TARGET_OS_FUCHSIA)
+
+#endif  // !defined(DART_IO_DISABLED)
diff --git a/runtime/bin/socket_fuchsia.h b/runtime/bin/socket_fuchsia.h
new file mode 100644
index 0000000..82f8916
--- /dev/null
+++ b/runtime/bin/socket_fuchsia.h
@@ -0,0 +1,12 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef BIN_SOCKET_FUCHSIA_H_
+#define BIN_SOCKET_FUCHSIA_H_
+
+#if !defined(BIN_SOCKET_H_)
+#error Do not include socket_fuchsia.h directly. Use socket.h.
+#endif
+
+#endif  // BIN_SOCKET_FUCHSIA_H_
diff --git a/runtime/bin/stdio_fuchsia.cc b/runtime/bin/stdio_fuchsia.cc
new file mode 100644
index 0000000..e297499
--- /dev/null
+++ b/runtime/bin/stdio_fuchsia.cc
@@ -0,0 +1,53 @@
+// 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.
+
+#if !defined(DART_IO_DISABLED)
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_FUCHSIA)
+
+#include "bin/stdio.h"
+
+namespace dart {
+namespace bin {
+
+int Stdin::ReadByte() {
+  UNIMPLEMENTED();
+  return -1;
+}
+
+
+bool Stdin::GetEchoMode() {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+void Stdin::SetEchoMode(bool enabled) {
+  UNIMPLEMENTED();
+}
+
+
+bool Stdin::GetLineMode() {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+void Stdin::SetLineMode(bool enabled) {
+  UNIMPLEMENTED();
+}
+
+
+bool Stdout::GetTerminalSize(intptr_t fd, int size[2]) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // defined(TARGET_OS_FUCHSIA)
+
+#endif  // !defined(DART_IO_DISABLED)
diff --git a/runtime/bin/thread.h b/runtime/bin/thread.h
index 979c77f..37a4b9f 100644
--- a/runtime/bin/thread.h
+++ b/runtime/bin/thread.h
@@ -18,6 +18,8 @@
 // Declare the OS-specific types ahead of defining the generic classes.
 #if defined(TARGET_OS_ANDROID)
 #include "bin/thread_android.h"
+#elif defined(TARGET_OS_FUCHSIA)
+#include "bin/thread_fuchsia.h"
 #elif defined(TARGET_OS_LINUX)
 #include "bin/thread_linux.h"
 #elif defined(TARGET_OS_MACOS)
diff --git a/runtime/bin/thread_fuchsia.cc b/runtime/bin/thread_fuchsia.cc
new file mode 100644
index 0000000..57f4cd0
--- /dev/null
+++ b/runtime/bin/thread_fuchsia.cc
@@ -0,0 +1,331 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_FUCHSIA)
+
+#include "bin/thread.h"
+#include "bin/thread_fuchsia.h"
+
+#include <errno.h>  // NOLINT
+#include <sys/resource.h>  // NOLINT
+#include <sys/time.h>  // NOLINT
+
+#include "platform/assert.h"
+#include "platform/utils.h"
+
+namespace dart {
+namespace bin {
+
+#define VALIDATE_PTHREAD_RESULT(result) \
+  if (result != 0) { \
+    const int kBufferSize = 1024; \
+    char error_buf[kBufferSize]; \
+    FATAL2("pthread error: %d (%s)", result, \
+           Utils::StrError(result, error_buf, kBufferSize)); \
+  }
+
+
+#ifdef DEBUG
+#define RETURN_ON_PTHREAD_FAILURE(result) \
+  if (result != 0) { \
+    const int kBufferSize = 1024; \
+    char error_buf[kBufferSize]; \
+    fprintf(stderr, "%s:%d: pthread error: %d (%s)\n", \
+            __FILE__, __LINE__, result, \
+            Utils::StrError(result, error_buf, kBufferSize)); \
+    return result; \
+  }
+#else
+#define RETURN_ON_PTHREAD_FAILURE(result) \
+  if (result != 0) { \
+    return result; \
+  }
+#endif
+
+
+static void ComputeTimeSpecMicros(struct timespec* ts, int64_t micros) {
+  int64_t secs = micros / kMicrosecondsPerSecond;
+  int64_t nanos =
+      (micros - (secs * kMicrosecondsPerSecond)) * kNanosecondsPerMicrosecond;
+  int result = clock_gettime(CLOCK_MONOTONIC, ts);
+  ASSERT(result == 0);
+  ts->tv_sec += secs;
+  ts->tv_nsec += nanos;
+  if (ts->tv_nsec >= kNanosecondsPerSecond) {
+    ts->tv_sec += 1;
+    ts->tv_nsec -= kNanosecondsPerSecond;
+  }
+}
+
+
+class ThreadStartData {
+ public:
+  ThreadStartData(Thread::ThreadStartFunction function,
+                  uword parameter)
+      : function_(function), parameter_(parameter) {}
+
+  Thread::ThreadStartFunction function() const { return function_; }
+  uword parameter() const { return parameter_; }
+
+ private:
+  Thread::ThreadStartFunction function_;
+  uword parameter_;
+
+  DISALLOW_COPY_AND_ASSIGN(ThreadStartData);
+};
+
+
+// Dispatch to the thread start function provided by the caller. This trampoline
+// is used to ensure that the thread is properly destroyed if the thread just
+// exits.
+static void* ThreadStart(void* data_ptr) {
+  ThreadStartData* data = reinterpret_cast<ThreadStartData*>(data_ptr);
+
+  Thread::ThreadStartFunction function = data->function();
+  uword parameter = data->parameter();
+  delete data;
+
+  // Call the supplied thread start function handing it its parameters.
+  function(parameter);
+
+  return NULL;
+}
+
+
+int Thread::Start(ThreadStartFunction function, uword parameter) {
+  pthread_attr_t attr;
+  int result = pthread_attr_init(&attr);
+  RETURN_ON_PTHREAD_FAILURE(result);
+
+  result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+  RETURN_ON_PTHREAD_FAILURE(result);
+
+  result = pthread_attr_setstacksize(&attr, Thread::GetMaxStackSize());
+  RETURN_ON_PTHREAD_FAILURE(result);
+
+  ThreadStartData* data = new ThreadStartData(function, parameter);
+
+  pthread_t tid;
+  result = pthread_create(&tid, &attr, ThreadStart, data);
+  RETURN_ON_PTHREAD_FAILURE(result);
+
+  result = pthread_attr_destroy(&attr);
+  RETURN_ON_PTHREAD_FAILURE(result);
+
+  return 0;
+}
+
+
+const ThreadLocalKey Thread::kUnsetThreadLocalKey =
+    static_cast<pthread_key_t>(-1);
+const ThreadId Thread::kInvalidThreadId = static_cast<ThreadId>(0);
+
+ThreadLocalKey Thread::CreateThreadLocal() {
+  pthread_key_t key = kUnsetThreadLocalKey;
+  int result = pthread_key_create(&key, NULL);
+  VALIDATE_PTHREAD_RESULT(result);
+  ASSERT(key != kUnsetThreadLocalKey);
+  return key;
+}
+
+
+void Thread::DeleteThreadLocal(ThreadLocalKey key) {
+  ASSERT(key != kUnsetThreadLocalKey);
+  int result = pthread_key_delete(key);
+  VALIDATE_PTHREAD_RESULT(result);
+}
+
+
+void Thread::SetThreadLocal(ThreadLocalKey key, uword value) {
+  ASSERT(key != kUnsetThreadLocalKey);
+  int result = pthread_setspecific(key, reinterpret_cast<void*>(value));
+  VALIDATE_PTHREAD_RESULT(result);
+}
+
+
+intptr_t Thread::GetMaxStackSize() {
+  const int kStackSize = (128 * kWordSize * KB);
+  return kStackSize;
+}
+
+
+ThreadId Thread::GetCurrentThreadId() {
+  return pthread_self();
+}
+
+
+intptr_t Thread::ThreadIdToIntPtr(ThreadId id) {
+  ASSERT(sizeof(id) == sizeof(intptr_t));
+  return static_cast<intptr_t>(id);
+}
+
+
+bool Thread::Compare(ThreadId a, ThreadId b) {
+  return (pthread_equal(a, b) != 0);
+}
+
+
+void Thread::GetThreadCpuUsage(ThreadId thread_id, int64_t* cpu_usage) {
+  UNIMPLEMENTED();
+}
+
+
+void Thread::InitOnce() {
+  // Nothing to be done.
+}
+
+
+Mutex::Mutex() {
+  pthread_mutexattr_t attr;
+  int result = pthread_mutexattr_init(&attr);
+  VALIDATE_PTHREAD_RESULT(result);
+
+#if defined(DEBUG)
+  result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
+  VALIDATE_PTHREAD_RESULT(result);
+#endif  // defined(DEBUG)
+
+  result = pthread_mutex_init(data_.mutex(), &attr);
+  // Verify that creating a pthread_mutex succeeded.
+  VALIDATE_PTHREAD_RESULT(result);
+
+  result = pthread_mutexattr_destroy(&attr);
+  VALIDATE_PTHREAD_RESULT(result);
+}
+
+
+Mutex::~Mutex() {
+  int result = pthread_mutex_destroy(data_.mutex());
+  // Verify that the pthread_mutex was destroyed.
+  VALIDATE_PTHREAD_RESULT(result);
+}
+
+
+void Mutex::Lock() {
+  int result = pthread_mutex_lock(data_.mutex());
+  // Specifically check for dead lock to help debugging.
+  ASSERT(result != EDEADLK);
+  ASSERT(result == 0);  // Verify no other errors.
+  // TODO(iposva): Do we need to track lock owners?
+}
+
+
+bool Mutex::TryLock() {
+  int result = pthread_mutex_trylock(data_.mutex());
+  // Return false if the lock is busy and locking failed.
+  if (result == EBUSY) {
+    return false;
+  }
+  ASSERT(result == 0);  // Verify no other errors.
+  // TODO(iposva): Do we need to track lock owners?
+  return true;
+}
+
+
+void Mutex::Unlock() {
+  // TODO(iposva): Do we need to track lock owners?
+  int result = pthread_mutex_unlock(data_.mutex());
+  // Specifically check for wrong thread unlocking to aid debugging.
+  ASSERT(result != EPERM);
+  ASSERT(result == 0);  // Verify no other errors.
+}
+
+
+Monitor::Monitor() {
+  pthread_mutexattr_t mutex_attr;
+  int result = pthread_mutexattr_init(&mutex_attr);
+  VALIDATE_PTHREAD_RESULT(result);
+
+#if defined(DEBUG)
+  result = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
+  VALIDATE_PTHREAD_RESULT(result);
+#endif  // defined(DEBUG)
+
+  result = pthread_mutex_init(data_.mutex(), &mutex_attr);
+  VALIDATE_PTHREAD_RESULT(result);
+
+  result = pthread_mutexattr_destroy(&mutex_attr);
+  VALIDATE_PTHREAD_RESULT(result);
+
+  pthread_condattr_t cond_attr;
+  result = pthread_condattr_init(&cond_attr);
+  VALIDATE_PTHREAD_RESULT(result);
+
+  result = pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
+  VALIDATE_PTHREAD_RESULT(result);
+
+  result = pthread_cond_init(data_.cond(), &cond_attr);
+  VALIDATE_PTHREAD_RESULT(result);
+
+  result = pthread_condattr_destroy(&cond_attr);
+  VALIDATE_PTHREAD_RESULT(result);
+}
+
+
+Monitor::~Monitor() {
+  int result = pthread_mutex_destroy(data_.mutex());
+  VALIDATE_PTHREAD_RESULT(result);
+
+  result = pthread_cond_destroy(data_.cond());
+  VALIDATE_PTHREAD_RESULT(result);
+}
+
+
+void Monitor::Enter() {
+  int result = pthread_mutex_lock(data_.mutex());
+  VALIDATE_PTHREAD_RESULT(result);
+  // TODO(iposva): Do we need to track lock owners?
+}
+
+
+void Monitor::Exit() {
+  // TODO(iposva): Do we need to track lock owners?
+  int result = pthread_mutex_unlock(data_.mutex());
+  VALIDATE_PTHREAD_RESULT(result);
+}
+
+
+Monitor::WaitResult Monitor::Wait(int64_t millis) {
+  return WaitMicros(millis * kMicrosecondsPerMillisecond);
+}
+
+
+Monitor::WaitResult Monitor::WaitMicros(int64_t micros) {
+  // TODO(iposva): Do we need to track lock owners?
+  Monitor::WaitResult retval = kNotified;
+  if (micros == kNoTimeout) {
+    // Wait forever.
+    int result = pthread_cond_wait(data_.cond(), data_.mutex());
+    VALIDATE_PTHREAD_RESULT(result);
+  } else {
+    struct timespec ts;
+    ComputeTimeSpecMicros(&ts, micros);
+    int result = pthread_cond_timedwait(data_.cond(), data_.mutex(), &ts);
+    ASSERT((result == 0) || (result == ETIMEDOUT));
+    if (result == ETIMEDOUT) {
+      retval = kTimedOut;
+    }
+  }
+  return retval;
+}
+
+
+void Monitor::Notify() {
+  // TODO(iposva): Do we need to track lock owners?
+  int result = pthread_cond_signal(data_.cond());
+  VALIDATE_PTHREAD_RESULT(result);
+}
+
+
+void Monitor::NotifyAll() {
+  // TODO(iposva): Do we need to track lock owners?
+  int result = pthread_cond_broadcast(data_.cond());
+  VALIDATE_PTHREAD_RESULT(result);
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // defined(TARGET_OS_FUCHSIA)
diff --git a/runtime/bin/thread_fuchsia.h b/runtime/bin/thread_fuchsia.h
new file mode 100644
index 0000000..6168719
--- /dev/null
+++ b/runtime/bin/thread_fuchsia.h
@@ -0,0 +1,77 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef BIN_THREAD_FUCHSIA_H_
+#define BIN_THREAD_FUCHSIA_H_
+
+#if !defined(BIN_THREAD_H_)
+#error Do not include thread_fuchsia.h directly; use thread.h instead.
+#endif
+
+#include <pthread.h>
+
+#include "platform/assert.h"
+#include "platform/globals.h"
+
+namespace dart {
+namespace bin {
+
+typedef pthread_key_t ThreadLocalKey;
+typedef pthread_t ThreadId;
+
+class ThreadInlineImpl {
+ private:
+  ThreadInlineImpl() {}
+  ~ThreadInlineImpl() {}
+
+  static uword GetThreadLocal(ThreadLocalKey key) {
+    static ThreadLocalKey kUnsetThreadLocalKey = static_cast<pthread_key_t>(-1);
+    ASSERT(key != kUnsetThreadLocalKey);
+    return reinterpret_cast<uword>(pthread_getspecific(key));
+  }
+
+  friend class Thread;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_COPY_AND_ASSIGN(ThreadInlineImpl);
+};
+
+
+class MutexData {
+ private:
+  MutexData() {}
+  ~MutexData() {}
+
+  pthread_mutex_t* mutex() { return &mutex_; }
+
+  pthread_mutex_t mutex_;
+
+  friend class Mutex;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_COPY_AND_ASSIGN(MutexData);
+};
+
+
+class MonitorData {
+ private:
+  MonitorData() {}
+  ~MonitorData() {}
+
+  pthread_mutex_t* mutex() { return &mutex_; }
+  pthread_cond_t* cond() { return &cond_; }
+
+  pthread_mutex_t mutex_;
+  pthread_cond_t cond_;
+
+  friend class Monitor;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_COPY_AND_ASSIGN(MonitorData);
+};
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // BIN_THREAD_FUCHSIA_H_
diff --git a/runtime/bin/utils_fuchsia.cc b/runtime/bin/utils_fuchsia.cc
new file mode 100644
index 0000000..1df2aba
--- /dev/null
+++ b/runtime/bin/utils_fuchsia.cc
@@ -0,0 +1,99 @@
+// 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.
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_FUCHSIA)
+
+#include <errno.h>
+#include <magenta/syscalls.h>
+#include <magenta/types.h>
+
+#include "bin/utils.h"
+#include "platform/assert.h"
+#include "platform/utils.h"
+
+namespace dart {
+namespace bin {
+
+OSError::OSError() : sub_system_(kSystem), code_(0), message_(NULL) {
+  set_sub_system(kSystem);
+  set_code(errno);
+  const int kBufferSize = 1024;
+  char error_buf[kBufferSize];
+  SetMessage(Utils::StrError(errno, error_buf, kBufferSize));
+}
+
+
+void OSError::SetCodeAndMessage(SubSystem sub_system, int code) {
+  set_sub_system(sub_system);
+  set_code(code);
+  if (sub_system == kSystem) {
+    const int kBufferSize = 1024;
+    char error_buf[kBufferSize];
+    SetMessage(Utils::StrError(code, error_buf, kBufferSize));
+  } else if (sub_system == kGetAddressInfo) {
+    UNIMPLEMENTED();
+  } else {
+    UNREACHABLE();
+  }
+}
+
+
+const char* StringUtils::ConsoleStringToUtf8(
+    const char* str, intptr_t len, intptr_t* result_len) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+const char* StringUtils::Utf8ToConsoleString(
+    const char* utf8, intptr_t len, intptr_t* result_len) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+char* StringUtils::ConsoleStringToUtf8(
+    char* str, intptr_t len, intptr_t* result_len) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+char* StringUtils::Utf8ToConsoleString(
+    char* utf8, intptr_t len, intptr_t* result_len) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
+  return false;
+}
+
+
+void TimerUtils::InitOnce() {
+}
+
+
+int64_t TimerUtils::GetCurrentMonotonicMillis() {
+  return GetCurrentMonotonicMicros() / 1000;
+}
+
+
+int64_t TimerUtils::GetCurrentMonotonicMicros() {
+  int64_t ticks = mx_current_time();
+  return ticks / kNanosecondsPerMicrosecond;
+}
+
+
+void TimerUtils::Sleep(int64_t millis) {
+  mx_nanosleep(
+      millis * kMicrosecondsPerMillisecond * kNanosecondsPerMicrosecond);
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // defined(TARGET_OS_FUCHSIA)
diff --git a/runtime/bin/vmservice/server.dart b/runtime/bin/vmservice/server.dart
index c8334da..4e4c54a 100644
--- a/runtime/bin/vmservice/server.dart
+++ b/runtime/bin/vmservice/server.dart
@@ -105,21 +105,64 @@
   final VMService _service;
   final String _ip;
   final int _port;
-
+  final bool _originCheckDisabled;
+  final List<String> _allowedOrigins = <String>[];
   HttpServer _server;
   bool get running => _server != null;
   bool _displayMessages = false;
 
-  Server(this._service, this._ip, this._port) {
+  Server(this._service, this._ip, this._port, this._originCheckDisabled) {
     _displayMessages = (_ip != '127.0.0.1' || _port != 8181);
   }
 
-  void _requestHandler(HttpRequest request) {
-    // Allow cross origin requests with 'observatory' header.
-    request.response.headers.add('Access-Control-Allow-Origin', '*');
-    request.response.headers.add('Access-Control-Allow-Headers',
-                                 'Observatory-Version');
+  void _addOrigin(String host, String port) {
+    if (port == null) {
+      String origin = 'http://$host';
+      _allowedOrigins.add(origin);
+    } else {
+      String origin = 'http://$host:$port';
+      _allowedOrigins.add(origin);
+    }
+  }
 
+  bool _isAllowedOrigin(String origin) {
+    for (String allowedOrigin in _allowedOrigins) {
+      if (origin.startsWith(allowedOrigin)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  bool _originCheck(HttpRequest request) {
+    if (_originCheckDisabled) {
+      // Always allow.
+      return true;
+    }
+    // First check the web-socket specific origin.
+    List<String> origins = request.headers["Sec-WebSocket-Origin"];
+    if (origins == null) {
+      // Fall back to the general Origin field.
+      origins = request.headers["Origin"];
+    }
+    if (origins == null) {
+      // No origin sent. This is a non-browser client or a same-origin request.
+      return true;
+    }
+    for (String origin in origins) {
+      if (_isAllowedOrigin(origin)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  void _requestHandler(HttpRequest request) {
+    if (!_originCheck(request)) {
+      // This is a cross origin attempt to connect
+      request.response.close();
+      return;
+    }
     if (request.method != 'GET') {
       // Not a GET request. Do nothing.
       request.response.close();
@@ -130,8 +173,7 @@
           request.uri.path == '/' ? ROOT_REDIRECT_PATH : request.uri.path;
 
     if (path == WEBSOCKET_PATH) {
-      WebSocketTransformer.upgrade(request,
-                                   compression: CompressionOptions.OFF).then(
+      WebSocketTransformer.upgrade(request).then(
                                    (WebSocket webSocket) {
         new WebSocketClient(webSocket, _service);
       });
@@ -165,6 +207,9 @@
       return new Future.value(this);
     }
 
+    // Clear allowed origins.
+    _allowedOrigins.clear();
+
     var address = new InternetAddress(_ip);
     // Startup HTTP server.
     return HttpServer.bind(address, _port).then((s) {
@@ -172,6 +217,13 @@
       _server.listen(_requestHandler, cancelOnError: true);
       var ip = _server.address.address.toString();
       var port = _server.port.toString();
+      // Add the numeric ip and host name to our allowed origins.
+      _addOrigin(ip, port);
+      _addOrigin(_server.address.host.toString(), port);
+      // Explicitly add localhost and 127.0.0.1 on any port (necessary for
+      // adb port forwarding).
+      _addOrigin('127.0.0.1', null);
+      _addOrigin('localhost', null);
       if (_displayMessages) {
         print('Observatory listening on http://$ip:$port');
       }
diff --git a/runtime/bin/vmservice/vmservice_io.dart b/runtime/bin/vmservice/vmservice_io.dart
index 3e1bee4..4e5ccab 100644
--- a/runtime/bin/vmservice/vmservice_io.dart
+++ b/runtime/bin/vmservice/vmservice_io.dart
@@ -19,8 +19,10 @@
 String _ip;
 // Should the HTTP server auto start?
 bool _autoStart;
-
+// Should the HTTP server run in devmode?
+bool _originCheckDisabled;
 bool _isWindows = false;
+bool _isFuchsia = false;
 var _signalWatch;
 var _signalSubscription;
 
@@ -35,7 +37,7 @@
   // Lazily create service.
   var service = new VMService();
   // Lazily create server.
-  server = new Server(service, _ip, _port);
+  server = new Server(service, _ip, _port, _originCheckDisabled);
 }
 
 Future cleanupCallback() async {
@@ -70,13 +72,63 @@
   await dir.delete(recursive: true);
 }
 
+class PendingWrite {
+  PendingWrite(this.uri, this.bytes);
+  final Completer completer = new Completer();
+  final Uri uri;
+  final List<int> bytes;
+
+  Future write() async {
+    var file = new File.fromUri(uri);
+    var parent_directory = file.parent;
+    await parent_directory.create(recursive: true);
+    var result = await file.writeAsBytes(bytes);
+    completer.complete(null);
+    WriteLimiter._writeCompleted();
+  }
+}
+
+class WriteLimiter {
+  static final List<PendingWrite> pendingWrites = new List<PendingWrite>();
+
+  // non-rooted Android devices have a very low limit for the number of
+  // open files. Artificially cap ourselves to 16.
+  static const kMaxOpenWrites = 16;
+  static int openWrites = 0;
+
+  static Future scheduleWrite(Uri path, List<int> bytes) async {
+    // Create a new pending write.
+    PendingWrite pw = new PendingWrite(path, bytes);
+    pendingWrites.add(pw);
+    _maybeWriteFiles();
+    return pw.completer.future;
+  }
+
+  static _maybeWriteFiles() {
+    while (openWrites < kMaxOpenWrites) {
+      if (pendingWrites.length > 0) {
+        PendingWrite pw = pendingWrites.removeLast();
+        pw.write();
+        openWrites++;
+      } else {
+        break;
+      }
+    }
+  }
+
+  static _writeCompleted() {
+    openWrites--;
+    assert(openWrites >= 0);
+    _maybeWriteFiles();
+  }
+}
+
 Future writeFileCallback(Uri path, List<int> bytes) async {
-  var file = await new File.fromUri(path);
-  await file.writeAsBytes(bytes);
+  return WriteLimiter.scheduleWrite(path, bytes);
 }
 
 Future<List<int>> readFileCallback(Uri path) async {
-  var file = await new File.fromUri(path);
+  var file = new File.fromUri(path);
   return await file.readAsBytes();
 }
 
@@ -126,8 +178,8 @@
     // Cannot register for signals.
     return;
   }
-  if (_isWindows) {
-    // Cannot register for signals on Windows.
+  if (_isWindows || _isFuchsia) {
+    // Cannot register for signals on Windows or Fuchsia.
     return;
   }
   _signalSubscription = _signalWatch(ProcessSignal.SIGQUIT).listen(_onSignal);
diff --git a/runtime/bin/vmservice_dartium.cc b/runtime/bin/vmservice_dartium.cc
index 535fb41..cd40dd7 100644
--- a/runtime/bin/vmservice_dartium.cc
+++ b/runtime/bin/vmservice_dartium.cc
@@ -65,7 +65,8 @@
   ASSERT(Dart_IsServiceIsolate(isolate));
   if (!VmService::Setup(DEFAULT_VM_SERVICE_SERVER_IP,
                         DEFAULT_VM_SERVICE_SERVER_PORT,
-                        false /* running_precompiled */)) {
+                        false /* running_precompiled */,
+                        false /* disable origin checks */)) {
     fprintf(stderr,
             "Vmservice::Setup failed: %s\n", VmService::GetErrorMessage());
     isolate = NULL;
diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc
index b7f4df4..d851863 100644
--- a/runtime/bin/vmservice_impl.cc
+++ b/runtime/bin/vmservice_impl.cc
@@ -176,7 +176,8 @@
 
 bool VmService::Setup(const char* server_ip,
                       intptr_t server_port,
-                      bool running_precompiled) {
+                      bool running_precompiled,
+                      bool dev_mode_server) {
   Dart_Isolate isolate = Dart_CurrentIsolate();
   ASSERT(isolate != NULL);
   SetServerIPAndPort("", 0);
@@ -241,6 +242,9 @@
                          DartUtils::NewString("_autoStart"),
                          Dart_NewBoolean(auto_start));
   SHUTDOWN_ON_ERROR(result);
+  result = Dart_SetField(library,
+                         DartUtils::NewString("_originCheckDisabled"),
+                         Dart_NewBoolean(dev_mode_server));
 
   // Are we running on Windows?
 #if defined(TARGET_OS_WINDOWS)
@@ -252,6 +256,16 @@
       Dart_SetField(library, DartUtils::NewString("_isWindows"), is_windows);
   SHUTDOWN_ON_ERROR(result);
 
+  // Are we running on Fuchsia?
+#if defined(TARGET_OS_FUCHSIA)
+  Dart_Handle is_fuchsia = Dart_True();
+#else
+  Dart_Handle is_fuchsia = Dart_False();
+#endif
+  result =
+      Dart_SetField(library, DartUtils::NewString("_isFuchsia"), is_fuchsia);
+  SHUTDOWN_ON_ERROR(result);
+
   // Get _getWatchSignalInternal from dart:io.
   Dart_Handle dart_io_str = Dart_NewStringFromCString(DartUtils::kIOLibURL);
   SHUTDOWN_ON_ERROR(dart_io_str);
diff --git a/runtime/bin/vmservice_impl.h b/runtime/bin/vmservice_impl.h
index f373b4b..f499abf 100644
--- a/runtime/bin/vmservice_impl.h
+++ b/runtime/bin/vmservice_impl.h
@@ -18,7 +18,8 @@
 
   static bool Setup(const char* server_ip,
                     intptr_t server_port,
-                    bool running_precompiled);
+                    bool running_precompiled,
+                    bool dev_mode_server);
 
   // Error message if startup failed.
   static const char* GetErrorMessage();
diff --git a/runtime/lib/bigint.dart b/runtime/lib/bigint.dart
index c21b04a..0c562d7 100644
--- a/runtime/lib/bigint.dart
+++ b/runtime/lib/bigint.dart
@@ -1206,9 +1206,9 @@
     return r_used;
   }
 
-  int get _identityHashCode {
-    return this;
-  }
+  int get hashCode => this;
+  int get _identityHashCode => this;
+
   int operator ~() {
     return _not()._toValidInt();
   }
diff --git a/runtime/lib/bool_patch.dart b/runtime/lib/bool_patch.dart
index 274b153..bbcbdb4 100644
--- a/runtime/lib/bool_patch.dart
+++ b/runtime/lib/bool_patch.dart
@@ -10,8 +10,6 @@
                                                  {bool defaultValue: false})
       native "Bool_fromEnvironment";
 
-  int get _identityHashCode {
-    return this ? 1231 : 1237;
-  }
-  int get hashCode => _identityHashCode;
+  int get hashCode => this ? 1231 : 1237;
+  int get _identityHashCode => this ? 1231 : 1237;
 }
diff --git a/runtime/lib/core_patch.dart b/runtime/lib/core_patch.dart
index 13f7513..6c792d2 100644
--- a/runtime/lib/core_patch.dart
+++ b/runtime/lib/core_patch.dart
@@ -11,13 +11,9 @@
 // The members of this class are cloned and added to each class that
 // represents an enum type.
 class _EnumHelper {
-  // Declare the list of enum value names private. When this field is
-  // cloned into a user-defined enum class, the field will be inaccessible
-  // because of the library-specific name suffix. The toString() function
-  // below can access it because it uses the same name suffix.
-  static const List<String> _enum_names = null;
-  String toString() => _enum_names[index];
-  int get hashCode => _enum_names[index].hashCode;
+  String _name;
+  String toString() => _name;
+  int get hashCode => _name.hashCode;
 }
 
 // _SyncIterable and _syncIterator are used by the compiler to
diff --git a/runtime/lib/developer.cc b/runtime/lib/developer.cc
index a2811ee..57a1a4c 100644
--- a/runtime/lib/developer.cc
+++ b/runtime/lib/developer.cc
@@ -34,14 +34,19 @@
 
 DEFINE_NATIVE_ENTRY(Developer_inspect, 1) {
   GET_NATIVE_ARGUMENT(Instance, inspectee, arguments->NativeArgAt(0));
+#ifndef PRODUCT
   if (FLAG_support_service) {
     Service::SendInspectEvent(isolate, inspectee);
   }
+#endif  // !PRODUCT
   return inspectee.raw();
 }
 
 
 DEFINE_NATIVE_ENTRY(Developer_log, 8) {
+#if defined(PRODUCT)
+  return Object::null();
+#else
   if (!FLAG_support_service) {
     return Object::null();
   }
@@ -63,10 +68,14 @@
                         error,
                         stack_trace);
   return Object::null();
+#endif  // PRODUCT
 }
 
 
 DEFINE_NATIVE_ENTRY(Developer_postEvent, 2) {
+#if defined(PRODUCT)
+  return Object::null();
+#else
   if (!FLAG_support_service) {
     return Object::null();
   }
@@ -74,19 +83,27 @@
   GET_NON_NULL_NATIVE_ARGUMENT(String, event_data, arguments->NativeArgAt(1));
   Service::SendExtensionEvent(isolate, event_kind, event_data);
   return Object::null();
+#endif  // PRODUCT
 }
 
 
 DEFINE_NATIVE_ENTRY(Developer_lookupExtension, 1) {
+#if defined(PRODUCT)
+  return Object::null();
+#else
   if (!FLAG_support_service) {
     return Object::null();
   }
   GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(0));
   return isolate->LookupServiceExtensionHandler(name);
+#endif  // PRODUCT
 }
 
 
 DEFINE_NATIVE_ENTRY(Developer_registerExtension, 2) {
+#if defined(PRODUCT)
+  return Object::null();
+#else
   if (!FLAG_support_service) {
     return Object::null();
   }
@@ -100,6 +117,7 @@
     isolate->RegisterServiceExtensionHandler(name, handler);
   }
   return Object::null();
+#endif  // PRODUCT
 }
 
 }  // namespace dart
diff --git a/runtime/lib/double.dart b/runtime/lib/double.dart
index cbf955d..ade4b93 100644
--- a/runtime/lib/double.dart
+++ b/runtime/lib/double.dart
@@ -8,10 +8,12 @@
 
   Type get runtimeType => double;
 
-  int get _identityHashCode {
-    if (isNaN || isInfinite) return 0;
-    return toInt();
-  }
+  // TODO: Make a stared static method for hashCode and _identityHashCode
+  //       when semantics are corrected as described in:
+  //       https://github.com/dart-lang/sdk/issues/2884
+  int get hashCode => (isNaN || isInfinite) ?  0 : toInt();
+  int get _identityHashCode => (isNaN || isInfinite) ?  0 : toInt();
+
   double operator +(num other) {
     return _add(other.toDouble());
   }
diff --git a/runtime/lib/growable_array.dart b/runtime/lib/growable_array.dart
index 016a454..271c71a 100644
--- a/runtime/lib/growable_array.dart
+++ b/runtime/lib/growable_array.dart
@@ -104,12 +104,6 @@
     return new _GrowableList<T>.withData(data);
   }
 
-  factory _GrowableList.from(Iterable<T> other) {
-    List<T> result = new _GrowableList<T>();
-    result.addAll(other);
-    return result;
-  }
-
   factory _GrowableList.withData(_List data)
     native "GrowableList_allocate";
 
diff --git a/runtime/lib/integers.dart b/runtime/lib/integers.dart
index b86b71c..0c5b119 100644
--- a/runtime/lib/integers.dart
+++ b/runtime/lib/integers.dart
@@ -408,8 +408,8 @@
     throw new UnsupportedError(
         "_Smi can only be allocated by the VM");
   }
-  int get _identityHashCode => this;
   int get hashCode => this;
+  int get _identityHashCode => this;
   int operator ~() native "Smi_bitNegate";
   int get bitLength native "Smi_bitLength";
 
@@ -608,8 +608,8 @@
     throw new UnsupportedError(
         "_Mint can only be allocated by the VM");
   }
-  int get _identityHashCode => this;
   int get hashCode => this;
+  int get _identityHashCode => this;
   int operator ~() native "Mint_bitNegate";
   int get bitLength native "Mint_bitLength";
 
diff --git a/runtime/lib/null_patch.dart b/runtime/lib/null_patch.dart
index 61972d1..047039b 100644
--- a/runtime/lib/null_patch.dart
+++ b/runtime/lib/null_patch.dart
@@ -11,10 +11,8 @@
   }
 
   static const _HASH_CODE = 2011; // The year Dart was announced and a prime.
-  int get _identityHashCode => _HASH_CODE;
   int get hashCode => _HASH_CODE;
+  int get _identityHashCode => _HASH_CODE;
 
-  String toString() {
-    return 'null';
-  }
+  String toString() => 'null';
 }
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index b450038..e1b7a71 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -39,9 +39,12 @@
 
 
 DEFINE_NATIVE_ENTRY(Object_getHash, 1) {
-  const Instance& instance = Instance::CheckedHandle(arguments->NativeArgAt(0));
+  // Please note that no handle is created for the argument.
+  // This is safe since the argument is only used in a tail call.
+  // The performance benefit is more than 5% when using hashCode.
   Heap* heap = isolate->heap();
-  return Smi::New(heap->GetHash(instance.raw()));
+  ASSERT(arguments->NativeArgAt(0)->IsDartInstance());
+  return Smi::New(heap->GetHash(arguments->NativeArgAt(0)));
 }
 
 
@@ -163,6 +166,37 @@
   return Bool::Get(negate.value() ? !is_instance_of : is_instance_of).raw();
 }
 
+DEFINE_NATIVE_ENTRY(Object_simpleInstanceOf, 2) {
+  // This native is only called when the right hand side passes
+  // simpleInstanceOfType and it is a non-negative test.
+  const Instance& instance =
+      Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
+  const AbstractType& type =
+      AbstractType::CheckedHandle(zone, arguments->NativeArgAt(1));
+  const TypeArguments& instantiator_type_arguments =
+      TypeArguments::Handle(TypeArguments::null());
+  ASSERT(type.IsFinalized());
+  ASSERT(!type.IsMalformed());
+  ASSERT(!type.IsMalbounded());
+  Error& bound_error = Error::Handle(zone, Error::null());
+  const bool is_instance_of = instance.IsInstanceOf(type,
+                                                    instantiator_type_arguments,
+                                                    &bound_error);
+  if (!is_instance_of && !bound_error.IsNull()) {
+    // Throw a dynamic type error only if the instanceof test fails.
+    DartFrameIterator iterator;
+    StackFrame* caller_frame = iterator.NextFrame();
+    ASSERT(caller_frame != NULL);
+    const TokenPosition location = caller_frame->GetTokenPos();
+    String& bound_error_message = String::Handle(
+        zone, String::New(bound_error.ToErrorCString()));
+    Exceptions::CreateAndThrowTypeError(
+        location, AbstractType::Handle(zone), AbstractType::Handle(zone),
+        Symbols::Empty(), bound_error_message);
+    UNREACHABLE();
+  }
+  return Bool::Get(is_instance_of).raw();
+}
 
 DEFINE_NATIVE_ENTRY(Object_instanceOfNum, 2) {
   const Instance& instance =
diff --git a/runtime/lib/object_patch.dart b/runtime/lib/object_patch.dart
index 7c4f5f5..719e592 100644
--- a/runtime/lib/object_patch.dart
+++ b/runtime/lib/object_patch.dart
@@ -15,21 +15,23 @@
   static _getHash(obj) native "Object_getHash";
   static _setHash(obj, hash) native "Object_setHash";
 
-  /* patch */ int get hashCode => _identityHashCode;
-
-  int get _identityHashCode {
-    var result = _getHash(this);
+  // Shared static implentation for hashCode and _identityHashCode.
+  static int _objectHashCode(obj) {
+    var result = _getHash(obj);
     if (result == 0) {
       // We want the hash to be a Smi value greater than 0.
       result = _hashCodeRnd.nextInt(0x40000000);
       while (result == 0) {
         result = _hashCodeRnd.nextInt(0x40000000);
       }
-      _setHash(this, result);
+      _setHash(obj, result);
     }
     return result;
   }
 
+  /* patch */ int get hashCode => _objectHashCode(this);
+  int get _identityHashCode => _objectHashCode(this);
+
   /* patch */ String toString() native "Object_toString";
   // A statically dispatched version of Object.toString.
   static String _toString(obj) native "Object_toString";
@@ -56,6 +58,11 @@
   bool _instanceOf(instantiator_type_arguments, type, bool negate)
       native "Object_instanceOf";
 
+  // Group of functions for implementing fast simple instance of.
+  bool _simpleInstanceOf(type) native "Object_simpleInstanceOf";
+  bool _simpleInstanceOfTrue(type) => true;
+  bool _simpleInstanceOfFalse(type) => false;
+  
   bool _instanceOfDouble(bool negate) native "Object_instanceOfDouble";
   bool _instanceOfNum(bool negate) native "Object_instanceOfNum";
   bool _instanceOfInt(bool negate) native "Object_instanceOfInt";
diff --git a/runtime/lib/timeline.cc b/runtime/lib/timeline.cc
index 6923e6f..300d6e3 100644
--- a/runtime/lib/timeline.cc
+++ b/runtime/lib/timeline.cc
@@ -16,12 +16,14 @@
 // Native implementations for the dart:developer library.
 
 DEFINE_NATIVE_ENTRY(Timeline_isDartStreamEnabled, 0) {
+#ifndef PRODUCT
   if (!FLAG_support_timeline) {
     return Bool::False().raw();
   }
   if (Timeline::GetDartStream()->enabled()) {
     return Bool::True().raw();
   }
+#endif  // !PRODUCT
   return Bool::False().raw();
 }
 
diff --git a/runtime/lib/vmservice.cc b/runtime/lib/vmservice.cc
index 831b9b8..584ceb8 100644
--- a/runtime/lib/vmservice.cc
+++ b/runtime/lib/vmservice.cc
@@ -13,6 +13,7 @@
 #include "vm/native_entry.h"
 #include "vm/object.h"
 #include "vm/port.h"
+#include "vm/service_event.h"
 #include "vm/service_isolate.h"
 #include "vm/symbols.h"
 
@@ -450,4 +451,43 @@
 #endif
 }
 
+
+
+DEFINE_NATIVE_ENTRY(VMService_spawnUriNotify, 2) {
+#ifndef PRODUCT
+  if (!FLAG_support_service) {
+    return Object::null();
+  }
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, result, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(String, token, arguments->NativeArgAt(1));
+
+  if (result.IsSendPort()) {
+    Dart_Port id = SendPort::Cast(result).Id();
+    Isolate* isolate = PortMap::GetIsolate(id);
+    if (isolate != NULL) {
+      ServiceEvent spawn_event(isolate, ServiceEvent::kIsolateSpawn);
+      spawn_event.set_spawn_token(&token);
+      Service::HandleEvent(&spawn_event);
+    } else {
+      // There is no isolate at the control port anymore.  Must have
+      // died already.
+      ServiceEvent spawn_event(NULL, ServiceEvent::kIsolateSpawn);
+      const String& error = String::Handle(String::New(
+          "spawned isolate exited before notification completed"));
+      spawn_event.set_spawn_token(&token);
+      spawn_event.set_spawn_error(&error);
+      Service::HandleEvent(&spawn_event);
+    }
+  } else {
+    // The isolate failed to spawn.
+    ASSERT(result.IsString());
+    ServiceEvent spawn_event(NULL, ServiceEvent::kIsolateSpawn);
+    spawn_event.set_spawn_token(&token);
+    spawn_event.set_spawn_error(&String::Cast(result));
+    Service::HandleEvent(&spawn_event);
+  }
+#endif  // PRODUCT
+  return Object::null();
+}
+
 }  // namespace dart
diff --git a/runtime/lib/vmservice_patch.dart b/runtime/lib/vmservice_patch.dart
index e0a85ae..498bda2 100644
--- a/runtime/lib/vmservice_patch.dart
+++ b/runtime/lib/vmservice_patch.dart
@@ -34,3 +34,5 @@
 patch bool _vmListenStream(String streamId) native "VMService_ListenStream";
 patch void _vmCancelStream(String streamId) native "VMService_CancelStream";
 patch Uint8List _requestAssets() native "VMService_RequestAssets";
+patch void _spawnUriNotify(obj, String token)
+    native "VMService_spawnUriNotify";
diff --git a/runtime/observatory/HACKING.md b/runtime/observatory/HACKING.md
index af74bda..e8c5500 100644
--- a/runtime/observatory/HACKING.md
+++ b/runtime/observatory/HACKING.md
@@ -69,7 +69,7 @@
 ```
 Start the script:
 ```
-$ dart --observe clock.dart
+$ dart --disable-service-origin-check --observe clock.dart
 ```
 
 ## Code Reviews
diff --git a/runtime/observatory/lib/app.dart b/runtime/observatory/lib/app.dart
index 15e802d..6212eb3 100644
--- a/runtime/observatory/lib/app.dart
+++ b/runtime/observatory/lib/app.dart
@@ -12,6 +12,9 @@
 import 'package:logging/logging.dart';
 import 'package:observatory/service_html.dart';
 import 'package:observatory/elements.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/repositories.dart';
 import 'package:observatory/tracer.dart';
 import 'package:observatory/utils.dart';
 import 'package:polymer/polymer.dart';
@@ -21,6 +24,7 @@
 
 part 'src/app/application.dart';
 part 'src/app/location_manager.dart';
+part 'src/app/notification.dart';
 part 'src/app/page.dart';
 part 'src/app/settings.dart';
 part 'src/app/target_manager.dart';
diff --git a/runtime/observatory/lib/elements.dart b/runtime/observatory/lib/elements.dart
index 9ee5cf2..e1889ac 100644
--- a/runtime/observatory/lib/elements.dart
+++ b/runtime/observatory/lib/elements.dart
@@ -10,7 +10,6 @@
 export 'package:observatory/src/elements/context_ref.dart';
 export 'package:observatory/src/elements/context_view.dart';
 export 'package:observatory/src/elements/cpu_profile.dart';
-export 'package:observatory/src/elements/curly_block.dart';
 export 'package:observatory/src/elements/debugger.dart';
 export 'package:observatory/src/elements/error_view.dart';
 export 'package:observatory/src/elements/eval_box.dart';
@@ -30,7 +29,6 @@
 export 'package:observatory/src/elements/instructions_view.dart';
 export 'package:observatory/src/elements/io_view.dart';
 export 'package:observatory/src/elements/isolate_reconnect.dart';
-export 'package:observatory/src/elements/isolate_ref.dart';
 export 'package:observatory/src/elements/isolate_summary.dart';
 export 'package:observatory/src/elements/isolate_view.dart';
 export 'package:observatory/src/elements/json_view.dart';
@@ -39,7 +37,6 @@
 export 'package:observatory/src/elements/logging.dart';
 export 'package:observatory/src/elements/megamorphiccache_view.dart';
 export 'package:observatory/src/elements/metrics.dart';
-export 'package:observatory/src/elements/nav_bar.dart';
 export 'package:observatory/src/elements/object_common.dart';
 export 'package:observatory/src/elements/object_view.dart';
 export 'package:observatory/src/elements/objectpool_view.dart';
@@ -53,9 +50,89 @@
 export 'package:observatory/src/elements/script_view.dart';
 export 'package:observatory/src/elements/service_ref.dart';
 export 'package:observatory/src/elements/service_view.dart';
-export 'package:observatory/src/elements/sliding_checkbox.dart';
 export 'package:observatory/src/elements/timeline_page.dart';
-export 'package:observatory/src/elements/view_footer.dart';
 export 'package:observatory/src/elements/vm_connect.dart';
-export 'package:observatory/src/elements/vm_ref.dart';
 export 'package:observatory/src/elements/vm_view.dart';
+
+import 'dart:async';
+
+import 'package:observatory/src/elements/curly_block.dart';
+import 'package:observatory/src/elements/curly_block_wrapper.dart';
+import 'package:observatory/src/elements/isolate_ref.dart';
+import 'package:observatory/src/elements/isolate_ref_wrapper.dart';
+import 'package:observatory/src/elements/nav/bar.dart';
+import 'package:observatory/src/elements/nav/class_menu.dart';
+import 'package:observatory/src/elements/nav/class_menu_wrapper.dart';
+import 'package:observatory/src/elements/nav/isolate_menu.dart';
+import 'package:observatory/src/elements/nav/isolate_menu_wrapper.dart';
+import 'package:observatory/src/elements/nav/library_menu.dart';
+import 'package:observatory/src/elements/nav/library_menu_wrapper.dart';
+import 'package:observatory/src/elements/nav/menu.dart';
+import 'package:observatory/src/elements/nav/menu_wrapper.dart';
+import 'package:observatory/src/elements/nav/menu_item.dart';
+import 'package:observatory/src/elements/nav/menu_item_wrapper.dart';
+import 'package:observatory/src/elements/nav/notify.dart';
+import 'package:observatory/src/elements/nav/notify_wrapper.dart';
+import 'package:observatory/src/elements/nav/notify_event.dart';
+import 'package:observatory/src/elements/nav/notify_exception.dart';
+import 'package:observatory/src/elements/nav/refresh.dart';
+import 'package:observatory/src/elements/nav/refresh_wrapper.dart';
+import 'package:observatory/src/elements/nav/top_menu.dart';
+import 'package:observatory/src/elements/nav/top_menu_wrapper.dart';
+import 'package:observatory/src/elements/nav/vm_menu.dart';
+import 'package:observatory/src/elements/nav/vm_menu_wrapper.dart';
+import 'package:observatory/src/elements/view_footer.dart';
+import 'package:observatory/src/elements/vm_connect_target.dart';
+import 'package:observatory/src/elements/vm_connect_target_wrapper.dart';
+
+export 'package:observatory/src/elements/helpers/rendering_queue.dart';
+
+export 'package:observatory/src/elements/curly_block.dart';
+export 'package:observatory/src/elements/isolate_ref.dart';
+export 'package:observatory/src/elements/nav/bar.dart';
+export 'package:observatory/src/elements/nav/class_menu.dart';
+export 'package:observatory/src/elements/nav/isolate_menu.dart';
+export 'package:observatory/src/elements/nav/library_menu.dart';
+export 'package:observatory/src/elements/nav/menu.dart';
+export 'package:observatory/src/elements/nav/menu_item.dart';
+export 'package:observatory/src/elements/nav/notify.dart';
+export 'package:observatory/src/elements/nav/notify_event.dart';
+export 'package:observatory/src/elements/nav/notify_exception.dart';
+export 'package:observatory/src/elements/nav/refresh.dart';
+export 'package:observatory/src/elements/nav/top_menu.dart';
+export 'package:observatory/src/elements/nav/vm_menu.dart';
+export 'package:observatory/src/elements/view_footer.dart';
+export 'package:observatory/src/elements/vm_connect_target.dart';
+
+// Even though this function does not invoke any asynchronous operation
+// it is marked as async to allow future backward compatible changes.
+Future initElements() async {
+  CurlyBlockElement.tag.ensureRegistration();
+  CurlyBlockElementWrapper.tag.ensureRegistration();
+  IsolateRefElement.tag.ensureRegistration();
+  IsolateRefElementWrapper.tag.ensureRegistration();
+  NavBarElement.tag.ensureRegistration();
+  NavClassMenuElement.tag.ensureRegistration();
+  NavClassMenuElementWrapper.tag.ensureRegistration();
+  NavIsolateMenuElement.tag.ensureRegistration();
+  NavIsolateMenuElementWrapper.tag.ensureRegistration();
+  NavLibraryMenuElement.tag.ensureRegistration();
+  NavLibraryMenuElementWrapper.tag.ensureRegistration();
+  NavMenuElement.tag.ensureRegistration();
+  NavMenuElementWrapper.tag.ensureRegistration();
+  NavMenuItemElement.tag.ensureRegistration();
+  NavMenuItemElementWrapper.tag.ensureRegistration();
+  NavNotifyElement.tag.ensureRegistration();
+  NavNotifyElementWrapper.tag.ensureRegistration();
+  NavNotifyEventElement.tag.ensureRegistration();
+  NavNotifyExceptionElement.tag.ensureRegistration();
+  NavRefreshElement.tag.ensureRegistration();
+  NavRefreshElementWrapper.tag.ensureRegistration();
+  NavTopMenuElement.tag.ensureRegistration();
+  NavTopMenuElementWrapper.tag.ensureRegistration();
+  NavVMMenuElement.tag.ensureRegistration();
+  NavVMMenuElementWrapper.tag.ensureRegistration();
+  ViewFooterElement.tag.ensureRegistration();
+  VMConnectTargetElement.tag.ensureRegistration();
+  VMConnectTargetElementWrapper.tag.ensureRegistration();
+}
diff --git a/runtime/observatory/lib/elements.html b/runtime/observatory/lib/elements.html
index 52b59b4..b1d51fa 100644
--- a/runtime/observatory/lib/elements.html
+++ b/runtime/observatory/lib/elements.html
@@ -5,7 +5,6 @@
 <link rel="import" href="src/elements/code_ref.html">
 <link rel="import" href="src/elements/code_view.html">
 <link rel="import" href="src/elements/cpu_profile.html">
-<link rel="import" href="src/elements/curly_block.html">
 <link rel="import" href="src/elements/debugger.html">
 <link rel="import" href="src/elements/error_view.html">
 <link rel="import" href="src/elements/eval_box.html">
@@ -23,7 +22,6 @@
 <link rel="import" href="src/elements/icdata_view.html">
 <link rel="import" href="src/elements/instructions_view.html">
 <link rel="import" href="src/elements/isolate_reconnect.html">
-<link rel="import" href="src/elements/isolate_ref.html">
 <link rel="import" href="src/elements/isolate_summary.html">
 <link rel="import" href="src/elements/isolate_view.html">
 <link rel="import" href="src/elements/json_view.html">
@@ -32,22 +30,17 @@
 <link rel="import" href="src/elements/logging.html">
 <link rel="import" href="src/elements/megamorphiccache_view.html">
 <link rel="import" href="src/elements/metrics.html">
-<link rel="import" href="src/elements/nav_bar.html">
 <link rel="import" href="src/elements/object_common.html">
 <link rel="import" href="src/elements/object_view.html">
 <link rel="import" href="src/elements/objectpool_view.html">
 <link rel="import" href="src/elements/objectstore_view.html">
 <link rel="import" href="src/elements/observatory_application.html">
-<link rel="import" href="src/elements/observatory_element.html">
 <link rel="import" href="src/elements/persistent_handles.html">
 <link rel="import" href="src/elements/ports.html">
 <link rel="import" href="src/elements/script_inset.html">
 <link rel="import" href="src/elements/script_ref.html">
 <link rel="import" href="src/elements/script_view.html">
 <link rel="import" href="src/elements/service_ref.html">
-<link rel="import" href="src/elements/sliding_checkbox.html">
 <link rel="import" href="src/elements/timeline_page.html">
-<link rel="import" href="src/elements/view_footer.html">
 <link rel="import" href="src/elements/vm_connect.html">
-<link rel="import" href="src/elements/vm_ref.html">
 <link rel="import" href="src/elements/vm_view.html">
diff --git a/runtime/observatory/lib/mocks.dart b/runtime/observatory/lib/mocks.dart
new file mode 100644
index 0000000..18d8805
--- /dev/null
+++ b/runtime/observatory/lib/mocks.dart
@@ -0,0 +1,24 @@
+// 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 mocks;
+
+import 'dart:async';
+
+import 'package:observatory/models.dart' as M;
+
+part 'src/mocks/exceptions/connection_exception.dart';
+
+part 'src/mocks/objects/error.dart';
+part 'src/mocks/objects/event.dart';
+part 'src/mocks/objects/class.dart';
+part 'src/mocks/objects/isolate.dart';
+part 'src/mocks/objects/library.dart';
+part 'src/mocks/objects/notification.dart';
+part 'src/mocks/objects/script.dart';
+part 'src/mocks/objects/source_location.dart';
+part 'src/mocks/objects/target.dart';
+part 'src/mocks/objects/vm.dart';
+
+part 'src/mocks/repositories/notification.dart';
diff --git a/runtime/observatory/lib/models.dart b/runtime/observatory/lib/models.dart
new file mode 100644
index 0000000..c047e9c
--- /dev/null
+++ b/runtime/observatory/lib/models.dart
@@ -0,0 +1,28 @@
+// 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 models;
+
+import 'dart:async';
+
+part 'src/models/exceptions.dart';
+
+part 'src/models/objects/class.dart';
+part 'src/models/objects/breakpoint.dart';
+part 'src/models/objects/error.dart';
+part 'src/models/objects/event.dart';
+part 'src/models/objects/extension_data.dart';
+part 'src/models/objects/frame.dart';
+part 'src/models/objects/instance.dart';
+part 'src/models/objects/isolate.dart';
+part 'src/models/objects/library.dart';
+part 'src/models/objects/notification.dart';
+part 'src/models/objects/object.dart';
+part 'src/models/objects/script.dart';
+part 'src/models/objects/source_location.dart';
+part 'src/models/objects/target.dart';
+part 'src/models/objects/timeline_event.dart';
+part 'src/models/objects/vm.dart';
+
+part 'src/models/repositories/notification.dart';
diff --git a/runtime/observatory/lib/repositories.dart b/runtime/observatory/lib/repositories.dart
new file mode 100644
index 0000000..5e333ad
--- /dev/null
+++ b/runtime/observatory/lib/repositories.dart
@@ -0,0 +1,10 @@
+// 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 repositories;
+
+import 'dart:async';
+import 'package:observatory/models.dart' as M;
+
+part 'src/repositories/notification.dart';
diff --git a/runtime/observatory/lib/service.dart b/runtime/observatory/lib/service.dart
index cb6f317..c3775a3 100644
--- a/runtime/observatory/lib/service.dart
+++ b/runtime/observatory/lib/service.dart
@@ -11,6 +11,7 @@
 
 import 'package:logging/logging.dart';
 import 'package:observatory/cpu_profile.dart';
+import 'package:observatory/models.dart' as M;
 import 'package:observatory/object_graph.dart';
 import 'package:observatory/tracer.dart';
 import 'package:observe/observe.dart';
diff --git a/runtime/observatory/lib/service_common.dart b/runtime/observatory/lib/service_common.dart
index ba55349..8e7b5c0 100644
--- a/runtime/observatory/lib/service_common.dart
+++ b/runtime/observatory/lib/service_common.dart
@@ -9,13 +9,14 @@
 import 'dart:typed_data';
 
 import 'package:logging/logging.dart';
+import 'package:observatory/models.dart' as M;
 import 'package:observatory/service.dart';
 
 // Export the service library.
 export 'package:observatory/service.dart';
 
 /// Description of a VM target.
-class WebSocketVMTarget {
+class WebSocketVMTarget implements M.Target {
   // Last time this VM has been connected to.
   int lastConnectionTime = 0;
   bool get hasEverConnected => lastConnectionTime > 0;
diff --git a/runtime/observatory/lib/src/app/application.dart b/runtime/observatory/lib/src/app/application.dart
index be95803..b37eda2 100644
--- a/runtime/observatory/lib/src/app/application.dart
+++ b/runtime/observatory/lib/src/app/application.dart
@@ -4,19 +4,12 @@
 
 part of app;
 
-class Notification {
-  Notification.fromEvent(this.event);
-  Notification.fromException(this.exception, this.stacktrace);
-
-  ServiceEvent event;
-  var exception;
-  var stacktrace;
-}
-
 /// The observatory application. Instances of this are created and owned
 /// by the observatory_application custom element.
 class ObservatoryApplication extends Observable {
   static ObservatoryApplication app;
+  final RenderingQueue queue = new RenderingQueue();
+  final NotificationRepository notifications = new NotificationRepository();
   final _pageRegistry = new List<Page>();
   LocationManager _locationManager;
   LocationManager get locationManager => _locationManager;
@@ -31,7 +24,7 @@
     }
     if (_vm != null) {
       // Disconnect from current VM.
-      notifications.clear();
+      notifications.deleteAll();
       _vm.disconnect();
     }
     if (vm != null) {
@@ -41,7 +34,7 @@
         if (vm is WebSocketVM) {
           targets.add(vm.target);
         }
-        _removeDisconnectEvents();
+        notifications.deleteDisconnectEvents();
       });
 
       vm.onDisconnect.then((String reason) {
@@ -50,8 +43,8 @@
           return;
         }
         notifications.add(
-            new Notification.fromEvent(
-                new ServiceEvent.connectionClosed(reason)));
+            new EventNotification.fromServiceEvent(
+              new ServiceEvent.connectionClosed(reason)));
       });
 
       vm.listenEventStream(VM.kIsolateStream, _onEvent);
@@ -65,8 +58,6 @@
   TraceViewElement _traceView = null;
 
   @reflectable ServiceObject lastErrorOrException;
-  @observable ObservableList<Notification> notifications =
-      new ObservableList<Notification>();
 
   void _initOnce() {
     assert(app == null);
@@ -77,15 +68,6 @@
     locationManager._visit();
   }
 
-  void removePauseEvents(Isolate isolate) {
-    notifications.removeWhere((notification) {
-        var event = notification.event;
-        return (event != null &&
-                event.isolate == isolate &&
-                event.isPauseEvent);
-      });
-  }
-
   void _onEvent(ServiceEvent event) {
     assert(event.kind != ServiceEvent.kNone);
 
@@ -102,12 +84,12 @@
         break;
 
       case ServiceEvent.kIsolateReload:
-        notifications.add(new Notification.fromEvent(event));
+        notifications.add(new EventNotification.fromServiceEvent(event));
         break;
 
       case ServiceEvent.kIsolateExit:
       case ServiceEvent.kResume:
-        removePauseEvents(event.isolate);
+        notifications.deletePauseEvents(isolate: event.isolate);
         break;
 
       case ServiceEvent.kPauseStart:
@@ -115,12 +97,12 @@
       case ServiceEvent.kPauseBreakpoint:
       case ServiceEvent.kPauseInterrupted:
       case ServiceEvent.kPauseException:
-        removePauseEvents(event.isolate);
-        notifications.add(new Notification.fromEvent(event));
+        notifications.deletePauseEvents(isolate: event.isolate);
+        notifications.add(new EventNotification.fromServiceEvent(event));
         break;
 
       case ServiceEvent.kInspect:
-        notifications.add(new Notification.fromEvent(event));
+        notifications.add(new EventNotification.fromServiceEvent(event));
         break;
 
       default:
@@ -219,14 +201,6 @@
     _initOnce();
   }
 
-  void _removeDisconnectEvents() {
-    notifications.removeWhere((notification) {
-        var event = notification.event;
-        return (event != null &&
-                event.kind == ServiceEvent.kConnectionClosed);
-      });
-  }
-
   loadCrashDump(Map crashDump) {
     this.vm = new FakeVM(crashDump['result']);
     app.locationManager.go('#/vm');
@@ -242,7 +216,7 @@
 
     // TODO(turnidge): Report this failure via analytics.
     Logger.root.warning('Caught exception: ${e}\n${st}');
-    notifications.add(new Notification.fromException(e, st));
+    notifications.add(new ExceptionNotification(e, stacktrace: st));
   }
 
   // This map keeps track of which curly-blocks have been expanded by the user.
diff --git a/runtime/observatory/lib/src/app/location_manager.dart b/runtime/observatory/lib/src/app/location_manager.dart
index 577cb92..64ea764 100644
--- a/runtime/observatory/lib/src/app/location_manager.dart
+++ b/runtime/observatory/lib/src/app/location_manager.dart
@@ -54,6 +54,11 @@
   /// Update the application location. After this function returns,
   /// [uri] and [debugArguments] will be updated.
   _updateApplicationLocation(String url) {
+    if (url == makeLink('/vm-connect')) {
+      // When we go to the vm-connect page, drop all notifications.
+      _app.notifications.deleteAll();
+    }
+
     // Chop off leading '#'.
     if (url.startsWith('#')) {
       url = url.substring(1);
@@ -115,11 +120,6 @@
       url = makeLink('/vm-connect');
     }
 
-    if (url == makeLink('/vm-connect')) {
-      // When we go to the vm-connect page, drop all notifications.
-      _app.notifications.clear();
-    }
-
     if (addToBrowserHistory) {
       _addToBrowserHistory(url);
     }
diff --git a/runtime/observatory/lib/src/app/notification.dart b/runtime/observatory/lib/src/app/notification.dart
new file mode 100644
index 0000000..b95c34e
--- /dev/null
+++ b/runtime/observatory/lib/src/app/notification.dart
@@ -0,0 +1,115 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of app;
+
+class ExceptionNotification implements M.ExceptionNotification {
+  final Exception exception;
+  /// [optional]
+  final StackTrace stacktrace;
+  ExceptionNotification(this.exception, {this.stacktrace});
+}
+
+class EventNotification implements M.EventNotification {
+  final M.Event event;
+  EventNotification(this.event);
+  factory EventNotification.fromServiceEvent(ServiceEvent event) {
+    M.Event e;
+    switch(event.kind) {
+      case ServiceEvent.kVMUpdate:
+        e = new VMUpdateEventMock(timestamp: event.timestamp, vm: event.vm);
+        break;
+      case ServiceEvent.kIsolateStart:
+        e = new IsolateStartEventMock(timestamp: event.timestamp,
+            isolate: event.isolate);
+        break;
+      case ServiceEvent.kIsolateRunnable:
+        e = new IsolateRunnableEventMock(timestamp: event.timestamp,
+            isolate: event.isolate);
+        break;
+      case ServiceEvent.kIsolateExit:
+        e = new IsolateExitEventMock(timestamp: event.timestamp,
+            isolate: event.isolate);
+        break;
+      case ServiceEvent.kIsolateUpdate:
+        e = new IsolateUpdateEventMock(timestamp: event.timestamp,
+            isolate: event.isolate);
+        break;
+      case ServiceEvent.kIsolateReload:
+        // TODO(bernaschina) add error: realoadError.
+        e = new IsolateRealodEventMock(timestamp: event.timestamp,
+            isolate: event.isolate);
+        break;
+      case ServiceEvent.kServiceExtensionAdded:
+        e = new ServiceExtensionAddedEventMock(timestamp: event.timestamp,
+            isolate: event.isolate, extensionRPC: event.extensionRPC);
+        break;
+      case ServiceEvent.kPauseStart:
+        e = new PauseStartEventMock(timestamp: event.timestamp,
+            isolate: event.isolate);
+        break;
+      case ServiceEvent.kPauseExit:
+        e = new PauseExitEventMock(timestamp: event.timestamp,
+            isolate: event.isolate);
+        break;
+      case ServiceEvent.kPauseBreakpoint:
+        // TODO(cbernaschina) add pauseBreakpoints.
+        e = new PauseBreakpointEventMock(timestamp: event.timestamp,
+            isolate: event.isolate, breakpoint: event.breakpoint,
+            pauseBreakpoints: const <M.Breakpoint>[],
+            topFrame: event.topFrame,
+            atAsyncSuspension: event.atAsyncSuspension);
+        break;
+      case ServiceEvent.kPauseInterrupted:
+        e = new PauseInterruptedEventMock(timestamp: event.timestamp,
+            isolate: event.isolate, topFrame: event.topFrame,
+            atAsyncSuspension: event.atAsyncSuspension);
+        break;
+      case ServiceEvent.kPauseException:
+        // TODO(cbernaschina) add exception.
+        e = new PauseExceptionEventMock(timestamp: event.timestamp,
+            isolate: event.isolate, topFrame: event.topFrame);
+        break;
+      case ServiceEvent.kNone:
+        e = new NoneEventMock(timestamp: event.timestamp,
+            isolate: event.isolate);
+        break;
+      case ServiceEvent.kResume:
+        e = new ResumeEventMock(timestamp: event.timestamp,
+            isolate: event.isolate);
+        break;
+      case ServiceEvent.kBreakpointAdded:
+        e = new BreakpointAddedEventMock(timestamp: event.timestamp,
+            isolate: event.isolate, breakpoint: event.breakpoint);
+        break;
+      case ServiceEvent.kBreakpointResolved:
+        e = new BreakpointResolvedEventMock(timestamp: event.timestamp,
+            isolate: event.isolate, breakpoint: event.breakpoint);
+        break;
+      case ServiceEvent.kBreakpointRemoved:
+        e = new BreakpointRemovedEventMock(timestamp: event.timestamp,
+            isolate: event.isolate, breakpoint: event.breakpoint);
+        break;
+      case ServiceEvent.kGC:
+        e = new GCEventMock(timestamp: event.timestamp,
+            isolate: event.isolate);
+        break;
+      case ServiceEvent.kInspect:
+       // TODO(cbernaschina) add inspectee: event.inspectee.
+        e = new InspectEventMock(timestamp: event.timestamp,
+            isolate: event.isolate);
+        break;
+      case ServiceEvent.kConnectionClosed:
+        e = new ConnectionClockedEventMock(timestamp: event.timestamp,
+            reason: event.reason);
+        break;
+      case ServiceEvent.kExtension:
+        e = new ExtensionEventMock(timestamp: event.timestamp,
+            isolate: event.isolate, extensionKind: event.extensionKind,
+            extensionData: event.extensionData);
+        break;
+    }
+    return new EventNotification(e);
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/action_link.html b/runtime/observatory/lib/src/elements/action_link.html
index 46ced34..1b0438b 100644
--- a/runtime/observatory/lib/src/elements/action_link.html
+++ b/runtime/observatory/lib/src/elements/action_link.html
@@ -1,8 +1,8 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="instance_ref.html">
-<link rel="import" href="observatory_element.html">
 
-<polymer-element name="action-link" extends="observatory-element">
+
+<polymer-element name="action-link">
   <template>
     <style>
       .idle {
diff --git a/runtime/observatory/lib/src/elements/class_ref.html b/runtime/observatory/lib/src/elements/class_ref.html
index c3ddec7..1ffe1d1 100644
--- a/runtime/observatory/lib/src/elements/class_ref.html
+++ b/runtime/observatory/lib/src/elements/class_ref.html
@@ -1,9 +1,8 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="curly_block.html">
-<link rel="import" href="observatory_element.html">
+
 <link rel="import" href="service_ref.html">
 
-<polymer-element name="class-ref" extends="service-ref">
+<polymer-element name="class-ref">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
diff --git a/runtime/observatory/lib/src/elements/class_tree.html b/runtime/observatory/lib/src/elements/class_tree.html
index c1e9635..94e43f7 100644
--- a/runtime/observatory/lib/src/elements/class_tree.html
+++ b/runtime/observatory/lib/src/elements/class_tree.html
@@ -1,9 +1,7 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="nav_bar.html">
-<link rel="import" href="observatory_element.html">
 <link rel="import" href="class_ref.html">
 
-<polymer-element name="class-tree" extends="observatory-element">
+<polymer-element name="class-tree">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
@@ -31,6 +29,7 @@
       <vm-nav-menu vm="{{ isolate.vm }}"></vm-nav-menu>
       <isolate-nav-menu isolate="{{ isolate }}"></isolate-nav-menu>
       <nav-menu link="{{ makeLink('/class-tree', isolate) }}" anchor="class hierarchy" last="{{ true }}"></nav-menu>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
     <div class="content-centered">
       <h1>Class Hierarchy</h1>
diff --git a/runtime/observatory/lib/src/elements/class_view.html b/runtime/observatory/lib/src/elements/class_view.html
index 086b96b..df003cd 100644
--- a/runtime/observatory/lib/src/elements/class_view.html
+++ b/runtime/observatory/lib/src/elements/class_view.html
@@ -1,20 +1,16 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="action_link.html">
 <link rel="import" href="cpu_profile.html">
-<link rel="import" href="curly_block.html">
 <link rel="import" href="eval_box.html">
 <link rel="import" href="eval_link.html">
 <link rel="import" href="field_ref.html">
 <link rel="import" href="function_ref.html">
 <link rel="import" href="instance_ref.html">
 <link rel="import" href="library_ref.html">
-<link rel="import" href="nav_bar.html">
-<link rel="import" href="observatory_element.html">
 <link rel="import" href="script_inset.html">
 <link rel="import" href="script_ref.html">
-<link rel="import" href="view_footer.html">
 
-<polymer-element name="class-view" extends="observatory-element">
+<polymer-element name="class-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <nav-bar>
@@ -25,6 +21,7 @@
       <class-nav-menu cls="{{ cls }}" last="{{ true }}"></class-nav-menu>
       <nav-refresh callback="{{ refreshAllocationProfile }}" label="Refresh Allocation Profile"></nav-refresh>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content">
diff --git a/runtime/observatory/lib/src/elements/code_ref.html b/runtime/observatory/lib/src/elements/code_ref.html
index c20fdb5..4a8c7f5 100644
--- a/runtime/observatory/lib/src/elements/code_ref.html
+++ b/runtime/observatory/lib/src/elements/code_ref.html
@@ -1,7 +1,7 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="service_ref.html">
 
-<polymer-element name="code-ref" extends="service-ref">
+<polymer-element name="code-ref">
   <template><link rel="stylesheet" href="css/shared.css"></template>
 </polymer-element>
 
diff --git a/runtime/observatory/lib/src/elements/code_view.html b/runtime/observatory/lib/src/elements/code_view.html
index 95f71e2..10e280c 100644
--- a/runtime/observatory/lib/src/elements/code_view.html
+++ b/runtime/observatory/lib/src/elements/code_view.html
@@ -1,12 +1,9 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="function_ref.html">
 <link rel="import" href="instance_ref.html">
-<link rel="import" href="observatory_element.html">
-<link rel="import" href="nav_bar.html">
 <link rel="import" href="script_ref.html">
-<link rel="import" href="view_footer.html">
 
-<polymer-element name="code-view" extends="observatory-element">
+<polymer-element name="code-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
@@ -59,6 +56,7 @@
       <nav-menu link="{{ makeLink('/inspect', code) }}" anchor="{{ code.name }}" last="{{ true }}"></nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
       <nav-refresh callback="{{ refreshTicks }}" label="Refresh Ticks"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
     <div class="content">
       <template if="{{ code.isDartCode && code.isOptimized }}">
diff --git a/runtime/observatory/lib/src/elements/context_ref.html b/runtime/observatory/lib/src/elements/context_ref.html
index 82e313d..9beb691 100644
--- a/runtime/observatory/lib/src/elements/context_ref.html
+++ b/runtime/observatory/lib/src/elements/context_ref.html
@@ -1,9 +1,8 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="curly_block.html">
-<link rel="import" href="observatory_element.html">
+
 <link rel="import" href="service_ref.html">
 
-<polymer-element name="context-ref" extends="service-ref">
+<polymer-element name="context-ref">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <span>
diff --git a/runtime/observatory/lib/src/elements/context_view.html b/runtime/observatory/lib/src/elements/context_view.html
index 44972f3..f9a2fbf 100644
--- a/runtime/observatory/lib/src/elements/context_view.html
+++ b/runtime/observatory/lib/src/elements/context_view.html
@@ -3,13 +3,10 @@
 <link rel="import" href="field_ref.html">
 <link rel="import" href="function_ref.html">
 <link rel="import" href="instance_ref.html">
-<link rel="import" href="observatory_element.html">
-<link rel="import" href="nav_bar.html">
 <link rel="import" href="object_common.html">
 <link rel="import" href="context_ref.html">
-<link rel="import" href="view_footer.html">
 
-<polymer-element name="context-view" extends="observatory-element">
+<polymer-element name="context-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <nav-bar>
@@ -20,6 +17,7 @@
       <class-nav-menu cls="{{ context.clazz }}"></class-nav-menu>
       <nav-menu link="." anchor="instance" last="{{ true }}"></nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <template if="{{ !context.isError }}">
diff --git a/runtime/observatory/lib/src/elements/cpu_profile.html b/runtime/observatory/lib/src/elements/cpu_profile.html
index 50db2db..05fc581 100644
--- a/runtime/observatory/lib/src/elements/cpu_profile.html
+++ b/runtime/observatory/lib/src/elements/cpu_profile.html
@@ -1,12 +1,8 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="code_ref.html">
 <link rel="import" href="function_ref.html">
-<link rel="import" href="nav_bar.html">
-<link rel="import" href="observatory_element.html">
-<link rel="import" href="sliding_checkbox.html">
-<link rel="import" href="view_footer.html">
 
-<polymer-element name="sample-buffer-control" extends="observatory-element">
+<polymer-element name="sample-buffer-control">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
@@ -115,7 +111,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="stack-trace-tree-config" extends="observatory-element">
+<polymer-element name="stack-trace-tree-config">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
@@ -182,7 +178,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="cpu-profile-tree" extends="observatory-element">
+<polymer-element name="cpu-profile-tree">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
@@ -254,7 +250,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="cpu-profile-virtual-tree" extends="observatory-element">
+<polymer-element name="cpu-profile-virtual-tree">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
@@ -277,7 +273,7 @@
 </polymer-element>
 
 
-<polymer-element name="cpu-profile-table" extends="observatory-element">
+<polymer-element name="cpu-profile-table">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <nav-bar>
@@ -287,6 +283,7 @@
       <nav-menu link="{{ makeLink('/profiler-table', isolate) }}" anchor="cpu profile (table)" last="{{ true }}"></nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
       <nav-refresh callback="{{ clearCpuProfile }}" label="Clear"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
     <style>
       /* general */
@@ -491,7 +488,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="cpu-profile" extends="observatory-element">
+<polymer-element name="cpu-profile">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <nav-bar>
@@ -501,6 +498,7 @@
       <nav-menu link="{{ makeLink('/profiler', isolate) }}" anchor="cpu profile" last="{{ true }}"></nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
       <nav-refresh callback="{{ clearCpuProfile }}" label="Clear"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
     <style>
       .tableWell {
diff --git a/runtime/observatory/lib/src/elements/css/shared.css b/runtime/observatory/lib/src/elements/css/shared.css
index 3442d98..75b35ce 100644
--- a/runtime/observatory/lib/src/elements/css/shared.css
+++ b/runtime/observatory/lib/src/elements/css/shared.css
@@ -7,6 +7,10 @@
   box-sizing: border-box;
 }
 
+body {
+  padding-top: 56px;
+}
+
 .content {
   padding-left: 10%;
   font: 400 14px 'Montserrat', sans-serif;
@@ -354,3 +358,131 @@
   animation: shake 0.5s;
   -webkit-animation: shake 0.5s;
 }
+
+/* nav-notify */
+/* TODO(cbernaschina) fix nav-notify-ref-wrapped to nav-notify-ref when wrapper
+removed */
+nav-notify-wrapped > div {
+  float: right;
+}
+nav-notify-wrapped > div > div {
+  display: block;
+  position: absolute;
+  top: 98%;
+  right: 0;
+  margin: 0;
+  padding: 0;
+  width: auto;
+  z-index: 1000;
+  background: none;
+}
+
+/* nav-exception & nav-event */
+
+nav-exception > div, nav-event > div {
+  position: relative;
+  padding: 16px;
+  margin-top: 10px;
+  margin-right: 10px;
+  padding-right: 25px;
+  width: 500px;
+  color: #ddd;
+  background: rgba(0,0,0,.6);
+  border: solid 2px white;
+  box-shadow: 0 0 5px black;
+  border-radius: 5px;
+  animation: fadein 1s;
+}
+
+nav-exception *, nav-event * {
+  color: #ddd;
+  font-size: 12px;
+}
+
+nav-exception > div > a, nav-event > div > a {
+  color: white;
+  text-decoration: none;
+}
+
+nav-exception > div > a:hover, nav-event > div > a:hover {
+  text-decoration: underline;
+}
+
+nav-exception > div > div {
+  margin-left:20px;
+  white-space: pre
+}
+
+nav-exception > div > button, nav-event > div > button {
+  background: transparent;
+  border: none;
+  position: absolute;
+  display: block;
+  top: 4px;
+  right: 4px;
+  height: 18px;
+  width: 18px;
+  line-height: 16px;
+  border-radius: 9px;
+  color: white;
+  font-size: 18px;
+  cursor: pointer;
+  text-align: center;
+}
+
+nav-exception > div > button:hover, nav-event > div > button:hover {
+  background: rgba(255,255,255,0.5);
+}
+
+/* nav-refresh */
+/* TODO(cbernaschina) fix nav-refresh-wrapped to nav-refresh when wrapper
+removed */
+
+nav-refresh-wrapped > li > button {
+  color: #000;
+  margin: 3px;
+  padding: 8px;
+  border-width: 2px;
+  line-height: 13px;
+  font: 400 13px 'Montserrat', sans-serif;
+}
+nav-refresh-wrapped > li > button[disabled] {
+  color: #aaa;
+  cursor: wait;
+}
+nav-refresh-wrapped > li {
+  float: right;
+  margin: 0;
+}
+
+/* view-footer */
+
+view-footer {
+  padding: 1em;
+  padding-top: 10.3em;
+  float: right;
+  align-content: right;
+}
+
+view-footer > a {
+  margin-bottom: 0.17em;
+  font-size: 90%;
+  float: right;
+  clear: both;
+  display: block;
+}
+
+/* vm-connect-target */
+/* TODO(cbernaschina) fix vm-connect-target-wrapped to vm-connect-target
++when wrapper removed */
+
+vm-connect-target-wrapped > button.delete-button {
+  margin-left: 0.28em;
+  padding: 4px;
+  background: transparent;
+  border: none !important;
+}
+
+vm-connect-target-wrapped > button.delete-button:hover {
+  background: #ff0000;
+}
diff --git a/runtime/observatory/lib/src/elements/curly_block.dart b/runtime/observatory/lib/src/elements/curly_block.dart
index 004a02e..9eadd76 100644
--- a/runtime/observatory/lib/src/elements/curly_block.dart
+++ b/runtime/observatory/lib/src/elements/curly_block.dart
@@ -4,52 +4,104 @@
 
 library curly_block_element;
 
-import 'package:polymer/polymer.dart';
-import 'observatory_element.dart';
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
 
-@CustomTag('curly-block')
-class CurlyBlockElement extends ObservatoryElement {
-  CurlyBlockElement.created() : super.created();
+class CurlyBlockToggleEvent {
+  final CurlyBlockElement control;
 
-  @observable bool expanded = false;
-  @observable bool busy = false;
-  @published var callback = null;
-  @published bool expand = false;
-  @published String expandKey;
+  CurlyBlockToggleEvent(this.control);
+}
 
-  void expandChanged(oldValue) {
-    expanded = expand;
+class CurlyBlockElement extends HtmlElement implements Renderable {
+  static final StyleElement _style = () {
+      var style = new StyleElement();
+      style.text = '''span.curly-block {
+                        color: #0489c3;
+                        cursor: pointer;
+                      }
+                      span.curly-block.disabled {
+                        color: white;
+                        cursor: wait;
+                      }''';
+      return style;
+  }();
+
+  static const tag = const Tag<CurlyBlockElement>('curly-block-wrapped');
+
+  RenderingScheduler<CurlyBlockElement> _r;
+
+  final StreamController<CurlyBlockToggleEvent> _onToggle =
+      new StreamController<CurlyBlockToggleEvent>.broadcast();
+  Stream<CurlyBlockToggleEvent> get onToggle => _onToggle.stream;
+  Stream<RenderedEvent<CurlyBlockElement>> get onRendered => _r.onRendered;
+
+  bool _expanded;
+  bool _disabled;
+
+  bool get expanded => _expanded;
+  set expanded(bool value) {
+    if (_expanded != value) _onToggle.add(new CurlyBlockToggleEvent(this));
+    _expanded = _r.checkAndReact(_expanded, value);
+  }
+  bool get disabled => _disabled;
+  set disabled(bool value) => _disabled = _r.checkAndReact(_disabled, value);
+
+  factory CurlyBlockElement({bool expanded: false, bool disabled: false,
+      RenderingQueue queue}) {
+    assert(expanded != null);
+    assert(disabled != null);
+    CurlyBlockElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._expanded = expanded;
+    e._disabled = disabled;
+    return e;
   }
 
-  void expandKeyChanged(oldValue) {
-    if (expandKey != null) {
-      var value = app.expansions[expandKey];
-      if (value != null) {
-        if (expanded != value) {
-          toggleExpand(null, null, null);
-        }
-      }
-    }
+  CurlyBlockElement.created() : super.created() { createShadowRoot(); }
+
+  @override
+  void attached() { super.attached(); _r.enable(); }
+
+  @override
+  void detached() {
+    super.detached(); _r.disable(notify: true);
+    shadowRoot.children = [];
   }
 
-  void doneCallback() {
-    expanded = !expanded;
-    if (expandKey != null) {
-      app.expansions[expandKey] = expanded;
-    }
-    busy = false;
-  }
-
-  void toggleExpand(var event, var b, var c) {
-    assert(callback == null || expand == false);
-    if (busy) {
+  void toggle() {
+    if (disabled) {
+      _r.scheduleNotification();
       return;
     }
-    busy = true;
-    if (callback != null) {
-      callback(!expanded, doneCallback);
+    expanded = !expanded;
+  }
+
+  void render() {
+    List<Element> children = [
+      _style.clone(true),
+      new SpanElement()..text = '{'
+    ];
+    SpanElement label = new SpanElement()
+      ..classes = disabled ? ['curly-block', 'disabled'] : ['curly-block']
+      ..innerHtml = expanded ?
+        '&nbsp;&nbsp;&#8863;&nbsp;&nbsp;' : '&nbsp;&nbsp;&#8862;&nbsp;&nbsp;';
+    if (disabled) {
+      children.add(label);
     } else {
-      doneCallback();
+      children.add(new AnchorElement()
+        ..onClick.listen((_) { toggle(); })
+        ..children = [label]);
     }
+    if (expanded) {
+      children.addAll([
+        new BRElement(),
+        new ContentElement()
+      ]);
+    }
+    children.add(new SpanElement()..text = '}');
+    shadowRoot.children = children;
   }
 }
diff --git a/runtime/observatory/lib/src/elements/curly_block.html b/runtime/observatory/lib/src/elements/curly_block.html
deleted file mode 100644
index d1702a2..0000000
--- a/runtime/observatory/lib/src/elements/curly_block.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="observatory_element.html">
-
-<polymer-element name="curly-block" extends="observatory-element">
-  <template>
-    <style>
-      .idle {
-        display: inline-block;
-        color: #0489c3;
-        cursor: pointer;
-      }
-      .busy {
-        display: inline-block;
-        color: white;
-        cursor: wait;
-      }
-    </style>
-    <template if="{{ expanded }}">
-      <template if="{{ busy }}">
-        {<div class="busy">&nbsp;&nbsp;&#8863;&nbsp;&nbsp;</div>
-        <br>
-        <content></content>
-        }
-      </template>
-      <template if="{{ !busy }}">
-        {<a on-click="{{ toggleExpand }}"><div class="idle">&nbsp;&nbsp;&#8863;&nbsp;&nbsp;</div></a>
-        <br>
-        <content></content>
-        }
-      </template>
-    </template>
-
-    <template if="{{ !expanded }}">
-      <template if="{{ busy }}">
-        {<div class="busy">&nbsp;&nbsp;&#8862;&nbsp;&nbsp;</div>}
-      </template>
-      <template if="{{ !busy }}">
-        {<a on-click="{{ toggleExpand }}"><div class="idle">&nbsp;&nbsp;&#8862;&nbsp;&nbsp;</div></a>}
-      </template>
-    </template>
-  </template>
-</polymer-element>
-
-<script type="application/dart" src="curly_block.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/curly_block_wrapper.dart b/runtime/observatory/lib/src/elements/curly_block_wrapper.dart
new file mode 100644
index 0000000..2a141b5
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/curly_block_wrapper.dart
@@ -0,0 +1,100 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:observatory/app.dart';
+import 'package:observatory/src/elements/curly_block.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/shims/binding.dart';
+
+typedef _callback();
+typedef CurlyBlockToggleCallback(bool a, _callback b);
+
+class CurlyBlockElementWrapper extends HtmlElement {
+
+  static final binder = new Binder<CurlyBlockElementWrapper>(
+    const [const Binding('expand'), const Binding('busy'),
+           const Binding('expandKey'), const Binding('callback')]);
+
+  static const tag = const Tag<CurlyBlockElementWrapper>('curly-block');
+
+  bool _expand;
+  bool get expand => _expand;
+  set expand(bool expanded) {
+    _expand = !(expanded == null || expanded == false);
+    render();
+  }
+
+  bool _busy;
+  bool get busy => _busy;
+  set busy(bool busy) {
+    _busy = !(busy == null || busy == false);
+    render();
+  }
+
+  String _expandKey;
+  String get expandKey => _expandKey;
+  set expandKey(String expandKey) {
+    _expandKey = expandKey;
+    if (expandKey != null) {
+      var value = application.expansions[expandKey];
+      if (value != null && expand != value) {
+
+      }
+    }
+    render();
+  }
+
+  CurlyBlockToggleCallback _callback;
+  CurlyBlockToggleCallback get callback => _callback;
+  set callback(CurlyBlockToggleCallback callback) {
+    _callback = callback;
+    render();
+  }
+
+  CurlyBlockElementWrapper.created() : super.created() {
+    binder.registerCallback(this);
+    createShadowRoot();
+    _expand = !_isFalseOrNull(getAttribute('expand'));
+    _busy = !_isFalseOrNull(getAttribute('busy'));
+    _expandKey = getAttribute('expandKey');
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    render();
+  }
+
+  void render() {
+    shadowRoot.children = [
+      new CurlyBlockElement(expanded: expand, disabled: busy,
+                                 queue: ObservatoryApplication.app.queue)
+        ..children = [new ContentElement()]
+        ..onToggle.listen(_toggle)
+    ];
+  }
+
+  ObservatoryApplication get application => ObservatoryApplication.app;
+
+  void _toggle(CurlyBlockToggleEvent e) {
+    _expand = e.control.expanded;
+    if (callback != null) {
+      busy = true;
+      callback(expand, () {
+        if (expandKey != null) {
+          application.expansions[expandKey] = expand;
+        }
+        busy = false;
+      });
+    } else {
+      application.expansions[expandKey] = expand;
+    }
+  }
+
+  bool _isFalseOrNull(String value) {
+    return value == null || value == false;
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart
index 61a8989..4ced2d6 100644
--- a/runtime/observatory/lib/src/elements/debugger.dart
+++ b/runtime/observatory/lib/src/elements/debugger.dart
@@ -8,7 +8,6 @@
 import 'dart:html';
 import 'dart:math';
 import 'observatory_element.dart';
-import 'nav_bar.dart';
 import 'package:observatory/app.dart';
 import 'package:observatory/cli.dart';
 import 'package:observatory/debugger.dart';
@@ -2005,7 +2004,8 @@
     var cmdDiv = $['commandDiv'];
 
     // For now, force navbar height to 40px in the debugger.
-    int navbarHeight = NavBarElement.height;
+    // TODO (cbernaschina) check if this is needed.
+    const navbarHeight = 40;
     int splitterHeight = splitterDiv.clientHeight;
     int cmdHeight = cmdDiv.clientHeight;
 
@@ -2255,7 +2255,8 @@
     if (varsDiv == null) {
       return minTop;
     }
-    const navbarHeight = NavBarElement.height;
+    // TODO (cbernaschina) check if this is needed.
+    const navbarHeight = 40;
     const bottomPad = 6;
     var parent = varsDiv.parent.getBoundingClientRect();
     var varsHeight = varsDiv.clientHeight;
diff --git a/runtime/observatory/lib/src/elements/debugger.html b/runtime/observatory/lib/src/elements/debugger.html
index 20e2e4d..54fee31 100644
--- a/runtime/observatory/lib/src/elements/debugger.html
+++ b/runtime/observatory/lib/src/elements/debugger.html
@@ -1,8 +1,6 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="function_ref.html">
-<link rel="import" href="nav_bar.html">
 <link rel="import" href="eval_link.html">
-<link rel="import" href="observatory_element.html">
 <link rel="import" href="script_inset.html">
 <link rel="import" href="script_ref.html">
 
@@ -72,7 +70,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="debugger-page" extends="observatory-element">
+<polymer-element name="debugger-page">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
@@ -109,11 +107,13 @@
     </style>
 
     <div class="container">
-      <nav-bar id="navbarDiv" notifyOnPause="{{ false }}">
+      <nav-bar id="navbarDiv" >
         <top-nav-menu></top-nav-menu>
 	<vm-nav-menu vm="{{ isolate.vm }}"></vm-nav-menu>
         <isolate-nav-menu isolate="{{ isolate }}"></isolate-nav-menu>
         <nav-menu link="{{ makeLink('/debugger', isolate) }}" anchor="debugger" last="{{ true }}"></nav-menu>
+        <nav-notify notifications="{{ app.notifications }}"
+                                      notifyOnPause="{{ false }}"></nav-notify>
       </nav-bar>
       <div id="stackDiv" class="stack">
         <debugger-stack id="stackElement" isolate="{{ isolate }}"></debugger-stack>
@@ -132,7 +132,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="debugger-stack" extends="observatory-element">
+<polymer-element name="debugger-stack">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
@@ -183,7 +183,7 @@
 </polymer-element>
 
 
-<polymer-element name="debugger-frame" extends="observatory-element">
+<polymer-element name="debugger-frame">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
@@ -299,7 +299,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="debugger-message" extends="observatory-element">
+<polymer-element name="debugger-message">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
@@ -404,7 +404,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="debugger-console" extends="observatory-element">
+<polymer-element name="debugger-console">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
@@ -443,7 +443,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="debugger-input" extends="observatory-element">
+<polymer-element name="debugger-input">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
diff --git a/runtime/observatory/lib/src/elements/error_ref.html b/runtime/observatory/lib/src/elements/error_ref.html
index 57de134..a132039 100644
--- a/runtime/observatory/lib/src/elements/error_ref.html
+++ b/runtime/observatory/lib/src/elements/error_ref.html
@@ -1,9 +1,8 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="curly_block.html">
-<link rel="import" href="observatory_element.html">
+
 <link rel="import" href="service_ref.html">
 
-<polymer-element name="error-ref" extends="service-ref">
+<polymer-element name="error-ref">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
diff --git a/runtime/observatory/lib/src/elements/error_view.html b/runtime/observatory/lib/src/elements/error_view.html
index 818ba1e..aa40472 100644
--- a/runtime/observatory/lib/src/elements/error_view.html
+++ b/runtime/observatory/lib/src/elements/error_view.html
@@ -1,13 +1,11 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="nav_bar.html">
-<link rel="import" href="observatory_element.html">
-<link rel="import" href="view_footer.html">
 
-<polymer-element name="error-view" extends="observatory-element">
+<polymer-element name="error-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <nav-bar>
       <top-nav-menu last="{{ true }}"></top-nav-menu>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
     <div class="content-centered">
       <h1>{{ error.kind }}</h1>
diff --git a/runtime/observatory/lib/src/elements/eval_box.html b/runtime/observatory/lib/src/elements/eval_box.html
index f01a995..eb1e639 100644
--- a/runtime/observatory/lib/src/elements/eval_box.html
+++ b/runtime/observatory/lib/src/elements/eval_box.html
@@ -1,9 +1,9 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="instance_ref.html">
 <link rel="import" href="error_ref.html">
-<link rel="import" href="observatory_element.html">
 
-<polymer-element name="eval-box" extends="observatory-element">
+
+<polymer-element name="eval-box">
   <template>
     <style>
       .textbox {
diff --git a/runtime/observatory/lib/src/elements/eval_link.html b/runtime/observatory/lib/src/elements/eval_link.html
index 1fdb584..38d2981 100644
--- a/runtime/observatory/lib/src/elements/eval_link.html
+++ b/runtime/observatory/lib/src/elements/eval_link.html
@@ -1,9 +1,9 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="instance_ref.html">
 <link rel="import" href="error_ref.html">
-<link rel="import" href="observatory_element.html">
 
-<polymer-element name="eval-link" extends="observatory-element">
+
+<polymer-element name="eval-link">
   <template>
     <style>
       .idle {
diff --git a/runtime/observatory/lib/src/elements/field_ref.html b/runtime/observatory/lib/src/elements/field_ref.html
index 762362a..a593d31 100644
--- a/runtime/observatory/lib/src/elements/field_ref.html
+++ b/runtime/observatory/lib/src/elements/field_ref.html
@@ -1,9 +1,9 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="instance_ref.html">
-<link rel="import" href="observatory_element.html">
+
 <link rel="import" href="service_ref.html">
 
-<polymer-element name="field-ref" extends="service-ref">
+<polymer-element name="field-ref">
   <template>
   <link rel="stylesheet" href="css/shared.css">
     <span>
diff --git a/runtime/observatory/lib/src/elements/field_view.html b/runtime/observatory/lib/src/elements/field_view.html
index d9cdefd..4df7b24 100644
--- a/runtime/observatory/lib/src/elements/field_view.html
+++ b/runtime/observatory/lib/src/elements/field_view.html
@@ -2,12 +2,9 @@
 <link rel="import" href="class_ref.html">
 <link rel="import" href="instance_ref.html">
 <link rel="import" href="library_ref.html">
-<link rel="import" href="nav_bar.html">
 <link rel="import" href="script_ref.html">
-<link rel="import" href="observatory_element.html">
-<link rel="import" href="view_footer.html">
 
-<polymer-element name="field-view" extends="observatory-element">
+<polymer-element name="field-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <nav-bar>
@@ -20,6 +17,7 @@
       </template>
       <nav-menu link="{{ makeLink('/inspect', field) }}" anchor="{{ field.name }}" last="{{ true }}"></nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content">
diff --git a/runtime/observatory/lib/src/elements/flag_list.html b/runtime/observatory/lib/src/elements/flag_list.html
index 9a39cbb..2c21db0 100644
--- a/runtime/observatory/lib/src/elements/flag_list.html
+++ b/runtime/observatory/lib/src/elements/flag_list.html
@@ -1,9 +1,6 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="nav_bar.html">
-<link rel="import" href="observatory_element.html">
-<link rel="import" href="view_footer.html">
 
-<polymer-element name="flag-list" extends="observatory-element">
+<polymer-element name="flag-list">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <nav-bar>
@@ -11,6 +8,7 @@
       <vm-nav-menu vm="{{ app.vm }}"></vm-nav-menu>
       <nav-menu link="{{ makeLink('/flags') }}" anchor="flags" last="{{ true }}"></nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content-centered">
@@ -40,7 +38,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="flag-item" extends="observatory-element">
+<polymer-element name="flag-item">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <span style="color:#aaa">// {{ flag['comment'] }}</span>
diff --git a/runtime/observatory/lib/src/elements/function_ref.html b/runtime/observatory/lib/src/elements/function_ref.html
index c9499b3..4669386 100644
--- a/runtime/observatory/lib/src/elements/function_ref.html
+++ b/runtime/observatory/lib/src/elements/function_ref.html
@@ -2,7 +2,7 @@
 <link rel="import" href="class_ref.html">
 <link rel="import" href="service_ref.html">
 
-<polymer-element name="function-ref" extends="service-ref">
+<polymer-element name="function-ref">
   <template><link rel="stylesheet" href="css/shared.css"></template>
 </polymer-element>
 
diff --git a/runtime/observatory/lib/src/elements/function_view.html b/runtime/observatory/lib/src/elements/function_view.html
index a087382..70accd2 100644
--- a/runtime/observatory/lib/src/elements/function_view.html
+++ b/runtime/observatory/lib/src/elements/function_view.html
@@ -3,13 +3,10 @@
 <link rel="import" href="code_ref.html">
 <link rel="import" href="function_ref.html">
 <link rel="import" href="library_ref.html">
-<link rel="import" href="observatory_element.html">
-<link rel="import" href="nav_bar.html">
 <link rel="import" href="script_inset.html">
 <link rel="import" href="script_ref.html">
-<link rel="import" href="view_footer.html">
 
-<polymer-element name="function-view" extends="observatory-element">
+<polymer-element name="function-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <nav-bar>
@@ -22,6 +19,7 @@
       </template>
       <nav-menu link="{{ makeLink('/inspect', function) }}" anchor="{{ function.name }}" last="{{ true }}"></nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content">
diff --git a/runtime/observatory/lib/src/elements/general_error.html b/runtime/observatory/lib/src/elements/general_error.html
index ef1e004..ef809d1 100644
--- a/runtime/observatory/lib/src/elements/general_error.html
+++ b/runtime/observatory/lib/src/elements/general_error.html
@@ -1,12 +1,11 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="nav_bar.html">
-<link rel="import" href="observatory_element.html">
 
-<polymer-element name="general-error" extends="observatory-element">
+<polymer-element name="general-error">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <nav-bar>
       <top-nav-menu last="{{ true }}"></top-nav-menu>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
     <div class="content-centered">
       <h1>Error</h1>
diff --git a/runtime/observatory/lib/src/elements/heap_map.html b/runtime/observatory/lib/src/elements/heap_map.html
index 8c95e22..82aad68 100644
--- a/runtime/observatory/lib/src/elements/heap_map.html
+++ b/runtime/observatory/lib/src/elements/heap_map.html
@@ -1,10 +1,7 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="class_ref.html">
-<link rel="import" href="observatory_element.html">
-<link rel="import" href="nav_bar.html">
-<link rel="import" href="view_footer.html">
 
-<polymer-element name="heap-map" extends="observatory-element">
+<polymer-element name="heap-map">
 <template>
   <link rel="stylesheet" href="css/shared.css">
   <style>
@@ -30,6 +27,7 @@
     <isolate-nav-menu isolate="{{ fragmentation.isolate }}"></isolate-nav-menu>
     <nav-menu link="{{ makeLink('/heap-map', fragmentation.isolate) }}" anchor="heap map" last="{{ true }}"></nav-menu>
     <nav-refresh callback="{{ refresh }}"></nav-refresh>
+    <nav-notify notifications="{{ app.notifications }}"></nav-notify>
   </nav-bar>
   <div class="hover">
     <p style="text-align:center">{{ status }}</p>
diff --git a/runtime/observatory/lib/src/elements/heap_profile.html b/runtime/observatory/lib/src/elements/heap_profile.html
index 5e05d55..47ac16b 100644
--- a/runtime/observatory/lib/src/elements/heap_profile.html
+++ b/runtime/observatory/lib/src/elements/heap_profile.html
@@ -1,10 +1,7 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="class_ref.html">
-<link rel="import" href="observatory_element.html">
-<link rel="import" href="nav_bar.html">
-<link rel="import" href="view_footer.html">
 
-<polymer-element name="heap-profile" extends="observatory-element">
+<polymer-element name="heap-profile">
 <template>
   <link rel="stylesheet" href="css/shared.css">
   <style>
@@ -76,6 +73,7 @@
     <div class="nav-option">
       <input type="checkbox" checked="{{ autoRefresh }}">Auto-refresh on GC
     </div>
+    <nav-notify notifications="{{ app.notifications }}"></nav-notify>
   </nav-bar>
   <div class="content">
     <h1>Allocation Profile</h1>
diff --git a/runtime/observatory/lib/src/elements/heap_snapshot.html b/runtime/observatory/lib/src/elements/heap_snapshot.html
index d593f97..f7a8bf5 100644
--- a/runtime/observatory/lib/src/elements/heap_snapshot.html
+++ b/runtime/observatory/lib/src/elements/heap_snapshot.html
@@ -1,10 +1,7 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="class_ref.html">
-<link rel="import" href="observatory_element.html">
-<link rel="import" href="nav_bar.html">
-<link rel="import" href="view_footer.html">
 
-<polymer-element name="heap-snapshot" extends="observatory-element">
+<polymer-element name="heap-snapshot">
 <template>
   <link rel="stylesheet" href="css/shared.css">
   <nav-bar>
@@ -13,6 +10,7 @@
     <isolate-nav-menu isolate="{{ isolate }}"></isolate-nav-menu>
     <nav-menu link="{{ makeLink('/heap-snapshot', isolate) }}" anchor="heap snapshot" last="{{ true }}"></nav-menu>
     <nav-refresh callback="{{ refresh }}"></nav-refresh>
+    <nav-notify notifications="{{ app.notifications }}"></nav-notify>
   </nav-bar>
   <style>
       /* general */
diff --git a/runtime/observatory/lib/src/elements/helpers/rendering_queue.dart b/runtime/observatory/lib/src/elements/helpers/rendering_queue.dart
new file mode 100644
index 0000000..a6062c3
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/helpers/rendering_queue.dart
@@ -0,0 +1,72 @@
+// 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 'dart:html';
+import 'dart:collection';
+import 'dart:async';
+
+/// A generic rendering task that can be scheduled.
+abstract class RenderingTask {
+  /// Rendering synchronous callback.
+  void render();
+}
+
+/// A generic synchronization system for rendering operations.
+abstract class RenderingBarrier {
+  /// Future to the next synchronization barrier (ms from application start).
+  Future<num> get next;
+}
+
+/// Synchronization system based on the AnimationFrame.
+class NextAnimationFrameBarrier implements RenderingBarrier {
+  Future<num> get next => window.animationFrame;
+}
+
+/// MOCK synchronization system for manual barrier triggering.
+class RenderingBarrierMock implements RenderingBarrier {
+  final StreamController<num> _stream = new StreamController<num>.broadcast();
+  num _ms = 0;
+
+  Future<num> get next => _stream.stream.first;
+
+  /// Trigger the next barrier with an optional numer of ms elapsed.
+  void triggerRenderingBarrier({num step: 20}) {
+    assert(step != null);
+    _stream.add(_ms += step);
+  }
+}
+
+/// RenderingTask queuing and synchronization system.
+class RenderingQueue {
+  final RenderingBarrier _barrier;
+  final Queue<RenderingTask> _queue = new Queue<RenderingTask>();
+
+  bool get isEmpty => _queue.isEmpty;
+  bool get isNotEmpty => _queue.isNotEmpty;
+
+  /// Creates a RenderingQueue with the default synchronization barrier.
+  RenderingQueue() : this.fromBarrier(new NextAnimationFrameBarrier());
+
+  /// Creates a RenderingQueue with a custom synchronization barrier.
+  RenderingQueue.fromBarrier(this._barrier) {
+    assert(this._barrier != null);
+  }
+
+  /// Add a task to the queue.
+  /// If the current rendering phase is running it will be executed during this
+  /// rendering cycle, otherwise it will be queued for the next one.
+  void enqueue(RenderingTask r) {
+    assert(r != null);
+    // If no task are in the queue there is no rendering phase scheduled.
+    if (isEmpty) _render();
+    _queue.addLast(r);
+  }
+
+  Future _render() async {
+    await _barrier.next;
+    while (_queue.isNotEmpty) {
+      _queue.removeFirst().render();
+    }
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/helpers/rendering_scheduler.dart b/runtime/observatory/lib/src/elements/helpers/rendering_scheduler.dart
new file mode 100644
index 0000000..562d04b
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/helpers/rendering_scheduler.dart
@@ -0,0 +1,117 @@
+// 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 'dart:async';
+
+import 'package:observatory/src/elements/helpers/rendering_queue.dart';
+export 'package:observatory/src/elements/helpers/rendering_queue.dart';
+
+/// A generic renderable object.
+abstract class Renderable {
+  void render();
+}
+
+/// Event related to a Renderable rendering phase.
+class RenderedEvent<T extends Renderable> {
+  /// Renderable to which the event is related
+  final T element;
+  /// Is another rendering scheduled for this element.
+  final bool otherRenderScheduled;
+
+  RenderedEvent(this.element, this.otherRenderScheduled) {
+    assert(element != null);
+    assert(otherRenderScheduled != null);
+  }
+}
+
+/// Scheduler for rendering operations.
+class RenderingScheduler<T extends Renderable> implements RenderingTask {
+  bool _enabled = false;
+  bool _dirty = false;
+  bool _renderingScheduled = false;
+  bool _notificationScheduled = false;
+  /// Element managed by this scheduler.
+  final T element;
+  /// Queue used for rendering operations.
+  final RenderingQueue queue;
+
+  final StreamController<RenderedEvent<T>> _onRendered =
+                            new StreamController<RenderedEvent<T>>.broadcast();
+  Stream<RenderedEvent<T>> get onRendered => _onRendered.stream;
+
+  /// Creates a new scheduler for an element.
+  /// If no queue is provided it will create a new default configured queue.
+  factory RenderingScheduler(T element, {RenderingQueue queue}) {
+    assert(element != null);
+    if (queue == null) { queue = new RenderingQueue(); }
+    return new RenderingScheduler<T>._(element, queue);
+  }
+
+  RenderingScheduler._(this.element, this.queue);
+
+  /// Enable the scheduler.
+  /// New dirty or schedule request will be considered.
+  void enable() {
+    if (_enabled) return;
+    _enabled = true;
+    scheduleRendering();
+  }
+
+  /// Disable the scheduler.
+  /// New dirty or schedule request will be discarded.
+  /// [optional] notify: send a final RenderEvent.
+  void disable({bool notify: false}) {
+    assert(notify != null);
+    if (!_enabled) return;
+    _enabled = false;
+    if (notify) scheduleNotification();
+  }
+
+  /// Set the object as dirty. A rendering will be scheduled.
+  void dirty() {
+    if (_dirty) return;
+    _dirty = true;
+    scheduleRendering();
+  }
+
+  /// Checks for modification during attribute set.
+  /// If value changes a new rendering is scheduled.
+  /// set attr(T v) => _attr = _r.checkAndReact(_attr, v);
+  dynamic checkAndReact(dynamic oldValue, dynamic newValue) {
+    if (oldValue != newValue) dirty();
+    else scheduleNotification();
+    return newValue;
+  }
+
+  /// Schedules a new rendering phase.
+  void scheduleRendering() {
+    if (_renderingScheduled) return;
+    if (!_enabled) return;
+    queue.enqueue(this);
+    _renderingScheduled = true;
+  }
+
+  /// Renders the element (if the scheduler is enabled).
+  /// It will clear the dirty flag.
+  void render() {
+    if (!_enabled) return;
+    _dirty = false;
+    element.render();
+    _renderingScheduled = false;
+    scheduleNotification();
+    if (_dirty) scheduleRendering();
+  }
+
+  /// Schedules a notification.
+  void scheduleNotification() {
+    if (_notificationScheduled) return;
+    _notify();
+    _notificationScheduled = true;
+  }
+
+  Future _notify() async {
+    _onRendered.add(new RenderedEvent<T>(element, _dirty));
+    _notificationScheduled = false;
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/helpers/tag.dart b/runtime/observatory/lib/src/elements/helpers/tag.dart
new file mode 100644
index 0000000..177e238
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/helpers/tag.dart
@@ -0,0 +1,36 @@
+// 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 'dart:html';
+
+/// Utility class for Custom Tags registration.
+class Tag<T extends HtmlElement> {
+  /// Tag name.
+  final String name;
+  /// Dependend tags that need to be registred for this tag to work properly.
+  final Iterable<Tag> dependencies;
+
+  const Tag(this.name, {this.dependencies : const []});
+
+  static final Map<Type, String> _tagByClass = <Type, String>{};
+  static final Map<String, Type> _classByTag = <String, Type>{};
+
+  /// Ensures that the Tag and all the dependencies are registered.
+  void ensureRegistration() {
+    if (!_tagByClass.containsKey(T) && !_classByTag.containsKey(name)) {
+      document.registerElement(name, T);
+      _tagByClass[T] = name;
+      _classByTag[name] = T;
+      dependencies.forEach((tag) => tag.ensureRegistration());
+    }
+    var tag = _tagByClass[T];
+    if (tag != name) {
+      throw new ArgumentError('Class $T is already registered to tag ${tag}');
+    }
+    var c = _classByTag[name];
+    if (c != T) {
+      throw new ArgumentError('Tag $name is already registered by class ${c}');
+    }
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/helpers/uris.dart b/runtime/observatory/lib/src/elements/helpers/uris.dart
new file mode 100644
index 0000000..1c9660c
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/helpers/uris.dart
@@ -0,0 +1,42 @@
+// 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:observatory/models.dart' as M;
+
+/// Utility class for URIs generation.
+abstract class Uris {
+  static String _isolatePage(String path, M.IsolateRef isolate,
+      {M.ObjectRef object}) {
+    final parameters = { 'isolateId': isolate.id };
+    if (object != null) parameters['objectId'] = object.id;
+    return '#' + new Uri(path: path, queryParameters: parameters).toString();
+  }
+
+  static String inspect(M.IsolateRef isolate, {M.ObjectRef object})
+      => _isolatePage('/inspect', isolate, object: object);
+  static String debugger(M.IsolateRef isolate)
+      => _isolatePage('/debugger', isolate);
+  static String classTree(M.IsolateRef isolate)
+      => _isolatePage('/class-tree', isolate);
+  static String cpuProfiler(M.IsolateRef isolate)
+      => _isolatePage('/profiler', isolate);
+  static String cpuProfilerTable(M.IsolateRef isolate)
+      => _isolatePage('/profiler-table', isolate);
+  static String allocationProfiler(M.IsolateRef isolate)
+      => _isolatePage('/allocation-profiler', isolate);
+  static String heapMap(M.IsolateRef isolate)
+      => _isolatePage('/heap-map', isolate);
+  static String metrics(M.IsolateRef isolate)
+      => _isolatePage('/metrics', isolate);
+  static String heapSnapshot(M.IsolateRef isolate)
+      => _isolatePage('/heap-snapshot', isolate);
+  static String persistentHandles(M.IsolateRef isolate)
+      => _isolatePage('/persistent-handles', isolate);
+  static String ports(M.IsolateRef isolate)
+      => _isolatePage('/ports', isolate);
+  static String logging(M.IsolateRef isolate)
+      => _isolatePage('/logging', isolate);
+  static String vm() => '#/vm';
+  static String vmConnect() => '#/vm-connect';
+}
diff --git a/runtime/observatory/lib/src/elements/icdata_view.html b/runtime/observatory/lib/src/elements/icdata_view.html
index d31f14f..9a5cf7b 100644
--- a/runtime/observatory/lib/src/elements/icdata_view.html
+++ b/runtime/observatory/lib/src/elements/icdata_view.html
@@ -5,12 +5,10 @@
 <link rel="import" href="function_ref.html">
 <link rel="import" href="inbound_reference.html">
 <link rel="import" href="instance_ref.html">
-<link rel="import" href="observatory_element.html">
 <link rel="import" href="object_common.html">
-<link rel="import" href="nav_bar.html">
 <link rel="import" href="eval_link.html">
 
-<polymer-element name="icdata-view" extends="observatory-element">
+<polymer-element name="icdata-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <nav-bar>
@@ -19,6 +17,7 @@
       <isolate-nav-menu isolate="{{ icData.isolate }}"></isolate-nav-menu>
       <nav-menu link="." anchor="object" last="{{ true }}"></nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content">
@@ -29,7 +28,7 @@
       <div class="memberList">
         <div class="memberItem">
           <div class="memberName">selector</div>
-          <div class="memberValue"> 
+          <div class="memberValue">
             {{ icData.selector }}
           </div>
         </div>
@@ -54,7 +53,7 @@
       </div>
 
     </div>
-  
+
     <hr>
     <view-footer></view-footer>
   </template>
diff --git a/runtime/observatory/lib/src/elements/inbound_reference.html b/runtime/observatory/lib/src/elements/inbound_reference.html
index 4ca13c3..cfda665 100644
--- a/runtime/observatory/lib/src/elements/inbound_reference.html
+++ b/runtime/observatory/lib/src/elements/inbound_reference.html
@@ -1,10 +1,9 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="curly_block.html">
 <link rel="import" href="field_ref.html">
-<link rel="import" href="observatory_element.html">
+
 <link rel="import" href="service_ref.html">
 
-<polymer-element name="inbound-reference" extends="service-ref">
+<polymer-element name="inbound-reference">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <div>
diff --git a/runtime/observatory/lib/src/elements/instance_ref.html b/runtime/observatory/lib/src/elements/instance_ref.html
index 311732b..dffa36c 100644
--- a/runtime/observatory/lib/src/elements/instance_ref.html
+++ b/runtime/observatory/lib/src/elements/instance_ref.html
@@ -1,9 +1,8 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="curly_block.html">
-<link rel="import" href="observatory_element.html">
+
 <link rel="import" href="service_ref.html">
 
-<polymer-element name="instance-ref" extends="service-ref">
+<polymer-element name="instance-ref">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
diff --git a/runtime/observatory/lib/src/elements/instance_view.html b/runtime/observatory/lib/src/elements/instance_view.html
index 5e98824..dd522e5 100644
--- a/runtime/observatory/lib/src/elements/instance_view.html
+++ b/runtime/observatory/lib/src/elements/instance_view.html
@@ -7,13 +7,10 @@
 <link rel="import" href="function_ref.html">
 <link rel="import" href="inbound_reference.html">
 <link rel="import" href="instance_ref.html">
-<link rel="import" href="observatory_element.html">
-<link rel="import" href="nav_bar.html">
 <link rel="import" href="object_common.html">
 <link rel="import" href="context_ref.html">
-<link rel="import" href="view_footer.html">
 
-<polymer-element name="instance-view" extends="observatory-element">
+<polymer-element name="instance-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <nav-bar>
@@ -24,6 +21,7 @@
       <class-nav-menu cls="{{ instance.clazz }}"></class-nav-menu>
       <nav-menu link="." anchor="instance" last="{{ true }}"></nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <template if="{{ instance.isError }}">
diff --git a/runtime/observatory/lib/src/elements/instructions_view.html b/runtime/observatory/lib/src/elements/instructions_view.html
index feb108c..07c5343 100644
--- a/runtime/observatory/lib/src/elements/instructions_view.html
+++ b/runtime/observatory/lib/src/elements/instructions_view.html
@@ -5,12 +5,10 @@
 <link rel="import" href="function_ref.html">
 <link rel="import" href="inbound_reference.html">
 <link rel="import" href="instance_ref.html">
-<link rel="import" href="observatory_element.html">
 <link rel="import" href="object_common.html">
-<link rel="import" href="nav_bar.html">
 <link rel="import" href="eval_link.html">
 
-<polymer-element name="instructions-view" extends="observatory-element">
+<polymer-element name="instructions-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <nav-bar>
@@ -19,6 +17,7 @@
       <isolate-nav-menu isolate="{{ instructions.isolate }}"></isolate-nav-menu>
       <nav-menu link="." anchor="object" last="{{ true }}"></nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content">
@@ -42,7 +41,7 @@
       </div>
 
     </div>
-  
+
     <hr>
     <view-footer></view-footer>
   </template>
diff --git a/runtime/observatory/lib/src/elements/io_view.html b/runtime/observatory/lib/src/elements/io_view.html
index fcc8399..c858e15 100644
--- a/runtime/observatory/lib/src/elements/io_view.html
+++ b/runtime/observatory/lib/src/elements/io_view.html
@@ -1,15 +1,14 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="nav_bar.html">
-<link rel="import" href="observatory_element.html">
 <link rel="import" href="service_ref.html">
 
-<polymer-element name="io-view" extends="observatory-element">
+<polymer-element name="io-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
 
     <nav-bar>
       <top-nav-menu last="{{ true }}"></top-nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content">
@@ -61,7 +60,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="io-ref" extends="service-ref">
+<polymer-element name="io-ref">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <template if="{{ ref.type == 'Socket' }}">
@@ -82,13 +81,14 @@
   </template>
 </polymer-element>
 
-<polymer-element name="io-http-server-list-view" extends="observatory-element">
+<polymer-element name="io-http-server-list-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
 
     <nav-bar>
       <top-nav-menu last="{{ true }}"></top-nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content">
@@ -109,20 +109,21 @@
   </template>
 </polymer-element>
 
-<polymer-element name="io-http-server-ref" extends="service-ref">
+<polymer-element name="io-http-server-ref">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <a on-click="{{ goto }}" _href="{{ url }}">{{ name }}</a>
   </template>
 </polymer-element>
 
-<polymer-element name="io-http-server-view" extends="observatory-element">
+<polymer-element name="io-http-server-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
 
     <nav-bar>
       <top-nav-menu last="{{ true }}"></top-nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content">
@@ -170,20 +171,21 @@
   </template>
 </polymer-element>
 
-<polymer-element name="io-http-server-connection-ref" extends="service-ref">
+<polymer-element name="io-http-server-connection-ref">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <a _href="{{ url }}">{{ name }}</a>
   </template>
 </polymer-element>
 
-<polymer-element name="io-http-server-connection-view" extends="observatory-element">
+<polymer-element name="io-http-server-connection-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
 
     <nav-bar>
       <top-nav-menu last="{{ true }}"></top-nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content">
@@ -211,20 +213,21 @@
   </template>
 </polymer-element>
 
-<polymer-element name="io-socket-ref" extends="service-ref">
+<polymer-element name="io-socket-ref">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <a on-click="{{ goto }}" _href="{{ url }}">{{ name }}</a>
   </template>
 </polymer-element>
 
-<polymer-element name="io-socket-list-view" extends="observatory-element">
+<polymer-element name="io-socket-list-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
 
     <nav-bar>
       <top-nav-menu last="{{ true }}"></top-nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content">
@@ -245,7 +248,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="io-socket-view" extends="observatory-element">
+<polymer-element name="io-socket-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
 
@@ -341,20 +344,21 @@
   </template>
 </polymer-element>
 
-<polymer-element name="io-web-socket-ref" extends="service-ref">
+<polymer-element name="io-web-socket-ref">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <a on-click="{{ goto }}" _href="{{ url }}">{{ name }}</a>
   </template>
 </polymer-element>
 
-<polymer-element name="io-web-socket-list-view" extends="observatory-element">
+<polymer-element name="io-web-socket-list-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
 
     <nav-bar>
       <top-nav-menu last="{{ true }}"></top-nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content">
@@ -375,13 +379,14 @@
   </template>
 </polymer-element>
 
-<polymer-element name="io-web-socket-view" extends="observatory-element">
+<polymer-element name="io-web-socket-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
 
     <nav-bar>
       <top-nav-menu last="{{ true }}"></top-nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content">
@@ -401,20 +406,21 @@
   </template>
 </polymer-element>
 
-<polymer-element name="io-random-access-file-ref" extends="service-ref">
+<polymer-element name="io-random-access-file-ref">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <a on-click="{{ goto }}" _href="{{ url }}">{{ name }}</a>
   </template>
 </polymer-element>
 
-<polymer-element name="io-random-access-file-list-view" extends="observatory-element">
+<polymer-element name="io-random-access-file-list-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
 
     <nav-bar>
       <top-nav-menu last="{{ true }}"></top-nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content">
@@ -435,13 +441,14 @@
   </template>
 </polymer-element>
 
-<polymer-element name="io-random-access-file-view" extends="observatory-element">
+<polymer-element name="io-random-access-file-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
 
     <nav-bar>
       <top-nav-menu last="{{ true }}"></top-nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content">
@@ -469,13 +476,14 @@
   </template>
 </polymer-element>
 
-<polymer-element name="io-process-list-view" extends="observatory-element">
+<polymer-element name="io-process-list-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
 
     <nav-bar>
       <top-nav-menu last="{{ true }}"></top-nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content">
@@ -496,7 +504,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="io-process-ref" extends="service-ref">
+<polymer-element name="io-process-ref">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <template if="{{ small }}">
@@ -508,13 +516,14 @@
   </template>
 </polymer-element>
 
-<polymer-element name="io-process-view" extends="observatory-element">
+<polymer-element name="io-process-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
 
     <nav-bar>
       <top-nav-menu last="{{ true }}"></top-nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content">
diff --git a/runtime/observatory/lib/src/elements/isolate_reconnect.html b/runtime/observatory/lib/src/elements/isolate_reconnect.html
index 9674038..1f678f5 100644
--- a/runtime/observatory/lib/src/elements/isolate_reconnect.html
+++ b/runtime/observatory/lib/src/elements/isolate_reconnect.html
@@ -1,8 +1,6 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="nav_bar.html">
-<link rel="import" href="observatory_element.html">
 
-<polymer-element name="isolate-reconnect" extends="observatory-element">
+<polymer-element name="isolate-reconnect">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
@@ -13,6 +11,7 @@
 
     <nav-bar>
       <top-nav-menu last="{{ true }}"></top-nav-menu>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content-centered">
diff --git a/runtime/observatory/lib/src/elements/isolate_ref.dart b/runtime/observatory/lib/src/elements/isolate_ref.dart
index 730a438..f27c8fb 100644
--- a/runtime/observatory/lib/src/elements/isolate_ref.dart
+++ b/runtime/observatory/lib/src/elements/isolate_ref.dart
@@ -4,10 +4,65 @@
 
 library isolate_ref_element;
 
-import 'package:polymer/polymer.dart';
-import 'service_ref.dart';
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory/models.dart' as M
+  show IsolateRef, IsolateUpdateEvent;
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
 
-@CustomTag('isolate-ref')
-class IsolateRefElement extends ServiceRefElement {
+class IsolateRefElement extends HtmlElement implements Renderable {
+  static const tag = const Tag<IsolateRefElement>('isolate-ref-wrapped');
+
+  RenderingScheduler<IsolateRefElement> _r;
+
+  Stream<RenderedEvent<IsolateRefElement>> get onRendered => _r.onRendered;
+
+  Stream<M.IsolateUpdateEvent> _updates;
+  StreamSubscription _updatesSubscription;
+  M.IsolateRef _isolate;
+
+  M.IsolateRef get isolate => _isolate;
+
+  factory IsolateRefElement(M.IsolateRef isolate,
+      Stream<M.IsolateUpdateEvent> updates, {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(updates != null);
+    IsolateRefElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._isolate = isolate;
+    e._updates = updates;
+    return e;
+  }
+
   IsolateRefElement.created() : super.created();
+
+  @override
+  void attached() {
+    super.attached();
+    assert(_isolate != null);
+    assert(_updates != null);
+    _r.enable();
+    _updatesSubscription = _updates
+      .where((M.IsolateUpdateEvent e) => e.isolate.id == isolate.id)
+      .listen((M.IsolateUpdateEvent e) { _isolate = e.isolate; _r.dirty(); });
+  }
+
+  @override
+  void detached() {
+    super.detached(); _r.disable(notify: true);
+    children = [];
+    assert(_updatesSubscription != null);
+    _updatesSubscription.cancel();
+    _updatesSubscription = null;
+  }
+
+  void render() {
+    children = [
+      new AnchorElement(href: Uris.inspect(isolate))
+        ..text = 'Isolate ${isolate.number} (${isolate.name})'
+        ..classes = ['isolate-ref']
+    ];
+  }
 }
diff --git a/runtime/observatory/lib/src/elements/isolate_ref.html b/runtime/observatory/lib/src/elements/isolate_ref.html
deleted file mode 100644
index edfb3ea..0000000
--- a/runtime/observatory/lib/src/elements/isolate_ref.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="service_ref.html">
-<polymer-element name="isolate-ref" extends="service-ref">
-<template><link rel="stylesheet" href="css/shared.css">
-  <a on-click="{{ goto }}" _href="{{ url }}">Isolate {{ ref.number }} ({{ ref.name }})</a>
-</template>
-</polymer-element>
-
-<script type="application/dart" src="isolate_ref.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/isolate_ref_wrapper.dart b/runtime/observatory/lib/src/elements/isolate_ref_wrapper.dart
new file mode 100644
index 0000000..dc78739
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/isolate_ref_wrapper.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+
+import 'package:observatory/app.dart';
+import 'package:observatory/models.dart' show IsolateUpdateEvent;
+import 'package:observatory/mocks.dart' show IsolateUpdateEventMock;
+import 'package:observatory/service_html.dart' show Isolate;
+import 'package:observatory/src/elements/isolate_ref.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/shims/binding.dart';
+
+class IsolateRefElementWrapper extends HtmlElement {
+
+  static final binder = new Binder<IsolateRefElementWrapper>(
+    const [const Binding('ref')]);
+
+  static const tag = const Tag<IsolateRefElementWrapper>('isolate-ref');
+
+  final StreamController<IsolateUpdateEvent> _updatesController =
+    new StreamController<IsolateUpdateEvent>();
+  Stream<IsolateUpdateEvent> _updates;
+  StreamSubscription _subscription;
+
+  Isolate _isolate;
+  Isolate get ref => _isolate;
+  void set ref(Isolate ref) { _isolate = ref; _detached(); _attached(); }
+
+  IsolateRefElementWrapper.created() : super.created() {
+    _updates = _updatesController.stream.asBroadcastStream();
+    binder.registerCallback(this);
+    createShadowRoot();
+    render();
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    _attached();
+  }
+
+  void _attached() {
+    if (ref != null) {
+      _subscription = ref.changes.listen((_) {
+        _updatesController.add(new IsolateUpdateEventMock(isolate: ref));
+      });
+    }
+    render();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _detached();
+  }
+
+  void _detached() {
+    if (_subscription != null) {
+      _subscription.cancel();
+      _subscription = null;
+    }
+  }
+
+  void render() {
+    shadowRoot.children = [];
+    if (ref == null) return;
+
+    shadowRoot.children = [
+      new StyleElement()
+        ..text = '@import "packages/observatory/src/elements/css/shared.css";',
+      new IsolateRefElement(_isolate, _updates,
+                                 queue: ObservatoryApplication.app.queue)
+    ];
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/isolate_summary.html b/runtime/observatory/lib/src/elements/isolate_summary.html
index c089da9..7b62b4d 100644
--- a/runtime/observatory/lib/src/elements/isolate_summary.html
+++ b/runtime/observatory/lib/src/elements/isolate_summary.html
@@ -1,11 +1,9 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="action_link.html">
 <link rel="import" href="function_ref.html">
-<link rel="import" href="isolate_ref.html">
-<link rel="import" href="observatory_element.html">
 <link rel="import" href="script_inset.html">
 <link rel="import" href="script_ref.html">
-<polymer-element name="isolate-summary" extends="observatory-element">
+<polymer-element name="isolate-summary">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <div class="flex-row">
@@ -24,7 +22,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="isolate-run-state" extends="observatory-element">
+<polymer-element name="isolate-run-state">
   <template>
     <template if="{{ isolate.paused }}">
       <strong title="{{ isolate.pauseEvent.timestamp.toString() }}">paused</strong>
@@ -44,7 +42,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="isolate-location" extends="observatory-element">
+<polymer-element name="isolate-location">
   <template>
     <template if="{{ isolate.pauseEvent != null }}">
       <template if="{{ isolate.pauseEvent.kind == 'PauseStart' }}">
@@ -88,7 +86,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="isolate-shared-summary" extends="observatory-element">
+<polymer-element name="isolate-shared-summary">
   <template>
     <style>
       .errorBox {
@@ -201,7 +199,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="isolate-counter-chart" extends="observatory-element">
+<polymer-element name="isolate-counter-chart">
   <template>
     <link rel="stylesheet" href="../../../../packages/charted/charts/themes/quantum_theme.css">
     <style>
diff --git a/runtime/observatory/lib/src/elements/isolate_view.html b/runtime/observatory/lib/src/elements/isolate_view.html
index e7777a7..a414e3f 100644
--- a/runtime/observatory/lib/src/elements/isolate_view.html
+++ b/runtime/observatory/lib/src/elements/isolate_view.html
@@ -1,17 +1,13 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="action_link.html">
-<link rel="import" href="curly_block.html">
 <link rel="import" href="eval_box.html">
 <link rel="import" href="function_ref.html">
 <link rel="import" href="isolate_summary.html">
 <link rel="import" href="library_ref.html">
-<link rel="import" href="nav_bar.html">
-<link rel="import" href="observatory_element.html">
 <link rel="import" href="script_inset.html">
 <link rel="import" href="script_ref.html">
-<link rel="import" href="view_footer.html">
 
-<polymer-element name="isolate-view" extends="observatory-element">
+<polymer-element name="isolate-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
@@ -29,6 +25,7 @@
       <vm-nav-menu vm="{{ isolate.vm }}"></vm-nav-menu>
       <isolate-nav-menu isolate="{{ isolate }}" last="{{ true }}"></isolate-nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content-centered">
diff --git a/runtime/observatory/lib/src/elements/json_view.html b/runtime/observatory/lib/src/elements/json_view.html
index 4ef479b..ea4b63f 100644
--- a/runtime/observatory/lib/src/elements/json_view.html
+++ b/runtime/observatory/lib/src/elements/json_view.html
@@ -1,10 +1,10 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="nav_bar.html">
-<link rel="import" href="observatory_element.html">
-<polymer-element name="json-view" extends="observatory-element">
+
+<polymer-element name="json-view">
   <template>
     <nav-bar>
       <top-nav-menu last="{{ true }}"></top-nav-menu>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
       <pre>{{ mapAsString }}</pre>
   </template>
diff --git a/runtime/observatory/lib/src/elements/library_ref.html b/runtime/observatory/lib/src/elements/library_ref.html
index a4313c1..6e8c7a0 100644
--- a/runtime/observatory/lib/src/elements/library_ref.html
+++ b/runtime/observatory/lib/src/elements/library_ref.html
@@ -1,9 +1,8 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="curly_block.html">
-<link rel="import" href="observatory_element.html">
+
 <link rel="import" href="service_ref.html">
 
-<polymer-element name="library-ref" extends="service-ref">
+<polymer-element name="library-ref">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
diff --git a/runtime/observatory/lib/src/elements/library_view.html b/runtime/observatory/lib/src/elements/library_view.html
index 51d2da8..97417fa 100644
--- a/runtime/observatory/lib/src/elements/library_view.html
+++ b/runtime/observatory/lib/src/elements/library_view.html
@@ -1,17 +1,13 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="class_ref.html">
-<link rel="import" href="curly_block.html">
 <link rel="import" href="eval_box.html">
 <link rel="import" href="field_ref.html">
 <link rel="import" href="function_ref.html">
 <link rel="import" href="instance_ref.html">
-<link rel="import" href="observatory_element.html">
 <link rel="import" href="library_ref.html">
-<link rel="import" href="nav_bar.html">
 <link rel="import" href="script_ref.html">
-<link rel="import" href="view_footer.html">
 
-<polymer-element name="library-view" extends="observatory-element">
+<polymer-element name="library-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
 
@@ -21,6 +17,7 @@
       <isolate-nav-menu isolate="{{ library.isolate }}"></isolate-nav-menu>
       <library-nav-menu library="{{ library }}" last="{{ true }}"></library-nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content">
diff --git a/runtime/observatory/lib/src/elements/logging.html b/runtime/observatory/lib/src/elements/logging.html
index a3a36a1..0360c82bf 100644
--- a/runtime/observatory/lib/src/elements/logging.html
+++ b/runtime/observatory/lib/src/elements/logging.html
@@ -1,12 +1,8 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="code_ref.html">
 <link rel="import" href="function_ref.html">
-<link rel="import" href="nav_bar.html">
-<link rel="import" href="observatory_element.html">
-<link rel="import" href="sliding_checkbox.html">
-<link rel="import" href="view_footer.html">
 
-<polymer-element name="logging-page" extends="observatory-element">
+<polymer-element name="logging-page">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
@@ -63,6 +59,7 @@
       <isolate-nav-menu isolate="{{ isolate }}"></isolate-nav-menu>
       <nav-menu link="{{ makeLink('/logging', isolate) }}" anchor="logging" last="{{ true }}"></nav-menu>
       <nav-refresh callback="{{ clear }}" label="Clear"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
     <div id="page" class="content-centered-big">
       <span>Show messages with severity <select id="severityLevelSelector" value="{{ severityLevel }}"></select> and higher</span>
diff --git a/runtime/observatory/lib/src/elements/megamorphiccache_view.html b/runtime/observatory/lib/src/elements/megamorphiccache_view.html
index 0454e0d..720dc29 100644
--- a/runtime/observatory/lib/src/elements/megamorphiccache_view.html
+++ b/runtime/observatory/lib/src/elements/megamorphiccache_view.html
@@ -5,12 +5,10 @@
 <link rel="import" href="function_ref.html">
 <link rel="import" href="inbound_reference.html">
 <link rel="import" href="instance_ref.html">
-<link rel="import" href="observatory_element.html">
 <link rel="import" href="object_common.html">
-<link rel="import" href="nav_bar.html">
 <link rel="import" href="eval_link.html">
 
-<polymer-element name="megamorphiccache-view" extends="observatory-element">
+<polymer-element name="megamorphiccache-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <nav-bar>
@@ -19,6 +17,7 @@
       <isolate-nav-menu isolate="{{ megamorphicCache.isolate }}"></isolate-nav-menu>
       <nav-menu link="." anchor="object" last="{{ true }}"></nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content">
@@ -41,7 +40,7 @@
         </div>
         <div class="memberItem">
           <div class="memberName">mask</div>
-          <div class="memberValue"> 
+          <div class="memberValue">
             {{ megamorphicCache.mask }}
           </div>
         </div>
@@ -54,7 +53,7 @@
       </div>
 
     </div>
-  
+
     <hr>
     <view-footer></view-footer>
   </template>
diff --git a/runtime/observatory/lib/src/elements/metrics.html b/runtime/observatory/lib/src/elements/metrics.html
index a6a0411..a82cea0 100644
--- a/runtime/observatory/lib/src/elements/metrics.html
+++ b/runtime/observatory/lib/src/elements/metrics.html
@@ -1,8 +1,6 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="nav_bar.html">
-<link rel="import" href="observatory_element.html">
 
-<polymer-element name="metrics-page" extends="observatory-element">
+<polymer-element name="metrics-page">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
@@ -23,6 +21,7 @@
       <nav-menu link="{{ makeLink('/metrics', isolate) }}" anchor="metrics" last="{{ true }}"></nav-menu>
 
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
     <div class="flex-row">
       <div class="flex-item-20-percent">
@@ -65,7 +64,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="metric-details" extends="observatory-element">
+<polymer-element name="metric-details">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <div class="content-centered">
@@ -124,7 +123,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="metrics-graph" extends="observatory-element">
+<polymer-element name="metrics-graph">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <link rel="stylesheet" href="../../../../packages/charted/charts/themes/quantum_theme.css">
diff --git a/runtime/observatory/lib/src/elements/nav/bar.dart b/runtime/observatory/lib/src/elements/nav/bar.dart
new file mode 100644
index 0000000..8bb115e
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/nav/bar.dart
@@ -0,0 +1,83 @@
+// 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 'dart:html';
+import 'dart:async';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+
+class NavBarElement extends HtmlElement implements Renderable {
+  static final StyleElement _style = () {
+      var style = new StyleElement();
+      style.text = 'nav.nav-bar {'
+                     'position: fixed;'
+                     'top: -56px;'
+                     'width: 100%;'
+                     'z-index: 1000;'
+                     '}'
+                   'nav.nav-bar > ul {'
+                     'display: inline-table;'
+                     'position: relative;'
+                     'list-style: none;'
+                     'padding-left: 0;'
+                     'margin-left: 0;'
+                     'width: 100%;'
+                     'z-index: 1000;'
+                     'font: 400 16px \'Montserrat\', sans-serif;'
+                     'color: white;'
+                     'background-color: #0489c3;'
+                   '}'
+                   'nav.nav-bar:after {'
+                     'content: ""; clear: both; display: block;'
+                   '}'
+                   'nav.nav-bar:before {'
+                     'height: 40px;'
+                     'background-color: #0489c3;'
+                     'content: ""; display: block;'
+                   '}';
+      return style;
+  }();
+
+  static const tag = const Tag<NavBarElement>('nav-bar');
+
+  RenderingScheduler _r;
+
+  Stream<RenderedEvent<NavBarElement>> get onRendered => _r.onRendered;
+
+  factory NavBarElement({RenderingQueue queue}) {
+    NavBarElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    return e;
+  }
+
+  NavBarElement.created() : super.created() {
+    // TODO(cbernaschina) remove when no more needed.
+    _r = new RenderingScheduler(this);
+    createShadowRoot();
+  }
+
+  @override
+  void attached() { super.attached(); _r.enable(); }
+
+  @override
+  void detached() {
+    super.detached(); _r.disable(notify: true);
+    shadowRoot.children = [];
+  }
+
+  void render() {
+    shadowRoot.children = [
+      _style.clone(true),
+      document.createElement('nav')
+        ..classes = ['nav-bar']
+        ..children = [
+          new UListElement()
+            ..children = [
+              new ContentElement()
+            ],
+        ],
+      new DivElement()
+    ];
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/nav/class_menu.dart b/runtime/observatory/lib/src/elements/nav/class_menu.dart
new file mode 100644
index 0000000..d8ed510
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/nav/class_menu.dart
@@ -0,0 +1,64 @@
+// 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 'dart:html';
+import 'dart:async';
+import 'package:observatory/models.dart' as M show IsolateRef, ClassRef;
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
+import 'package:observatory/src/elements/nav/menu.dart';
+
+class NavClassMenuElement extends HtmlElement implements Renderable {
+  static const tag = const Tag<NavClassMenuElement>('nav-class-menu',
+                     dependencies: const [NavMenuElement.tag]);
+
+  RenderingScheduler _r;
+
+  Stream<RenderedEvent<NavClassMenuElement>> get onRendered => _r.onRendered;
+
+  bool _last;
+  M.IsolateRef _isolate;
+  M.ClassRef _cls;
+  bool get last => _last;
+  M.IsolateRef get isolate => _isolate;
+  M.ClassRef get cls => _cls;
+  set last(bool value) => _last = _r.checkAndReact(_last, value);
+
+  factory NavClassMenuElement(M.IsolateRef isolate, M.ClassRef cls,
+      {bool last: false, RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(cls != null);
+    assert(last != null);
+    NavClassMenuElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._isolate = isolate;
+    e._cls = cls;
+    e._last = last;
+    return e;
+  }
+
+  NavClassMenuElement.created() : super.created() { createShadowRoot(); }
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    shadowRoot.children = [];
+  }
+
+  void render() {
+    shadowRoot.children = [
+      new NavMenuElement(cls.name, last: last, queue: _r.queue,
+          link: Uris.inspect(isolate, object: cls))
+        ..children = [new ContentElement()]
+    ];
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/nav/class_menu_wrapper.dart b/runtime/observatory/lib/src/elements/nav/class_menu_wrapper.dart
new file mode 100644
index 0000000..d1e56ac
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/nav/class_menu_wrapper.dart
@@ -0,0 +1,59 @@
+// 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 'dart:html';
+
+import 'package:observatory/app.dart';
+import 'package:observatory/service.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/shims/binding.dart';
+import 'package:observatory/src/elements/nav/class_menu.dart';
+
+class NavClassMenuElementWrapper extends HtmlElement {
+  static final binder = new Binder<NavClassMenuElementWrapper>(
+    const [const Binding('last'), const Binding('cls')]);
+
+  static const tag =
+    const Tag<NavClassMenuElementWrapper>('class-nav-menu');
+
+  bool _last = false;
+  Class _cls;
+  bool get last => _last;
+  Class get cls => _cls;
+  set last(bool value) {
+    _last = value; render();
+  }
+  set cls(Class value) {
+    _cls = value; render();
+  }
+
+  NavClassMenuElementWrapper.created() : super.created() {
+    binder.registerCallback(this);
+    _last = _getBoolAttribute('last');
+    createShadowRoot();
+    render();
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    render();
+  }
+
+  void render() {
+    shadowRoot.children = [];
+    if (_cls == null || _last == null) return;
+
+    shadowRoot.children = [
+      new NavClassMenuElement(cls.isolate, cls, last: last,
+                                 queue: ObservatoryApplication.app.queue)
+        ..children = [new ContentElement()]
+    ];
+  }
+
+  bool _getBoolAttribute(String name) {
+    final String value = getAttribute(name);
+    return !(value == null || value == 'false');
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/nav/isolate_menu.dart b/runtime/observatory/lib/src/elements/nav/isolate_menu.dart
new file mode 100644
index 0000000..3f0089a
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/nav/isolate_menu.dart
@@ -0,0 +1,103 @@
+// 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 'dart:html';
+import 'dart:async';
+import 'package:observatory/models.dart' as M
+  show IsolateRef, IsolateUpdateEvent;
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
+import 'package:observatory/src/elements/nav/menu.dart';
+import 'package:observatory/src/elements/nav/menu_item.dart';
+
+class NavIsolateMenuElement extends HtmlElement implements Renderable {
+  static const tag = const Tag<NavIsolateMenuElement>('nav-isolate-menu',
+                     dependencies: const [NavMenuElement.tag,
+                                          NavMenuItemElement.tag]);
+
+  RenderingScheduler _r;
+
+  Stream<RenderedEvent<NavIsolateMenuElement>> get onRendered => _r.onRendered;
+
+  Stream<M.IsolateUpdateEvent> _updates;
+  StreamSubscription _updatesSubscription;
+
+  bool _last;
+  M.IsolateRef _isolate;
+  bool get last => _last;
+  M.IsolateRef get isolate => _isolate;
+  set last(bool value) => _last = _r.checkAndReact(_last, value);
+
+  factory NavIsolateMenuElement(M.IsolateRef isolate,
+      Stream<M.IsolateUpdateEvent> updates, {bool last: false,
+      RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(last != null);
+    NavIsolateMenuElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._isolate = isolate;
+    e._last = last;
+    e._updates = updates;
+    return e;
+  }
+
+  NavIsolateMenuElement.created() : super.created() {
+    _r = new RenderingScheduler(this);
+    createShadowRoot();
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    assert(_isolate != null);
+    assert(_updates != null);
+    _r.enable();
+    _updatesSubscription = _updates
+      .where((M.IsolateUpdateEvent e) => e.isolate.id == isolate.id)
+      .listen((M.IsolateUpdateEvent e) { _isolate = e.isolate; _r.dirty(); });
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    shadowRoot.children = [];
+    assert(_updatesSubscription != null);
+    _updatesSubscription.cancel();
+    _updatesSubscription = null;
+  }
+
+  void render() {
+    shadowRoot.children = [
+      new NavMenuElement(isolate.name, last: last, queue: _r.queue,
+          link: Uris.inspect(isolate))
+        ..children = [
+          new NavMenuItemElement('debugger', queue: _r.queue,
+              link: Uris.debugger(isolate)),
+          new NavMenuItemElement('class hierarchy', queue: _r.queue,
+              link: Uris.classTree(isolate)),
+          new NavMenuItemElement('cpu profile', queue: _r.queue,
+              link: Uris.cpuProfiler(isolate)),
+          new NavMenuItemElement('cpu profile (table)', queue: _r.queue,
+              link: Uris.cpuProfilerTable(isolate)),
+          new NavMenuItemElement('allocation profile', queue: _r.queue,
+              link: Uris.allocationProfiler(isolate)),
+          new NavMenuItemElement('heap map', queue: _r.queue,
+              link: Uris.heapMap(isolate)),
+          new NavMenuItemElement('metrics', queue: _r.queue,
+              link: Uris.metrics(isolate)),
+          new NavMenuItemElement('heap snapshot', queue: _r.queue,
+              link: Uris.heapSnapshot(isolate)),
+          new NavMenuItemElement('persistent handles', queue: _r.queue,
+              link: Uris.persistentHandles(isolate)),
+          new NavMenuItemElement('ports', queue: _r.queue,
+              link: Uris.ports(isolate)),
+          new NavMenuItemElement('logging', queue: _r.queue,
+              link: Uris.logging(isolate)),
+          new ContentElement()
+        ]
+    ];
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/nav/isolate_menu_wrapper.dart b/runtime/observatory/lib/src/elements/nav/isolate_menu_wrapper.dart
new file mode 100644
index 0000000..c2cf8f3
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/nav/isolate_menu_wrapper.dart
@@ -0,0 +1,90 @@
+// 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 'dart:html';
+import 'dart:async';
+
+import 'package:observatory/app.dart';
+import 'package:observatory/service.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/shims/binding.dart';
+import 'package:observatory/src/elements/nav/isolate_menu.dart';
+
+class NavIsolateMenuElementWrapper extends HtmlElement {
+  static final binder = new Binder<NavIsolateMenuElementWrapper>(
+    const [const Binding('last'), const Binding('isolate')]);
+
+  static const tag =
+    const Tag<NavIsolateMenuElementWrapper>('isolate-nav-menu');
+
+  final StreamController<M.IsolateUpdateEvent> _updatesController =
+    new StreamController<M.IsolateUpdateEvent>();
+  Stream<M.IsolateUpdateEvent> _updates;
+  StreamSubscription _subscription;
+
+  bool _last = false;
+  Isolate _isolate;
+  bool get last => _last;
+  Isolate get isolate => _isolate;
+  set last(bool value) {
+    _last = value; render();
+  }
+  set isolate(Isolate value) {
+    _isolate = value;  _detached(); _attached();
+  }
+
+  NavIsolateMenuElementWrapper.created() : super.created() {
+    _updates = _updatesController.stream.asBroadcastStream();
+    binder.registerCallback(this);
+    _last = _getBoolAttribute('last');
+    createShadowRoot();
+    render();
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    _attached();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _detached();
+  }
+
+  void _attached() {
+    if (_isolate != null) {
+      _subscription = _isolate.changes.listen((_) {
+        _updatesController.add(new IsolateUpdateEventMock(isolate: isolate));
+      });
+    }
+    render();
+  }
+
+  void _detached() {
+    if (_subscription != null) {
+      _subscription.cancel();
+      _subscription = null;
+    }
+  }
+
+  void render() {
+    shadowRoot.children = [];
+    if (_isolate == null || _last == null) return;
+
+    shadowRoot.children = [
+      new NavIsolateMenuElement(isolate, _updates, last: last,
+                                 queue: ObservatoryApplication.app.queue)
+        ..children = [new ContentElement()]
+    ];
+  }
+
+  bool _getBoolAttribute(String name) {
+    final String value = getAttribute(name);
+    return !(value == null || value == 'false');
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/nav/library_menu.dart b/runtime/observatory/lib/src/elements/nav/library_menu.dart
new file mode 100644
index 0000000..0403ac3
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/nav/library_menu.dart
@@ -0,0 +1,60 @@
+// 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 'dart:html';
+import 'dart:async';
+import 'package:observatory/models.dart' as M show IsolateRef, LibraryRef;
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
+import 'package:observatory/src/elements/nav/menu.dart';
+
+class NavLibraryMenuElement extends HtmlElement implements Renderable {
+  static const tag = const Tag<NavLibraryMenuElement>('nav-library-menu',
+                     dependencies: const [NavMenuElement.tag]);
+
+  RenderingScheduler _r;
+
+  Stream<RenderedEvent<NavLibraryMenuElement>> get onRendered => _r.onRendered;
+
+  bool _last;
+  M.IsolateRef _isolate;
+  M.LibraryRef _library;
+  bool get last => _last;
+  M.IsolateRef get isolate => _isolate;
+  M.LibraryRef get library => _library;
+  set last(bool value) => _last = _r.checkAndReact(_last, value);
+
+  factory NavLibraryMenuElement(M.IsolateRef isolate, M.LibraryRef library,
+      {bool last: false, RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(library != null);
+    assert(last != null);
+    NavLibraryMenuElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._isolate = isolate;
+    e._library = library;
+    e._last = last;
+    return e;
+  }
+
+  NavLibraryMenuElement.created() : super.created() { createShadowRoot(); }
+
+  @override
+  void attached() { super.attached(); _r.enable(); }
+
+  @override
+  void detached() {
+    super.detached(); _r.disable(notify: true);
+    shadowRoot.children = [];
+  }
+
+  void render() {
+    shadowRoot.children = [
+      new NavMenuElement(library.name, last: last, queue: _r.queue,
+                link: Uris.inspect(isolate, object: library).toString())
+        ..children = [new ContentElement()]
+    ];
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/nav/library_menu_wrapper.dart b/runtime/observatory/lib/src/elements/nav/library_menu_wrapper.dart
new file mode 100644
index 0000000..6e48155
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/nav/library_menu_wrapper.dart
@@ -0,0 +1,59 @@
+// 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 'dart:html';
+
+import 'package:observatory/app.dart';
+import 'package:observatory/service.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/shims/binding.dart';
+import 'package:observatory/src/elements/nav/library_menu.dart';
+
+class NavLibraryMenuElementWrapper extends HtmlElement {
+  static final binder = new Binder<NavLibraryMenuElementWrapper>(
+    const [const Binding('last'), const Binding('library')]);
+
+  static const tag =
+    const Tag<NavLibraryMenuElementWrapper>('library-nav-menu');
+
+  bool _last = false;
+  Library _library;
+  bool get last => _last;
+  Library get library => _library;
+  set last(bool value) {
+    _last = value; render();
+  }
+  set library(Library value) {
+    _library = value; render();
+  }
+
+  NavLibraryMenuElementWrapper.created() : super.created() {
+    binder.registerCallback(this);
+    _last = _getBoolAttribute('last');
+    createShadowRoot();
+    render();
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    render();
+  }
+
+  void render() {
+    shadowRoot.children = [];
+    if (_library == null || _last == null) return;
+
+    shadowRoot.children = [
+      new NavLibraryMenuElement(library.isolate, library, last: last,
+                                 queue: ObservatoryApplication.app.queue)
+        ..children = [new ContentElement()]
+    ];
+  }
+
+  bool _getBoolAttribute(String name) {
+    final String value = getAttribute(name);
+    return !(value == null || value == 'false');
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/nav/menu.dart b/runtime/observatory/lib/src/elements/nav/menu.dart
new file mode 100644
index 0000000..bcd9c90
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/nav/menu.dart
@@ -0,0 +1,109 @@
+// 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 'dart:html';
+import 'dart:async';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+
+class NavMenuElement extends HtmlElement implements Renderable {
+  static final StyleElement _style = () {
+      var style = new StyleElement();
+      style.text = '''li.nav-menu_label, li.nav-menu_spacer {
+                        float: left;
+                      }
+                      li.nav-menu_label > a, li.nav-menu_spacer {
+                        display: block;
+                        padding: 12px 8px;
+                        color: White;
+                        text-decoration: none;
+                      }
+                      li.nav-menu_label:hover {
+                        background: #455;
+                      }
+                      li.nav-menu_label > ul {
+                        display: none;
+                        position: absolute;
+                        top: 98%;
+                        list-style: none;
+                        margin: 0;
+                        padding: 0;
+                        width: auto;
+                        z-index: 1000;
+                        font: 400 16px \'Montserrat\', sans-serif;
+                        color: white;
+                        background: #567;
+                      }
+                      li.nav-menu_label > ul:after {
+                        content: ""; clear: both; display: block;
+                      }
+                      li.nav-menu_label:hover > ul {
+                        display: block;
+                      }''';
+      return style;
+  }();
+
+  static const tag = const Tag<NavMenuElement>('nav-menu-wrapped');
+
+  RenderingScheduler _r;
+
+  Stream<RenderedEvent<NavMenuElement>> get onRendered => _r.onRendered;
+
+  String _label;
+  String _link;
+  bool _last;
+  String get label => _label;
+  String get link => _link;
+  bool get last => _last;
+  set label(String value) => _label = _r.checkAndReact(_label, value);
+  set link(String value) => _link = _r.checkAndReact(_link, value);
+  set last(bool value) => _last = _r.checkAndReact(_link, value);
+
+  factory NavMenuElement(String label, {String link, bool last: false,
+                             RenderingQueue queue}) {
+    assert(label != null);
+    assert(last != null);
+    NavMenuElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._label = label;
+    e._link = link;
+    e._last = last;
+    return e;
+  }
+
+  NavMenuElement.created() : super.created() { createShadowRoot(); }
+
+  @override
+  void attached() { super.attached(); _r.enable(); }
+
+  @override
+  void detached() {
+    super.detached(); _r.disable(notify: true);
+    shadowRoot.children = [];
+  }
+
+  void render() {
+    List<Element> children = [
+      _style.clone(true),
+      new LIElement()
+        ..classes = ['nav-menu_label']
+        ..children = [
+          new AnchorElement(href: link)
+            ..text = label,
+          new UListElement()
+            ..children = [
+              new ContentElement()
+            ]
+        ]
+    ];
+    if (!last) {
+      children.add(
+        new LIElement()
+          ..classes = ['nav-menu_spacer']
+          ..innerHtml = '&gt;'
+      );
+    }
+    shadowRoot.children = children;
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/nav/menu_item.dart b/runtime/observatory/lib/src/elements/nav/menu_item.dart
new file mode 100644
index 0000000..2411ee5
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/nav/menu_item.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.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+
+class NavMenuItemElement extends HtmlElement implements Renderable {
+  static final StyleElement _style = () {
+      var style = new StyleElement();
+      style.text = '''li.nav-menu-item {
+                        float: none;
+                        border-top: 1px solid #677;
+                        border-bottom: 1px solid #556; position: relative;
+                      }
+                      li.nav-menu-item:hover {
+                        background: #455;
+                      }
+                      li.nav-menu-item > a {
+                        display: block;
+                        padding: 12px 12px;
+                        color: white;
+                        text-decoration: none;
+                      }
+                      li.nav-menu-item > ul {
+                        display: none;
+                        position: absolute;
+                        top:0;
+                        left: 100%;
+                        list-style: none;
+                        padding: 0;
+                        margin-left: 0;
+                        width: auto;
+                        z-index: 1000;
+                        font: 400 16px \'Montserrat\', sans-serif;
+                        color: white;
+                        background: #567;
+                      }
+                      li.nav-menu-item > ul:after {
+                        content: ""; clear: both; display: block;
+                      }
+                      li.nav-menu-item:hover > ul {
+                        display: block;
+                      }''';
+      return style;
+  }();
+
+  static const tag = const Tag<NavMenuItemElement>('nav-menu-item-wrapped');
+
+  RenderingScheduler _r;
+
+  Stream<RenderedEvent<NavMenuItemElement>> get onRendered => _r.onRendered;
+
+  String _label;
+  String _link;
+  String get label => _label;
+  String get link => _link;
+  set label(String value) => _label = _r.checkAndReact(_label, value);
+  set link(String value) => _link = _r.checkAndReact(_link, value);
+
+
+  factory NavMenuItemElement(String label, {String link,
+                             RenderingQueue queue}) {
+    assert(label != null);
+    NavMenuItemElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._label = label;
+    e._link = link;
+    return e;
+  }
+
+  NavMenuItemElement.created() : super.created() { createShadowRoot(); }
+
+  @override
+  void attached() { super.attached(); _r.enable(); }
+
+  @override
+  void detached() {
+    super.detached(); _r.disable(notify: true);
+    shadowRoot.children = [];
+  }
+
+  void render() {
+    shadowRoot.children = [
+      _style.clone(true),
+      new LIElement()
+        ..classes = ['nav-menu-item']
+        ..children = [
+          new AnchorElement(href: link)
+            ..text = label,
+          new UListElement()
+            ..children = [
+              new ContentElement()
+            ]
+        ]
+    ];
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/nav/menu_item_wrapper.dart b/runtime/observatory/lib/src/elements/nav/menu_item_wrapper.dart
new file mode 100644
index 0000000..045d67a
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/nav/menu_item_wrapper.dart
@@ -0,0 +1,54 @@
+// 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 'dart:html';
+
+import 'package:observatory/app.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/shims/binding.dart';
+import 'package:observatory/src/elements/nav/menu_item.dart';
+
+class NavMenuItemElementWrapper extends HtmlElement {
+  static final binder = new Binder<NavMenuItemElementWrapper>(
+    const [const Binding('anchor'), const Binding('link')]);
+
+  static const tag =
+    const Tag<NavMenuItemElementWrapper>('nav-menu-item');
+
+  String _anchor;
+  String _link;
+  String get anchor => _anchor;
+  String get link => _link;
+  set anchor(String value) {
+    _anchor = value; render();
+  }
+  set link(String value) {
+    _link = value; render();
+  }
+
+  NavMenuItemElementWrapper.created() : super.created() {
+    binder.registerCallback(this);
+    _anchor = getAttribute('anchor');
+    _link = getAttribute('link');
+    createShadowRoot();
+    render();
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    render();
+  }
+
+  void render() {
+    shadowRoot.children = [];
+    if (_anchor == null) return;
+
+    shadowRoot.children = [
+      new NavMenuItemElement(_anchor, link: '#$link',
+                                 queue: ObservatoryApplication.app.queue)
+        ..children = [new ContentElement()]
+    ];
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/nav/menu_wrapper.dart b/runtime/observatory/lib/src/elements/nav/menu_wrapper.dart
new file mode 100644
index 0000000..c237fed
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/nav/menu_wrapper.dart
@@ -0,0 +1,66 @@
+// 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 'dart:html';
+
+import 'package:observatory/app.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/shims/binding.dart';
+import 'package:observatory/src/elements/nav/menu.dart';
+
+class NavMenuElementWrapper extends HtmlElement {
+  static final binder = new Binder<NavMenuElementWrapper>(
+    const [const Binding('anchor'), const Binding('link'),
+           const Binding('last')]);
+
+  static const tag =
+    const Tag<NavMenuElementWrapper>('nav-menu');
+
+  String _anchor = '---';
+  String _link;
+  bool _last = false;
+  String get anchor => _anchor;
+  String get link => _link;
+  bool get last => _last;
+  set anchor(String value) {
+    _anchor = value; render();
+  }
+  set link(String value) {
+    _link = value; render();
+  }
+  set last(bool value) {
+    _last = value; render();
+  }
+
+  NavMenuElementWrapper.created() : super.created() {
+    binder.registerCallback(this);
+    _anchor = getAttribute('anchor');
+    _link = getAttribute('link');
+    _last = _getBoolAttribute('last');
+    createShadowRoot();
+    render();
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    render();
+  }
+
+  void render() {
+    shadowRoot.children = [];
+    if (_anchor == null || _last == null) return;
+
+    shadowRoot.children = [
+      new NavMenuElement(_anchor, link: '#$_link', last: last,
+                                 queue: ObservatoryApplication.app.queue)
+        ..children = [new ContentElement()]
+    ];
+  }
+
+  bool _getBoolAttribute(String name) {
+    final String value = getAttribute(name);
+    return !(value == null || value == 'false');
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/nav/notify.dart b/runtime/observatory/lib/src/elements/nav/notify.dart
new file mode 100644
index 0000000..ba99f01
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/nav/notify.dart
@@ -0,0 +1,90 @@
+// 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 'dart:html';
+import 'dart:async';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/nav/notify_event.dart';
+import 'package:observatory/src/elements/nav/notify_exception.dart';
+
+class NavNotifyElement extends HtmlElement implements Renderable {
+  static const tag = const Tag<NavNotifyElement>('nav-notify-wrapped',
+          dependencies: const [ NavNotifyEventElement.tag,
+                                NavNotifyExceptionElement.tag ]);
+
+  RenderingScheduler _r;
+
+  Stream<RenderedEvent<NavNotifyElement>> get onRendered => _r.onRendered;
+
+  M.NotificationRepository _repository;
+  StreamSubscription _subscription;
+
+  bool _notifyOnPause;
+  bool get notifyOnPause => _notifyOnPause;
+  set notifyOnPause(bool value) =>
+      _notifyOnPause = _r.checkAndReact(_notifyOnPause, value);
+
+  factory NavNotifyElement(M.NotificationRepository repository,
+                           {bool notifyOnPause: true, RenderingQueue queue}) {
+    assert(repository != null);
+    assert(notifyOnPause != null);
+    NavNotifyElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._repository = repository;
+    e._notifyOnPause = notifyOnPause;
+    return e;
+  }
+
+  NavNotifyElement.created() : super.created();
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+    _subscription = _repository.onChange.listen((_) => _r.dirty());
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = [];
+    _r.disable(notify: true);
+    _subscription.cancel();
+  }
+
+  void render() {
+    children = [
+      new DivElement()
+        ..children = [
+          new DivElement()
+            ..children = _repository.list()
+              .where(_filter).map(_toElement).toList()
+        ]
+    ];
+  }
+
+  bool _filter(M.Notification notification) {
+    if (!_notifyOnPause && notification is M.EventNotification) {
+      return !M.Event.isPauseEvent(notification.event);
+    }
+    return true;
+  }
+
+  HtmlElement _toElement(M.Notification notification) {
+    if (notification is M.EventNotification) {
+      return new NavNotifyEventElement(notification.event, queue: _r.queue)
+          ..onDelete.listen((_) => _repository.delete(notification));
+    } else if (notification is M.ExceptionNotification) {
+      return new NavNotifyExceptionElement(
+              notification.exception, stacktrace: notification.stacktrace,
+              queue: _r.queue)
+          ..onDelete.listen((_) => _repository.delete(notification));
+    } else {
+      assert(false);
+      return new DivElement()..text = 'Invalid Notification Type';
+    }
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/nav/notify_event.dart b/runtime/observatory/lib/src/elements/nav/notify_event.dart
new file mode 100644
index 0000000..0f75062
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/nav/notify_event.dart
@@ -0,0 +1,232 @@
+// 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 'dart:html';
+import 'dart:async';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
+
+class EventDeleteEvent{
+  final M.Event event;
+  EventDeleteEvent(this.event);
+}
+
+class NavNotifyEventElement extends HtmlElement implements Renderable {
+  static const tag = const Tag<NavNotifyEventElement>('nav-event');
+
+  RenderingScheduler _r;
+
+  Stream<RenderedEvent<NavNotifyEventElement>> get onRendered => _r.onRendered;
+
+  final StreamController<EventDeleteEvent> _onDelete =
+      new StreamController<EventDeleteEvent>.broadcast();
+  Stream<EventDeleteEvent> get onDelete => _onDelete.stream;
+
+  M.Event _event;
+  M.Event get event => _event;
+
+  factory NavNotifyEventElement(M.Event event, {RenderingQueue queue}) {
+    assert(event != null);
+    NavNotifyEventElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._event = event;
+    return e;
+  }
+
+  NavNotifyEventElement.created() : super.created();
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = [];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    children = [];
+    List<Element> content;
+    if (event is M.PauseStartEvent) {
+      content = _managePauseStartEvent(event as M.PauseStartEvent);
+    } else if (event is M.PauseExitEvent) {
+      content = _managePauseExitEvent(event as M.PauseExitEvent);
+    } else if (event is M.PauseBreakpointEvent) {
+      content = _managePauseBreakpointEvent(event as M.PauseBreakpointEvent);
+    } else if (event is M.PauseInterruptedEvent) {
+      content = _managePauseInterruptedEvent(event as M.PauseInterruptedEvent);
+    } else if (event is M.PauseExceptionEvent) {
+      content = _managePauseExceptionEvent(event as M.PauseExceptionEvent);
+    } else if (event is M.NoneEvent) {
+      content = _manageNoneEvent(event as M.NoneEvent);
+    } else if (event is M.ConnectionClosedEvent) {
+      content = _manageConnectionClosedEvent(event as M.ConnectionClosedEvent);
+    } else if (event is M.InspectEvent) {
+      content = _manageInspectEvent(event as M.InspectEvent);
+    } else if (event is M.IsolateReloadEvent) {
+      content = _manageIsolateReloadEvent(event as M.IsolateReloadEvent);
+    } else {
+      return;
+    }
+    children = [
+      new DivElement()
+        ..children = []
+        ..children.addAll(content)
+        ..children.add(new ButtonElement()..innerHtml = '&times;'
+            ..onClick.map(_toEvent).listen(_delete))
+    ];
+  }
+
+  static List<Element> _managePauseStartEvent(M.PauseStartEvent event) {
+    return [
+      new SpanElement()..text = 'Isolate ',
+      new AnchorElement(
+        href: Uris.inspect(event.isolate))
+        ..text = event.isolate.name,
+      new SpanElement()..text = ' is paused at isolate start',
+      new BRElement(), new BRElement(), new SpanElement()..text = '[',
+      new AnchorElement(
+        href: Uris.debugger(event.isolate))
+        ..text = 'debug',
+      new SpanElement()..text = ']'
+    ];
+  }
+
+  static List<Element> _managePauseExitEvent(M.PauseExitEvent event) {
+    return [
+      new SpanElement()..text = 'Isolate ',
+      new AnchorElement(
+        href: Uris.inspect(event.isolate))
+        ..text = event.isolate.name,
+      new SpanElement()..text = ' is paused at isolate exit',
+      new BRElement(), new BRElement(), new SpanElement()..text = '[',
+      new AnchorElement(
+        href: Uris.debugger(event.isolate))
+        ..text = 'debug',
+      new SpanElement()..text = ']'
+    ];
+  }
+
+  static List<Element> _managePauseBreakpointEvent(M.PauseBreakpointEvent event) {
+    String message = ' is paused';
+    if (event.breakpoint != null) {
+       message += ' at breakpoint ${event.breakpoint.number}';
+    }
+    return [
+      new SpanElement()..text = 'Isolate ',
+      new AnchorElement(
+        href: Uris.inspect(event.isolate))
+        ..text = event.isolate.name,
+      new SpanElement()
+        ..text = message,
+      new BRElement(), new BRElement(), new SpanElement()..text = '[',
+      new AnchorElement(
+        href: Uris.debugger(event.isolate))
+        ..text = 'debug',
+      new SpanElement()..text = ']'
+    ];
+  }
+
+  static List<Element> _managePauseInterruptedEvent(M.PauseInterruptedEvent event) {
+    return [
+      new SpanElement()..text = 'Isolate ',
+      new AnchorElement(
+        href: Uris.inspect(event.isolate))
+        ..text = event.isolate.name,
+      new SpanElement()
+        ..text = ' is paused',
+      new BRElement(), new BRElement(), new SpanElement()..text = '[',
+      new AnchorElement(
+        href: Uris.debugger(event.isolate))
+        ..text = 'debug',
+      new SpanElement()..text = ']'
+    ];
+  }
+
+  static List<Element> _managePauseExceptionEvent(M.PauseExceptionEvent event) {
+    return [
+      new SpanElement()..text = 'Isolate ',
+      new AnchorElement(
+        href: Uris.inspect(event.isolate))
+        ..text = event.isolate.name,
+      new SpanElement()
+        ..text = ' is paused due to exception',
+      new BRElement(), new BRElement(), new SpanElement()..text = '[',
+      new AnchorElement(
+        href: Uris.debugger(event.isolate))
+        ..text = 'debug',
+      new SpanElement()..text = ']'
+    ];
+  }
+
+  static List<Element> _manageNoneEvent(M.NoneEvent event) {
+    return [
+      new SpanElement()..text = 'Isolate ',
+      new AnchorElement(
+        href: Uris.inspect(event.isolate))
+        ..text = event.isolate.name,
+      new SpanElement()
+        ..text = ' is paused',
+      new BRElement(), new BRElement(), new SpanElement()..text = '[',
+      new AnchorElement(
+        href: Uris.debugger(event.isolate))
+        ..text = 'debug',
+      new SpanElement()..text = ']'
+    ];
+  }
+
+  static List<Element> _manageConnectionClosedEvent(M.ConnectionClosedEvent event) {
+    return [
+      new SpanElement()..text = 'Disconnected from VM: ${event.reason}',
+      new BRElement(), new BRElement(), new SpanElement()..text = '[',
+      new AnchorElement(href: Uris.vmConnect())..text = 'Connect to a VM',
+      new SpanElement()..text = ']'
+    ];
+  }
+
+  static List<Element> _manageInspectEvent(M.InspectEvent event) {
+    return [
+      new SpanElement()..text = 'Inspect ${event.inspectee.id}',
+      new BRElement(), new BRElement(), new SpanElement()..text = '[',
+      new AnchorElement(href: Uris.inspect(event.isolate,
+          object: event.inspectee))
+        ..text = 'Inspect',
+      new SpanElement()..text = ']'
+      // TODO(cbernaschina) add InstanceRefElement back.
+      //new InstanceRefElement()..instance = event.inspectee
+    ];
+  }
+
+  static List<Element> _manageIsolateReloadEvent(M.IsolateReloadEvent event) {
+    if (event.error != null) {
+      return [
+        new SpanElement()..text = 'Isolate reload failed:',
+        new BRElement(), new BRElement(),
+        new DivElement()
+          ..classes = ["indent", "error"]
+          ..text = event.error.message.toString()
+      ];
+    } else {
+      return [new SpanElement()..text = 'Isolate reload'];
+    }
+  }
+
+  EventDeleteEvent _toEvent(_) {
+    return new EventDeleteEvent(_event);
+  }
+
+  void _delete(EventDeleteEvent e) {
+    _onDelete.add(e);
+  }
+
+  void delete() {
+    _onDelete.add(new EventDeleteEvent(_event));
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/nav/notify_exception.dart b/runtime/observatory/lib/src/elements/nav/notify_exception.dart
new file mode 100644
index 0000000..cf0a463
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/nav/notify_exception.dart
@@ -0,0 +1,128 @@
+// 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 'dart:html';
+import 'dart:async';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
+import 'package:observatory/models.dart' show ConnectionException;
+
+
+class ExceptionDeleteEvent{
+  final Exception exception;
+  final StackTrace stacktrace;
+
+  ExceptionDeleteEvent(this.exception, {this.stacktrace});
+}
+
+class NavNotifyExceptionElement extends HtmlElement implements Renderable {
+  static const tag = const Tag<NavNotifyExceptionElement>('nav-exception');
+
+  RenderingScheduler _r;
+
+  Stream<RenderedEvent<NavNotifyExceptionElement>> get onRendered =>
+                                                                  _r.onRendered;
+
+  final StreamController<ExceptionDeleteEvent> _onDelete =
+      new StreamController<ExceptionDeleteEvent>.broadcast();
+  Stream<ExceptionDeleteEvent> get onDelete => _onDelete.stream;
+
+  Exception _exception;
+  StackTrace _stacktrace;
+  Exception get exception => _exception;
+  StackTrace get stacktrace => _stacktrace;
+
+  factory NavNotifyExceptionElement(Exception exception,
+      {StackTrace stacktrace: null, RenderingQueue queue}) {
+    assert(exception != null);
+    NavNotifyExceptionElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._exception = exception;
+    e._stacktrace = stacktrace;
+    return e;
+  }
+
+  NavNotifyExceptionElement.created() : super.created();
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = [];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    if (exception is ConnectionException) {
+      renderConnectionException();
+    } else {
+      renderGenericException();
+    }
+  }
+
+  void renderConnectionException() {
+    children = [
+      new DivElement()
+        ..children = [
+        new SpanElement()..text = 'The request cannot be completed because the '
+                                  'VM is currently disconnected',
+        new BRElement(), new BRElement(),
+        new SpanElement()..text = '[',
+        new AnchorElement(href: Uris.vmConnect())
+          ..text = 'Connect to a different VM',
+        new SpanElement()..text = ']',
+        new ButtonElement()..innerHtml = '&times;'
+          ..onClick.map(_toEvent).listen(_delete)
+      ]
+    ];
+  }
+
+  void renderGenericException() {
+    List<Node> content;
+    content = [
+      new SpanElement()..text = 'Unexpected exception:',
+      new BRElement(), new BRElement(),
+      new DivElement()..text = exception.toString(),
+      new BRElement()
+    ];
+    if (stacktrace != null) {
+      content.addAll([
+        new SpanElement()..text = 'Stacktrace:',
+        new BRElement(), new BRElement(),
+        new DivElement()..text = stacktrace.toString(),
+        new BRElement()
+      ]);
+    }
+    content.addAll([
+      new SpanElement()..text = '[',
+      new AnchorElement(href: Uris.vmConnect())
+        ..text = 'Connect to a different VM',
+      new SpanElement()..text = ']',
+      new ButtonElement()..innerHtml = '&times;'
+        ..onClick.map(_toEvent).listen(_delete)
+    ]);
+    children = [
+      new DivElement()
+        ..children = content
+    ];
+  }
+
+  ExceptionDeleteEvent _toEvent(_) {
+    return new ExceptionDeleteEvent(exception, stacktrace: stacktrace);
+  }
+
+  void _delete(ExceptionDeleteEvent e) {
+    _onDelete.add(e);
+  }
+
+  void delete() {
+    _onDelete.add(new ExceptionDeleteEvent(exception, stacktrace: stacktrace));
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/nav/notify_wrapper.dart b/runtime/observatory/lib/src/elements/nav/notify_wrapper.dart
new file mode 100644
index 0000000..97f4ded
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/nav/notify_wrapper.dart
@@ -0,0 +1,123 @@
+// 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 'dart:html';
+
+import 'package:observatory/app.dart';
+import 'package:observatory/repositories.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/shims/binding.dart';
+import 'package:observatory/src/elements/nav/notify.dart';
+
+class NavNotifyElementWrapper extends HtmlElement {
+  static final binder = new Binder<NavNotifyElementWrapper>(
+    const [const Binding('notifications'), const Binding('notifyOnPause')]);
+
+  static const tag = const Tag<NavNotifyElementWrapper>('nav-notify');
+
+  NotificationRepository _notifications;
+  bool _notifyOnPause = true;
+  NotificationRepository get notifications => _notifications;
+  bool get notifyOnPause => _notifyOnPause;
+  set notifications(NotificationRepository value) {
+    _notifications = value; render();
+  }
+  set notifyOnPause(bool value) {
+    _notifyOnPause = value; render();
+  }
+
+  NavNotifyElementWrapper.created() : super.created() {
+    binder.registerCallback(this);
+    createShadowRoot();
+    render();
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    render();
+  }
+
+  void render() {
+    shadowRoot.children = [];
+    if (_notifications == null) return;
+
+    shadowRoot.children = [
+      new StyleElement()
+        ..text = '''nav-notify-wrapped > div {
+          float: right;
+        }
+        nav-notify-wrapped > div > div {
+          display: block;
+          position: absolute;
+          top: 98%;
+          right: 0;
+          margin: 0;
+          padding: 0;
+          width: auto;
+          z-index: 1000;
+          background: none;
+        }
+
+        /* nav-exception & nav-event */
+
+        nav-exception > div, nav-event > div {
+          position: relative;
+          padding: 16px;
+          margin-top: 10px;
+          margin-right: 10px;
+          padding-right: 25px;
+          width: 500px;
+          color: #ddd;
+          background: rgba(0,0,0,.6);
+          border: solid 2px white;
+          box-shadow: 0 0 5px black;
+          border-radius: 5px;
+          animation: fadein 1s;
+        }
+
+        nav-exception *, nav-event * {
+          color: #ddd;
+          font-size: 12px;
+        }
+
+        nav-exception > div > a, nav-event > div > a {
+          color: white;
+          text-decoration: none;
+        }
+
+        nav-exception > div > a:hover, nav-event > div > a:hover {
+          text-decoration: underline;
+        }
+
+        nav-exception > div > div {
+          margin-left:20px;
+          white-space: pre
+        }
+
+        nav-exception > div > button, nav-event > div > button {
+          background: transparent;
+          border: none;
+          position: absolute;
+          display: block;
+          top: 4px;
+          right: 4px;
+          height: 18px;
+          width: 18px;
+          line-height: 16px;
+          border-radius: 9px;
+          color: white;
+          font-size: 18px;
+          cursor: pointer;
+          text-align: center;
+        }
+
+        nav-exception > div > button:hover, nav-event > div > button:hover {
+          background: rgba(255,255,255,0.5);
+        }''',
+      new NavNotifyElement(_notifications, notifyOnPause: notifyOnPause,
+                                 queue: ObservatoryApplication.app.queue)
+    ];
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/nav/refresh.dart b/runtime/observatory/lib/src/elements/nav/refresh.dart
new file mode 100644
index 0000000..795c7bd
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/nav/refresh.dart
@@ -0,0 +1,77 @@
+// 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 'dart:html';
+import 'dart:async';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+
+class RefreshEvent {
+  final NavRefreshElement element;
+  RefreshEvent(this.element);
+}
+
+class NavRefreshElement extends HtmlElement implements Renderable {
+  static const tag = const Tag<NavRefreshElement>('nav-refresh-wrapped');
+
+  RenderingScheduler _r;
+
+  Stream<RenderedEvent<NavRefreshElement>> get onRendered => _r.onRendered;
+
+  final StreamController<RefreshEvent> _onRefresh =
+                                new StreamController<RefreshEvent>.broadcast();
+  Stream<RefreshEvent> get onRefresh => _onRefresh.stream;
+
+  bool _disabled;
+  String _label;
+  bool get disabled => _disabled;
+  String get label => _label;
+  set disabled(bool value) => _disabled = _r.checkAndReact(_disabled, value);
+  set label(String value) => _label = _r.checkAndReact(_label, value);
+
+  factory NavRefreshElement({String label: 'Refresh', bool disabled: false,
+                             RenderingQueue queue}) {
+    assert(label != null);
+    assert(disabled != null);
+    NavRefreshElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._label = label;
+    e._disabled = disabled;
+    return e;
+  }
+
+  NavRefreshElement.created() : super.created();
+
+  @override
+  void attached() { super.attached(); _r.enable(); }
+
+  @override
+  void detached() { super.detached(); children = []; _r.disable(notify: true); }
+
+  void render() {
+    children = [
+      new LIElement()
+        ..children = [
+          new ButtonElement()
+            ..text = label
+            ..disabled = disabled
+            ..onClick.map(_toEvent).listen(_refresh)
+        ]
+    ];
+  }
+
+  RefreshEvent _toEvent(_) {
+    return new RefreshEvent(this);
+  }
+
+  void _refresh(RefreshEvent e) {
+    if (_disabled) return;
+    _onRefresh.add(e);
+  }
+
+  void refresh() {
+    if (_disabled) return;
+    _refresh(new RefreshEvent(this));
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/nav/refresh_wrapper.dart b/runtime/observatory/lib/src/elements/nav/refresh_wrapper.dart
new file mode 100644
index 0000000..dcd1696
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/nav/refresh_wrapper.dart
@@ -0,0 +1,78 @@
+// 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 'dart:html';
+import 'dart:async';
+
+import 'package:observatory/app.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/shims/binding.dart';
+import 'package:observatory/src/elements/nav/refresh.dart';
+
+class NavRefreshElementWrapper extends HtmlElement {
+  static final binder = new Binder<NavRefreshElementWrapper>(
+    const [const Binding('callback'), const Binding('label')]);
+
+  static const tag = const Tag<NavRefreshElementWrapper>('nav-refresh');
+
+  Function _callback;
+  String _label;
+  Function get callback => _callback;
+  String get label => _label;
+  set callback(Function value) {
+    _callback = value; render();
+  }
+  set label(String value) {
+    _label = value; render();
+  }
+
+  NavRefreshElementWrapper.created() : super.created() {
+    binder.registerCallback(this);
+    _label = getAttribute('label') ?? 'Refresh';
+    createShadowRoot();
+    render();
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    render();
+  }
+
+  void render() {
+    shadowRoot.children = [];
+    if (_callback == null || _label == null) return;
+
+    shadowRoot.children = [
+      new StyleElement()
+        ..text = '''nav-refresh-wrapped > li > button {
+          color: #000;
+          margin: 3px;
+          padding: 8px;
+          border-width: 2px;
+          line-height: 13px;
+          font: 400 13px 'Montserrat', sans-serif;
+        }
+        nav-refresh-wrapped > li > button[disabled] {
+          color: #aaa;
+          cursor: wait;
+        }
+        nav-refresh-wrapped > li {
+          float: right;
+          margin: 0;
+        }''',
+      new NavRefreshElement(label: _label,
+                            queue: ObservatoryApplication.app.queue)
+        ..onRefresh.listen((event) async{
+          event.element.disabled = true;
+          try {
+            var future = callback();
+            if (future is Future) await future;
+          } finally {
+            event.element.disabled = false;
+          }
+        })
+    ];
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/nav/top_menu.dart b/runtime/observatory/lib/src/elements/nav/top_menu.dart
new file mode 100644
index 0000000..a289277
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/nav/top_menu.dart
@@ -0,0 +1,60 @@
+// 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 'dart:html';
+import 'dart:async';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
+import 'package:observatory/src/elements/nav/menu.dart';
+import 'package:observatory/src/elements/nav/menu_item.dart';
+
+class NavTopMenuElement extends HtmlElement implements Renderable {
+  static const tag = const Tag<NavTopMenuElement>('nav-top-menu',
+                     dependencies: const [NavMenuElement.tag,
+                                          NavMenuItemElement.tag]);
+
+  RenderingScheduler _r;
+
+  Stream<RenderedEvent<NavTopMenuElement>> get onRendered => _r.onRendered;
+
+  bool _last;
+  bool get last => _last;
+  set last(bool value) => _last = _r.checkAndReact(_last, value);
+
+  factory NavTopMenuElement({bool last: false, RenderingQueue queue}) {
+    assert(last != null);
+    NavTopMenuElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._last = last;
+    return e;
+  }
+
+  NavTopMenuElement.created() : super.created() { createShadowRoot(); }
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    shadowRoot.children = [];
+  }
+
+  void render() {
+    shadowRoot.children = [
+      new NavMenuElement('Observatory', link: Uris.vm(), last: last,
+                         queue: _r.queue)
+        ..children = [
+          new NavMenuItemElement('Connect to a VM', link: Uris.vmConnect(),
+                                 queue: _r.queue),
+          new ContentElement()
+        ]
+    ];
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/nav/top_menu_wrapper.dart b/runtime/observatory/lib/src/elements/nav/top_menu_wrapper.dart
new file mode 100644
index 0000000..fbfebff
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/nav/top_menu_wrapper.dart
@@ -0,0 +1,51 @@
+// 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 'dart:html';
+
+import 'package:observatory/app.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/shims/binding.dart';
+import 'package:observatory/src/elements/nav/top_menu.dart';
+
+class NavTopMenuElementWrapper extends HtmlElement {
+  static final binder = new Binder<NavTopMenuElementWrapper>(
+    const [const Binding('last')]);
+
+  static const tag = const Tag<NavTopMenuElementWrapper>('top-nav-menu');
+
+  bool _last = false;
+  bool get last => _last;
+  set last(bool value) {
+    _last = value; render();
+  }
+
+  NavTopMenuElementWrapper.created() : super.created() {
+    binder.registerCallback(this);
+    _last = _getBoolAttribute('last');
+    createShadowRoot();
+    render();
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    render();
+  }
+
+  void render() {
+    shadowRoot.children = [];
+    if (_last == null) return;
+
+    shadowRoot.children = [
+      new NavTopMenuElement(last: last, queue: ObservatoryApplication.app.queue)
+        ..children = [new ContentElement()]
+    ];
+  }
+
+  bool _getBoolAttribute(String name) {
+    final String value = getAttribute(name);
+    return !(value == null || value == 'false');
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/nav/vm_menu.dart b/runtime/observatory/lib/src/elements/nav/vm_menu.dart
new file mode 100644
index 0000000..a46d4ca
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/nav/vm_menu.dart
@@ -0,0 +1,84 @@
+// 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 'dart:html';
+import 'dart:async';
+import 'package:observatory/models.dart' as M
+  show VM, IsolateRef, Target, VMUpdateEvent;
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
+import 'package:observatory/src/elements/nav/menu.dart';
+import 'package:observatory/src/elements/nav/menu_item.dart';
+
+class NavVMMenuElement extends HtmlElement implements Renderable {
+  static const tag = const Tag<NavVMMenuElement>('nav-vm-menu',
+                     dependencies: const [NavMenuElement.tag,
+                                          NavMenuItemElement.tag]);
+
+  RenderingScheduler _r;
+
+  Stream<RenderedEvent<NavVMMenuElement>> get onRendered => _r.onRendered;
+
+  Stream<M.VMUpdateEvent> _updates;
+  StreamSubscription _updatesSubscription;
+
+  bool _last;
+  M.VM _vm;
+  M.Target _target;
+  bool get last => _last;
+  M.VM get vm => _vm;
+  M.Target get target => _target;
+  set last(bool value) => _last = _r.checkAndReact(_last, value);
+
+  factory NavVMMenuElement(M.VM vm, Stream<M.VMUpdateEvent> updates,
+      {bool last: false, M.Target target, RenderingQueue queue}) {
+    assert(vm != null);
+    assert(updates != null);
+    assert(last != null);
+    NavVMMenuElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._vm = vm;
+    e._updates = updates;
+    e._last = last;
+    e._target = target;
+    return e;
+  }
+
+  NavVMMenuElement.created() : super.created() { createShadowRoot(); }
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+    _updatesSubscription = _updates
+      .listen((M.VMUpdateEvent e) { _vm = e.vm; _r.dirty(); });
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    shadowRoot.children = [];
+    assert(_updatesSubscription != null);
+    _updatesSubscription.cancel();
+    _updatesSubscription = null;
+  }
+
+  void render() {
+    final String name = (target == null) ? vm.name
+                                         : '${vm.name}@${target.name}';
+    /// TODO(cbernaschina) use the isolate repository.
+    shadowRoot.children = [
+      new NavMenuElement(name, link: Uris.vm(), last: last, queue: _r.queue)
+        ..children = (
+          _vm.isolates.map((M.IsolateRef isolate) {
+            return new NavMenuItemElement(isolate.name, queue: _r.queue,
+                link: Uris.inspect(isolate));
+          }).toList()
+          ..add(new ContentElement())
+        )
+    ];
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/nav/vm_menu_wrapper.dart b/runtime/observatory/lib/src/elements/nav/vm_menu_wrapper.dart
new file mode 100644
index 0000000..ef71b2d
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/nav/vm_menu_wrapper.dart
@@ -0,0 +1,89 @@
+// 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 'dart:html';
+import 'dart:async';
+
+import 'package:observatory/app.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/service.dart';
+import 'package:observatory/service_common.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/shims/binding.dart';
+import 'package:observatory/src/elements/nav/vm_menu.dart';
+
+class NavVMMenuElementWrapper extends HtmlElement {
+  static final binder = new Binder<NavVMMenuElementWrapper>(
+    const [const Binding('last'), const Binding('vm')]);
+
+  static const tag = const Tag<NavVMMenuElementWrapper>('vm-nav-menu');
+
+  StreamSubscription _subscription;
+  StreamController<M.VMUpdateEvent> _updatesController =
+      new StreamController<M.VMUpdateEvent>.broadcast();
+
+  bool _last = false;
+  VM _vm;
+  bool get last => _last;
+  VM get vm => _vm;
+  set last(bool value) {
+    _last = value; render();
+  }
+  set vm(VM value) {
+    _vm = value; _detached(); _attached();
+  }
+
+  NavVMMenuElementWrapper.created() : super.created() {
+    binder.registerCallback(this);
+    _last = _getBoolAttribute('last');
+    createShadowRoot();
+    render();
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    _attached();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _detached();
+  }
+
+  void _attached() {
+    if (_vm != null) {
+      _subscription = _vm.changes.listen((_) {
+        _updatesController.add(new VMUpdateEventMock(vm: _vm));
+      });
+    }
+    render();
+  }
+
+  void _detached() {
+    if (_subscription != null) {
+      _subscription.cancel();
+      _subscription = null;
+    }
+  }
+
+  void render() {
+    shadowRoot.children = [];
+    if (_vm == null || _last == null) return;
+
+    shadowRoot.children = [
+      new NavVMMenuElement(vm, _updatesController.stream, last: last,
+          target: (vm as CommonWebSocketVM)?.target,
+          queue: ObservatoryApplication.app.queue)
+        ..children = [new ContentElement()]
+    ];
+  }
+
+  bool _getBoolAttribute(String name) {
+    final String value = getAttribute(name);
+    return !(value == null || value == 'false');
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/nav_bar.dart b/runtime/observatory/lib/src/elements/nav_bar.dart
deleted file mode 100644
index 3999db87..0000000
--- a/runtime/observatory/lib/src/elements/nav_bar.dart
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library nav_bar_element;
-
-import 'dart:async';
-import 'dart:html' hide Notification;
-import 'observatory_element.dart';
-import 'package:observatory/service.dart';
-import 'package:observatory/app.dart' show Notification;
-import 'package:polymer/polymer.dart';
-
-
-@CustomTag('nav-bar')
-class NavBarElement extends ObservatoryElement {
-  @published bool notifyOnPause = true;
-  @published bool pad = true;
-
-  // Desired nav var height in pixels.
-  static const height = 40;
-
-  NavBarElement.created() : super.created();
-}
-
-@CustomTag('nav-menu')
-class NavMenuElement extends ObservatoryElement {
-  @published String link = '#';
-  @published String anchor = '---';
-  @published bool last = false;
-
-  NavMenuElement.created() : super.created();
-}
-
-@CustomTag('nav-menu-item')
-class NavMenuItemElement extends ObservatoryElement {
-  @published String link = '#';
-  @published String anchor = '---';
-
-  NavMenuItemElement.created() : super.created();
-}
-
-typedef Future RefreshCallback();
-
-@CustomTag('nav-refresh')
-class NavRefreshElement extends ObservatoryElement {
-  @published RefreshCallback callback;
-  @published bool active = false;
-  @published String label = 'Refresh';
-
-  NavRefreshElement.created() : super.created();
-
-  void buttonClick(Event e, var detail, Node target) {
-    if (active) {
-      return;
-    }
-    active = true;
-    if (callback != null) {
-      callback()
-        .catchError(app.handleException)
-        .whenComplete(refreshDone);
-    }
-  }
-
-  void refreshDone() {
-    active = false;
-  }
-}
-
-@CustomTag('top-nav-menu')
-class TopNavMenuElement extends ObservatoryElement {
-  @published bool last = false;
-
-  TopNavMenuElement.created() : super.created();
-}
-
-@CustomTag('vm-nav-menu')
-class VMNavMenuElement extends ObservatoryElement {
-  @published bool last = false;
-  @published VM vm;
-
-  String nameAndAddress(name, target) {
-    if (name != null && target != null) {
-      return '${name}@${target.networkAddress}';
-    } else {
-      return '<initializing>';
-    }
-  }
-
-  VMNavMenuElement.created() : super.created();
-}
-
-@CustomTag('isolate-nav-menu')
-class IsolateNavMenuElement extends ObservatoryElement {
-  @published bool last = false;
-  @published Isolate isolate;
-
-  IsolateNavMenuElement.created() : super.created();
-}
-
-@CustomTag('library-nav-menu')
-class LibraryNavMenuElement extends ObservatoryElement {
-  @published Library library;
-  @published bool last = false;
-
-  LibraryNavMenuElement.created() : super.created();
-}
-
-@CustomTag('class-nav-menu')
-class ClassNavMenuElement extends ObservatoryElement {
-  @published Class cls;
-  @published bool last = false;
-
-  ClassNavMenuElement.created() : super.created();
-}
-
-@CustomTag('nav-notify')
-class NavNotifyElement extends ObservatoryElement {
-  @published ObservableList<Notification> notifications;
-  @published bool notifyOnPause = true;
-
-  NavNotifyElement.created() : super.created();
-}
-
-@CustomTag('nav-notify-event')
-class NavNotifyEventElement extends ObservatoryElement {
-  @published ObservableList<Notification> notifications;
-  @published Notification notification;
-  @published ServiceEvent event;
-  @published bool notifyOnPause = true;
-
-  void closeItem(MouseEvent e, var detail, Element target) {
-    notifications.remove(notification);
-  }
-
-  NavNotifyEventElement.created() : super.created();
-}
-
-@CustomTag('nav-notify-exception')
-class NavNotifyExceptionElement extends ObservatoryElement {
-  @published ObservableList<Notification> notifications;
-  @published Notification notification;
-  @published var exception;
-  @published var stacktrace;
-
-  exceptionChanged() {
-    notifyPropertyChange(#isNetworkError, true, false);
-    notifyPropertyChange(#isUnexpectedError, true, false);
-  }
-
-  @observable get isNetworkError {
-    return (exception is NetworkRpcException);
-  }
-
-  @observable get isUnexpectedError {
-    return (exception is! NetworkRpcException);
-  }
-
-  void closeItem(MouseEvent e, var detail, Element target) {
-    notifications.remove(notification);
-  }
-
-  NavNotifyExceptionElement.created() : super.created();
-}
diff --git a/runtime/observatory/lib/src/elements/nav_bar.html b/runtime/observatory/lib/src/elements/nav_bar.html
deleted file mode 100644
index c97b1d1..0000000
--- a/runtime/observatory/lib/src/elements/nav_bar.html
+++ /dev/null
@@ -1,486 +0,0 @@
-<link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="action_link.html">
-<link rel="import" href="observatory_element.html">
-
-<polymer-element name="nav-bar" extends="observatory-element">
-  <template>
-    <link rel="stylesheet" href="css/shared.css">
-    <style>
-      nav {
-        position: fixed;
-        width: 100%;
-        z-index: 1000;
-      }
-      nav ul {
-        display: inline-table;
-        position: relative;
-        list-style: none;
-        padding-left: 0;
-        margin-left: 0;
-        width: 100%;
-        z-index: 1000;
-        font: 400 16px 'Montserrat', sans-serif;
-        color: white;
-        background-color: #0489c3;
-      }
-      nav ul:after {
-        content: ""; clear: both; display: block;
-      }
-      .vertical-spacer {
-        height: 40px;
-        background-color: #0489c3;
-      }
-    </style>
-    <nav>
-      <ul>
-        <nav-notify notifications="{{ app.notifications }}"
-                    notifyOnPause="{{ notifyOnPause }}"></nav-notify>
-        <content></content>
-      </ul>
-    </nav>
-    <div class="vertical-spacer">
-    </div>
-    <template if="{{ pad }}">
-      <br>
-    </template>
-  </template>
-</polymer-element>
-
-<polymer-element name="nav-menu" extends="observatory-element">
-  <template>
-    <style>
-      .menu, .spacer {
-        float: left;
-      }
-      .menu a, .spacer {
-        display: block;
-        padding: 12px 8px;
-        color: White;
-        text-decoration: none;
-      }
-      .menu:hover {
-        background: #455;
-      }
-      .menu ul {
-        display: none;
-        position: absolute;
-        top: 98%;
-        list-style: none;
-        margin: 0;
-        padding: 0;
-        width: auto;
-        z-index: 1000;
-        font: 400 16px 'Montserrat', sans-serif;
-        color: white;
-        background: #567;
-      }
-      .menu ul:after {
-        content: ""; clear: both; display: block;
-      }
-      .menu:hover > ul {
-        display: block;
-      }
-    </style>
-
-    <li class="menu">
-      <a on-click="{{ goto }}" _href="{{ gotoLink(link) }}">{{ anchor }}</a>
-      <ul><content></content></ul>
-    </li>
-    <template if="{{ !last }}">
-      <li class="spacer">&gt;</li>
-    </template>
-
-  </template>
-</polymer-element>
-
-<polymer-element name="nav-menu-item" extends="observatory-element">
-  <template>
-    <style>
-      li {
-        float: none;
-        border-top: 1px solid #677;
-        border-bottom: 1px solid #556; position: relative;
-      }
-      li:hover {
-        background: #455;
-      }
-      li ul {
-        display: none;
-        position: absolute;
-        top:0;
-        left: 100%;
-        list-style: none;
-        padding: 0;
-        margin-left: 0;
-        width: auto;
-        z-index: 1000;
-        font: 400 16px 'Montserrat', sans-serif;
-        color: white;
-        background: #567;
-      }
-      li ul:after {
-        content: ""; clear: both; display: block;
-      }
-      li:hover > ul {
-        display: block;
-      }
-      li a {
-        display: block;
-        padding: 12px 12px;
-        color: white;
-        text-decoration: none;
-      }
-    </style>
-    <li><a on-click="{{ goto }}" _href="{{ gotoLink(link) }}">{{ anchor }}</a>
-      <ul><content></content></ul>
-    </li>
-  </template>
-</polymer-element>
-
-<polymer-element name="nav-refresh" extends="observatory-element">
-  <template>
-    <style>
-      .active {
-        color: #aaa;
-        cursor: wait;
-      }
-      .idle {
-        color: #000;
-      }
-      li {
-        float: right;
-        margin: 0;
-      }
-      li button {
-        margin: 3px;
-        padding: 8px;
-      }
-    </style>
-    <li>
-      <template if="{{ active }}">
-        <button class="active" on-click="{{ buttonClick }}">{{ label }}</button>
-      </template>
-      <template if="{{ !active }}">
-        <button class="idle" on-click="{{ buttonClick }}">{{ label }}</button>
-      </template>
-    </li>
-  </template>
-</polymer-element>
-
-<polymer-element name="top-nav-menu">
-  <template>
-    <nav-menu link="/vm" anchor="Observatory" last="{{ last }}">
-      <nav-menu-item link="/vm-connect" anchor="Connect to a VM"></nav-menu-item>
-      <content></content>
-    </nav-menu>
-  </template>
-</polymer-element>
-
-<polymer-element name="vm-nav-menu">
-  <template>
-    <nav-menu link="/vm" anchor="{{ nameAndAddress(vm.name, vm.target) }}" last="{{ last }}">
-      <template repeat="{{ isolate in vm.isolates }}">
-        <nav-menu-item link="{{ makeLink('/inspect', isolate) }}"
-	               anchor="{{ isolate.name }}"></nav-menu-item>
-      </template>
-      <content></content>
-    </nav-menu>
-  </template>
-</polymer-element>
-
-<polymer-element name="isolate-nav-menu" extends="observatory-element">
-  <template>
-    <nav-menu link="{{ makeLink('/inspect', isolate) }}" anchor="{{ isolate.name }}" last="{{ last }}">
-      <nav-menu-item link="{{ makeLink('/debugger', isolate) }}"
-                     anchor="debugger"></nav-menu-item>
-      <nav-menu-item link="{{ makeLink('/class-tree', isolate) }}"
-                     anchor="class hierarchy"></nav-menu-item>
-      <nav-menu-item link="{{ makeLink('/profiler', isolate) }}"
-                     anchor="cpu profile"></nav-menu-item>
-      <nav-menu-item link="{{ makeLink('/profiler-table', isolate) }}"
-                     anchor="cpu profile (table)"></nav-menu-item>
-      <nav-menu-item link="{{ makeLink('/allocation-profiler', isolate) }}"
-                     anchor="allocation profile"></nav-menu-item>
-      <nav-menu-item link="{{ makeLink('/heap-map', isolate) }}"
-                     anchor="heap map"></nav-menu-item>
-      <nav-menu-item link="{{ makeLink('/metrics', isolate) }}"
-                     anchor="metrics"></nav-menu-item>
-      <nav-menu-item link="{{ makeLink('/heap-snapshot', isolate) }}"
-                     anchor="heap snapshot"></nav-menu-item>
-      <nav-menu-item link="{{ makeLink('/persistent-handles', isolate) }}"
-                     anchor="persistent handles"></nav-menu-item>
-      <nav-menu-item link="{{ makeLink('/ports', isolate) }}"
-                     anchor="ports"></nav-menu-item>
-      <nav-menu-item link="{{ makeLink('/logging', isolate) }}"
-                     anchor="logging"></nav-menu-item>
-      <content></content>
-    </nav-menu>
-  </template>
-</polymer-element>
-
-<polymer-element name="library-nav-menu" extends="observatory-element">
-  <template>
-    <nav-menu link="{{ makeLink('/inspect', library) }}"
-              anchor="{{ library.name }}" last="{{ last }}">
-      <content></content>
-    </nav-menu>
-  </template>
-</polymer-element>
-
-<polymer-element name="class-nav-menu" extends="observatory-element">
-  <template>
-    <nav-menu link="{{ makeLink('/inspect', cls) }}"
-              anchor="{{ cls.name }}" last="{{ last }}">
-      <content></content>
-    </nav-menu>
-  </template>
-</polymer-element>
-
-<polymer-element name="nav-notify" extends="observatory-element">
-  <template>
-    <style>
-      .menu {
-        float: right;
-      }
-      .menu .list {
-        display: block;
-        position: absolute;
-        top: 98%;
-        right: 0;
-        margin: 0;
-        padding: 0;
-        width: auto;
-        z-index: 1000;
-        font: 400 12px 'Montserrat', sans-serif;
-        color: white;
-        background: none;
-      }
-    </style>
-
-    <div class="menu">
-      <div class="list">
-        <template repeat="{{ notification in notifications }}">
-          <template if="{{ notification.event != null }}">
-            <nav-notify-event notifications="{{ notifications }}"
-                              notification="{{ notification }}"
-                              event="{{ notification.event }}"
-                              notifyOnPause="{{ notifyOnPause }}">
-            </nav-notify-event>
-          </template>
-          <template if="{{ notification.exception != null }}">
-            <nav-notify-exception notifications="{{ notifications }}"
-                              notification="{{ notification }}"
-                              exception="{{ notification.exception }}"
-                              stacktrace="{{ notification.stacktrace }}">
-            </nav-notify-exception>
-          </template>
-        </template>
-      </div>
-    </div>
-  </template>
-</polymer-element>
-
-<polymer-element name="nav-notify-event" extends="observatory-element">
-  <template>
-    <style>
-      .item {
-        position: relative;
-        padding: 16px;
-        margin-top: 10px;
-        margin-right: 10px;
-        padding-right: 25px;
-        width: 250px;
-        color: #ddd;
-        background: rgba(0,0,0,.6);
-        border: solid 2px white;
-        box-shadow: 0 0 5px black;
-        border-radius: 5px;
-        animation: fadein 1s;
-      }
-
-      .wide-item {
-        width: 50vw;
-      }
-
-      @keyframes fadein {
-        from { opacity: 0; }
-        to   { opacity: 1; }
-      }
-
-      a.link {
-        color: white;
-        text-decoration: none;
-      }
-      a.link:hover {
-        text-decoration: underline;
-      }
-
-      a.boxclose {
-        position: absolute;
-        display: block;
-        top: 4px;
-        right: 4px;
-        height: 18px;
-        width: 18px;
-        line-height: 16px;
-        border-radius: 9px;
-        color: white;
-        font-size: 18px;
-        cursor: pointer;
-        text-align: center;
-      }
-      a.boxclose:hover {
-        background: rgba(255,255,255,0.5);
-      }
-      .error {
-        white-space: pre;
-      }
-    </style>
-    <template if="{{ event != null }}">
-      <template if="{{ notifyOnPause && event.isPauseEvent }}">
-        <div class="item">
-          Isolate
-          <a class="link" on-click="{{ goto }}"
-             _href="{{ gotoLink('/inspect', event.isolate) }}">{{ event.isolate.name }}</a>
-          is paused
-          <template if="{{ event.kind == 'PauseStart' }}">
-            at isolate start
-          </template>
-          <template if="{{ event.kind == 'PauseExit' }}">
-            at isolate exit
-          </template>
-          <template if="{{ event.breakpoint != null }}">
-            at breakpoint {{ event.breakpoint.number }}
-          </template>
-          <template if="{{ event.kind == 'PauseException' }}">
-            due to exception
-          </template>
-
-          <br><br>
-          [<a class="link" on-click="{{ goto }}"
-              _href="{{ gotoLink('/debugger', event.isolate) }}">debug</a>]
-
-          <a class="boxclose" on-click="{{ closeItem }}">&times;</a>
-        </div>
-      </template>
-      <template if="{{ event.kind == 'ConnectionClosed' }}">
-        <div class="item">
-          Disconnected from VM: {{ event.reason }}
-          <br><br>
-          [<a class="link" on-click="{{ goto }}"
-              _href="{{ gotoLink('/vm-connect') }}">Connect to a VM</a>]
-          <a class="boxclose" on-click="{{ closeItem }}">&times;</a>
-        </div>
-      </template>
-      <template if="{{ event.kind == 'Inspect' }}">
-        <div class="item">
-          Inspect <any-service-ref ref="{{ event.inspectee }}"></any-service-ref>
-          <br><br>
-          <a class="boxclose" on-click="{{ closeItem }}">&times;</a>
-        </div>
-      </template>
-      <template if="{{ event.kind == 'IsolateReload' }}">
-        <div class="wide-item item">
-          Isolate reload
-          <template if="{{ event.reloadError != null }}">
-            failed:
-            <br>
-            <br>
-            <div class="indent error">{{ event.reloadError.message.toString() }}</div><br>
-          </template>
-          <template if="{{ event.reloadError == null }}">
-            succeeded
-          </template>
-          <a class="boxclose" on-click="{{ closeItem }}">&times;</a>
-        </div>
-      </template>
-    </template>
-  </template>
-</polymer-element>
-
-
-<polymer-element name="nav-notify-exception" extends="observatory-element">
-  <template>
-    <style>
-      .item {
-        position: relative;
-        padding: 16px;
-        margin-top: 10px;
-        margin-right: 10px;
-        padding-right: 25px;
-        width: 500px;
-        color: #ddd;
-        background: rgba(0,0,0,.6);
-        border: solid 2px white;
-        box-shadow: 0 0 5px black;
-        border-radius: 5px;
-        animation: fadein 1s;
-      }
-
-      @keyframes fadein {
-        from { opacity: 0; }
-        to   { opacity: 1; }
-      }
-
-      a.link {
-        color: white;
-        text-decoration: none;
-      }
-      a.link:hover {
-        text-decoration: underline;
-      }
-      .indent {
-        margin-left:20px;
-      }
-
-      a.boxclose {
-        position: absolute;
-        display: block;
-        top: 4px;
-        right: 4px;
-        height: 18px;
-        width: 18px;
-        line-height: 16px;
-        border-radius: 9px;
-        color: white;
-        font-size: 18px;
-        cursor: pointer;
-        text-align: center;
-      }
-      a.boxclose:hover {
-        background: rgba(255,255,255,0.5);
-      }
-      .stacktrace {
-        white-space: pre
-      }
-    </style>
-    <template if="{{ isUnexpectedError }}">
-      <!-- TODO(turnidge): Add a file-a-bug link to this notification -->
-      <div class="item">
-        Unexpected exception:<br><br>
-        <div class="indent">{{ exception.toString() }}</div><br>
-        <template if="{{ stacktrace != null }}">
-          Stacktrace:<br><br>
-          <div class="indent stacktrace">{{ stacktrace.toString() }}</div>
-          <br>
-        </template>
-        [<a class="link" on-click="{{ goto }}"
-            _href="{{ gotoLink('vm-connect') }}">Connect to a different VM</a>]
-        <a class="boxclose" on-click="{{ closeItem }}">&times;</a>
-    </div>
-    </template>
-    <template if="{{ isNetworkError }}">
-      <div class="item">
-        The request cannot be completed because the VM is currently
-        disconnected.
-        <br><br>
-        [<a class="link" on-click="{{ goto }}"
-            _href="{{ gotoLink('vm-connect') }}">Connect to a different VM</a>]
-        <a class="boxclose" on-click="{{ closeItem }}">&times;</a>
-    </div>
-    </template>
-  </template>
-</polymer-element>
-
-
-<script type="application/dart" src="nav_bar.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/object_common.html b/runtime/observatory/lib/src/elements/object_common.html
index 14311e0..c0167ea 100644
--- a/runtime/observatory/lib/src/elements/object_common.html
+++ b/runtime/observatory/lib/src/elements/object_common.html
@@ -5,11 +5,9 @@
 <link rel="import" href="function_ref.html">
 <link rel="import" href="inbound_reference.html">
 <link rel="import" href="instance_ref.html">
-<link rel="import" href="observatory_element.html">
-<link rel="import" href="nav_bar.html">
 <link rel="import" href="eval_link.html">
 
-<polymer-element name="object-common" extends="observatory-element">
+<polymer-element name="object-common">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <div class="memberList">
diff --git a/runtime/observatory/lib/src/elements/object_view.html b/runtime/observatory/lib/src/elements/object_view.html
index eff9e49..99917f2 100644
--- a/runtime/observatory/lib/src/elements/object_view.html
+++ b/runtime/observatory/lib/src/elements/object_view.html
@@ -5,12 +5,10 @@
 <link rel="import" href="function_ref.html">
 <link rel="import" href="inbound_reference.html">
 <link rel="import" href="instance_ref.html">
-<link rel="import" href="observatory_element.html">
 <link rel="import" href="object_common.html">
-<link rel="import" href="nav_bar.html">
 <link rel="import" href="eval_link.html">
 
-<polymer-element name="object-view" extends="observatory-element">
+<polymer-element name="object-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <nav-bar>
@@ -19,6 +17,7 @@
       <isolate-nav-menu isolate="{{ object.isolate }}"></isolate-nav-menu>
       <nav-menu link="." anchor="object" last="{{ true }}"></nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content">
diff --git a/runtime/observatory/lib/src/elements/objectpool_view.html b/runtime/observatory/lib/src/elements/objectpool_view.html
index 4177eea..1aff2dd 100644
--- a/runtime/observatory/lib/src/elements/objectpool_view.html
+++ b/runtime/observatory/lib/src/elements/objectpool_view.html
@@ -5,12 +5,10 @@
 <link rel="import" href="function_ref.html">
 <link rel="import" href="inbound_reference.html">
 <link rel="import" href="instance_ref.html">
-<link rel="import" href="observatory_element.html">
 <link rel="import" href="object_common.html">
-<link rel="import" href="nav_bar.html">
 <link rel="import" href="eval_link.html">
 
-<polymer-element name="objectpool-view" extends="observatory-element">
+<polymer-element name="objectpool-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <nav-bar>
@@ -19,6 +17,7 @@
       <isolate-nav-menu isolate="{{ pool.isolate }}"></isolate-nav-menu>
       <nav-menu link="." anchor="object" last="{{ true }}"></nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content">
@@ -48,7 +47,7 @@
       </div>
 
     </div>
-  
+
     <hr>
     <view-footer></view-footer>
   </template>
diff --git a/runtime/observatory/lib/src/elements/objectstore_view.html b/runtime/observatory/lib/src/elements/objectstore_view.html
index a8d4d02..01f467b 100644
--- a/runtime/observatory/lib/src/elements/objectstore_view.html
+++ b/runtime/observatory/lib/src/elements/objectstore_view.html
@@ -1,17 +1,13 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="class_ref.html">
-<link rel="import" href="curly_block.html">
 <link rel="import" href="eval_box.html">
 <link rel="import" href="field_ref.html">
 <link rel="import" href="function_ref.html">
 <link rel="import" href="instance_ref.html">
-<link rel="import" href="observatory_element.html">
 <link rel="import" href="library_ref.html">
-<link rel="import" href="nav_bar.html">
 <link rel="import" href="script_ref.html">
-<link rel="import" href="view_footer.html">
 
-<polymer-element name="objectstore-view" extends="observatory-element">
+<polymer-element name="objectstore-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
 
@@ -20,6 +16,7 @@
       <vm-nav-menu vm="{{ objectStore.isolate.vm }}"></vm-nav-menu>
       <isolate-nav-menu isolate="{{ objectStore.isolate }}" last="{{ true }}"></isolate-nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content-centered-big">
diff --git a/runtime/observatory/lib/src/elements/observatory_application.html b/runtime/observatory/lib/src/elements/observatory_application.html
index 73a2615..d91819f 100644
--- a/runtime/observatory/lib/src/elements/observatory_application.html
+++ b/runtime/observatory/lib/src/elements/observatory_application.html
@@ -1,7 +1,7 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="observatory_element.html">
+
 <link rel="import" href="service_view.html">
-<polymer-element name="observatory-application" extends="observatory-element">
+<polymer-element name="observatory-application">
   <!-- This element explicitly manages its child elements -->
 </polymer-element>
 
diff --git a/runtime/observatory/lib/src/elements/observatory_element.dart b/runtime/observatory/lib/src/elements/observatory_element.dart
index 164f079..a661ccf 100644
--- a/runtime/observatory/lib/src/elements/observatory_element.dart
+++ b/runtime/observatory/lib/src/elements/observatory_element.dart
@@ -11,7 +11,6 @@
 import 'package:polymer/polymer.dart';
 
 /// Base class for all Observatory custom elements.
-@CustomTag('observatory-element')
 class ObservatoryElement extends PolymerElement {
   ObservatoryElement.created() : super.created();
 
diff --git a/runtime/observatory/lib/src/elements/observatory_element.html b/runtime/observatory/lib/src/elements/observatory_element.html
deleted file mode 100644
index dce89dc..0000000
--- a/runtime/observatory/lib/src/elements/observatory_element.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<link rel="import" href="../../../../packages/polymer/polymer.html">
-
-<polymer-element name="observatory-element">
-</polymer-element>
-
-<script type="application/dart" src="observatory_element.dart"></script>
\ No newline at end of file
diff --git a/runtime/observatory/lib/src/elements/persistent_handles.html b/runtime/observatory/lib/src/elements/persistent_handles.html
index 9005494..af92aa7 100644
--- a/runtime/observatory/lib/src/elements/persistent_handles.html
+++ b/runtime/observatory/lib/src/elements/persistent_handles.html
@@ -1,8 +1,6 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="nav_bar.html">
-<link rel="import" href="observatory_element.html">
 
-<polymer-element name="persistent-handles-page" extends="observatory-element">
+<polymer-element name="persistent-handles-page">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
@@ -56,6 +54,7 @@
       <isolate-nav-menu isolate="{{ isolate }}"></isolate-nav-menu>
       <nav-menu link="{{ makeLink('/persistent-handles', isolate) }}" anchor="persistent handles" last="{{ true }}"></nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
     <div class="content-centered-big">
       <template if="{{ persistentHandles.isEmpty }}">
diff --git a/runtime/observatory/lib/src/elements/ports.html b/runtime/observatory/lib/src/elements/ports.html
index d5b3152..af2adfb 100644
--- a/runtime/observatory/lib/src/elements/ports.html
+++ b/runtime/observatory/lib/src/elements/ports.html
@@ -1,8 +1,6 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="nav_bar.html">
-<link rel="import" href="observatory_element.html">
 
-<polymer-element name="ports-page" extends="observatory-element">
+<polymer-element name="ports-page">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
@@ -22,6 +20,7 @@
       <isolate-nav-menu isolate="{{ isolate }}"></isolate-nav-menu>
       <nav-menu link="{{ makeLink('/ports', isolate) }}" anchor="ports" last="{{ true }}"></nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
     <div class="content">
       <h1>Ports ({{ports.length}})</h1>
diff --git a/runtime/observatory/lib/src/elements/script_inset.dart b/runtime/observatory/lib/src/elements/script_inset.dart
index 5776bc4..d4f2899 100644
--- a/runtime/observatory/lib/src/elements/script_inset.dart
+++ b/runtime/observatory/lib/src/elements/script_inset.dart
@@ -8,7 +8,6 @@
 import 'dart:html';
 import 'dart:math';
 import 'observatory_element.dart';
-import 'nav_bar.dart';
 import 'service_ref.dart';
 import 'package:observatory/service.dart';
 import 'package:observatory/utils.dart';
@@ -984,7 +983,8 @@
       return 5;
     }
     const padding = 5;
-    const navbarHeight = NavBarElement.height;
+    // TODO (cbernaschina) check if this is needed.
+    const navbarHeight = 40;
     var rect = getBoundingClientRect();
     var buttonHeight = element.clientHeight;
     return min(max(0, navbarHeight - rect.top) + padding,
diff --git a/runtime/observatory/lib/src/elements/script_inset.html b/runtime/observatory/lib/src/elements/script_inset.html
index dd21155..c8ea9df 100644
--- a/runtime/observatory/lib/src/elements/script_inset.html
+++ b/runtime/observatory/lib/src/elements/script_inset.html
@@ -1,5 +1,5 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="observatory_element.html">
+
 
 <polymer-element name="icon-refresh" noscript>
   <template>
@@ -27,7 +27,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="script-inset" extends="observatory-element">
+<polymer-element name="script-inset">
   <template>
     <style>
       a {
diff --git a/runtime/observatory/lib/src/elements/script_ref.html b/runtime/observatory/lib/src/elements/script_ref.html
index ccbb177..7a9f0f1 100644
--- a/runtime/observatory/lib/src/elements/script_ref.html
+++ b/runtime/observatory/lib/src/elements/script_ref.html
@@ -1,8 +1,8 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="observatory_element.html">
+
 <link rel="import" href="service_ref.html">
 
-<polymer-element name="script-ref" extends="service-ref">
+<polymer-element name="script-ref">
 <template>
   <link rel="stylesheet" href="css/shared.css">
   <a on-click="{{ goto }}" title="{{ hoverText }}" _href="{{ url }}">{{ name }}</a>
diff --git a/runtime/observatory/lib/src/elements/script_view.html b/runtime/observatory/lib/src/elements/script_view.html
index e5aec18..b732128 100644
--- a/runtime/observatory/lib/src/elements/script_view.html
+++ b/runtime/observatory/lib/src/elements/script_view.html
@@ -1,10 +1,7 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="nav_bar.html">
-<link rel="import" href="observatory_element.html">
 <link rel="import" href="script_inset.html">
-<link rel="import" href="view_footer.html">
 
-<polymer-element name="script-view" extends="observatory-element">
+<polymer-element name="script-view">
 <template>
   <link rel="stylesheet" href="css/shared.css">
   <nav-bar>
@@ -14,6 +11,7 @@
     <library-nav-menu library="{{ script.library }}"></library-nav-menu>
     <nav-menu link="{{ makeLink('/inspect', script) }}" anchor="{{ script.name }}" last="{{ true }}"></nav-menu>
     <nav-refresh callback="{{ refresh }}"></nav-refresh>
+    <nav-notify notifications="{{ app.notifications }}"></nav-notify>
   </nav-bar>
 
   <div class="content-centered-big">
diff --git a/runtime/observatory/lib/src/elements/service_ref.dart b/runtime/observatory/lib/src/elements/service_ref.dart
index e9aad6d..d368713 100644
--- a/runtime/observatory/lib/src/elements/service_ref.dart
+++ b/runtime/observatory/lib/src/elements/service_ref.dart
@@ -14,7 +14,6 @@
 import 'library_ref.dart';
 import 'observatory_element.dart';
 
-@CustomTag('service-ref')
 class ServiceRefElement extends ObservatoryElement {
   @published ServiceObject ref;
   @published bool internal = false;
diff --git a/runtime/observatory/lib/src/elements/service_ref.html b/runtime/observatory/lib/src/elements/service_ref.html
index 17ce4c5..c6e8b8b 100644
--- a/runtime/observatory/lib/src/elements/service_ref.html
+++ b/runtime/observatory/lib/src/elements/service_ref.html
@@ -1,13 +1,9 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="observatory_element.html">
 
-<polymer-element name="service-ref" extends="observatory-element">
+<polymer-element name="any-service-ref">
 </polymer-element>
 
-<polymer-element name="any-service-ref" extends="observatory-element">
-</polymer-element>
-
-<polymer-element name="object-ref" extends="service-ref">
+<polymer-element name="object-ref">
   <template><link rel="stylesheet" href="css/shared.css">
 
     <template if="{{ ref.isObjectPool }}">
diff --git a/runtime/observatory/lib/src/elements/service_view.html b/runtime/observatory/lib/src/elements/service_view.html
index 723248f..3ddbbe4 100644
--- a/runtime/observatory/lib/src/elements/service_view.html
+++ b/runtime/observatory/lib/src/elements/service_view.html
@@ -11,16 +11,15 @@
 <link rel="import" href="instance_view.html">
 <link rel="import" href="library_view.html">
 <link rel="import" href="heap_snapshot.html">
-<link rel="import" href="observatory_element.html">
+
 <link rel="import" href="script_view.html">
 <link rel="import" href="vm_view.html">
-<link rel="import" href="view_footer.html">
-<polymer-element name="service-view" extends="observatory-element">
+<polymer-element name="service-view">
   <!-- This element explicitly manages the child elements to avoid setting
        an observable property on the old element to an invalid type. -->
 </polymer-element>
 
-<polymer-element name="trace-view" extends="observatory-element">
+<polymer-element name="trace-view">
    <template>
     <link rel="stylesheet" href="css/shared.css">
 
@@ -48,7 +47,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="map-viewer" extends="observatory-element">
+<polymer-element name="map-viewer">
   <template>
     <link rel="stylesheet" href="css/shared.css">
 
@@ -80,7 +79,7 @@
   </template>
 </polymer-element>
 
-<polymer-element name="list-viewer" extends="observatory-element">
+<polymer-element name="list-viewer">
   <template>
     <link rel="stylesheet" href="css/shared.css">
 
diff --git a/runtime/observatory/lib/src/elements/shims/binding.dart b/runtime/observatory/lib/src/elements/shims/binding.dart
new file mode 100644
index 0000000..5e37609
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/shims/binding.dart
@@ -0,0 +1,61 @@
+// 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 'dart:core';
+import 'dart:html';
+import 'dart:js';
+import 'dart:mirrors';
+import 'package:js/js.dart';
+import 'package:js_util/js_util.dart';
+import 'package:polymer/polymer.dart';
+
+class Binding {
+  final String attribute;
+  final String property;
+  const Binding (attribute, [String property])
+      : attribute = attribute,
+        property = property == null ? attribute : property;
+}
+
+///This is a temporary bridge between Polymer Bindings and the wrapper entities.
+class Binder<T extends HtmlElement> {
+  final List<Binding> attributes;
+  final callback;
+
+  Binder(List<Binding> attributes)
+      : attributes = attributes,
+        callback = _createCallback(T, attributes);
+
+  registerCallback(T element) {
+    assert(element != null);
+    setValue(element, 'bind', callback);
+  }
+
+  static _createCallback(Type T, List<Binding> attributes){
+    final target = reflectClass(T);
+    final setters = <String, Symbol>{};
+    for (Binding binding in attributes){
+      var member = target.instanceMembers[new Symbol(binding.property + '=')];
+      if (!member.isSetter)
+        throw new ArgumentError(
+          '${binding.property} is not a Setter for class $T');
+      setters[binding.attribute] = new Symbol(binding.property);
+    }
+    return allowInteropCaptureThis((_this, name, value, [other]) {
+      final setter = setters[name];
+      if (setter == null) return;
+      Bindable bindable;
+      if (identical(1, 1.0)) { // dart2js
+        bindable = getValue(getValue(value, '__dartBindable'), 'o') as Bindable;
+      } else { // vm
+        bindable = getValue(value, '__dartBindable');
+      }
+      var obj = reflect(_this);
+      obj.setField(setter, bindable.value);
+      bindable.open((value) {
+        obj.setField(setter, value);
+      });
+    });
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/sliding_checkbox.dart b/runtime/observatory/lib/src/elements/sliding_checkbox.dart
deleted file mode 100644
index 760fd11..0000000
--- a/runtime/observatory/lib/src/elements/sliding_checkbox.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library sliding_checkbox_element;
-
-import 'dart:html';
-import 'package:polymer/polymer.dart';
-
-@CustomTag('sliding-checkbox')
-class SlidingCheckboxElement extends PolymerElement {
-  SlidingCheckboxElement.created() : super.created();
-  @published bool checked;
-  @published String checkedText;
-  @published String uncheckedText;
-
-  void change(Event e, var details, Node target) {
-    CheckboxInputElement input = shadowRoot.querySelector('#slide-switch');
-    checked = input.checked;
-  }
-}
diff --git a/runtime/observatory/lib/src/elements/sliding_checkbox.html b/runtime/observatory/lib/src/elements/sliding_checkbox.html
deleted file mode 100644
index cdb4f78..0000000
--- a/runtime/observatory/lib/src/elements/sliding_checkbox.html
+++ /dev/null
@@ -1,90 +0,0 @@
-<link rel="import" href="../../../../packages/polymer/polymer.html">
-
-<polymer-element name="sliding-checkbox">
-  <template>
-    <style>
-      .switch {
-        position: relative;
-        width: 121px;
-        -webkit-user-select: none;
-        -moz-user-select: none;
-        -ms-user-select: none;
-      }
-      .hide {
-        display: none;
-      }
-      .label {
-        display: block;
-        overflow: hidden;
-        cursor: pointer;
-        border: 2px solid #999999;
-        border-radius: 15px;
-      }
-      .content {
-        width: 200%;
-        margin-left: -100%;
-        -moz-transition: margin 0.3s ease-in 0s;
-        -webkit-transition: margin 0.3s ease-in 0s;
-        -o-transition: margin 0.3s ease-in 0s;
-        transition: margin 0.3s ease-in 0s;
-      }
-      .content:before, .content:after {
-        float: left;
-        width: 50%;
-        height: 30px;
-        padding: 0;
-        line-height: 30px;
-        color: white;
-        font: 400 14px 'Montserrat', sans-serif;
-        -moz-box-sizing: border-box;
-        -webkit-box-sizing: border-box;
-        box-sizing: border-box;
-      }
-      .content:before {
-        content: {{ checkedText }};
-        padding-left: 10px;
-        background-color: #0489C3;
-      }
-      .content:after {
-        content: {{ uncheckedText }};
-        padding-right: 10px;
-        background-color: #EEEEEE;
-        color: #999999;
-        text-align: right;
-      }
-      .dot {
-        width: 14px;
-        margin: 8px;
-        background: #FFFFFF;
-        border: 2px solid #999999;
-        border-radius: 15px;
-        position: absolute;
-        top: 0;
-        bottom: 0;
-        right: 87px;
-        -moz-transition: all 0.3s ease-in 0s;
-        -webkit-transition: all 0.3s ease-in 0s;
-        -o-transition: all 0.3s ease-in 0s;
-        transition: all 0.3s ease-in 0s;
-      }
-      :checked + .label .content {
-        margin-left: 0;
-      }
-      :checked + .label .dot {
-        right: 0px;
-      }
-    </style>
-    <div class="switch">
-      <input type="checkbox"
-             class="hide"
-             id="slide-switch"
-             on-change="{{ change }}">
-      <label class="label" for="slide-switch">
-        <div class="content"></div>
-        <div class="dot"></div>
-      </label>
-    </div>
-  </template>
-</polymer-element>
-
-<script type="application/dart" src="sliding_checkbox.dart"></script>
\ No newline at end of file
diff --git a/runtime/observatory/lib/src/elements/timeline_page.html b/runtime/observatory/lib/src/elements/timeline_page.html
index 433c242..df9e0b4 100644
--- a/runtime/observatory/lib/src/elements/timeline_page.html
+++ b/runtime/observatory/lib/src/elements/timeline_page.html
@@ -1,8 +1,6 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="nav_bar.html">
-<link rel="import" href="observatory_element.html">
 
-<polymer-element name="timeline-page" extends="observatory-element">
+<polymer-element name="timeline-page">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <nav-bar>
@@ -13,6 +11,7 @@
       <nav-refresh callback="{{ clear }}" label="Clear"></nav-refresh>
       <nav-refresh callback="{{ saveTimeline }}" label="Save"></nav-refresh>
       <nav-refresh callback="{{ loadTimeline }}" label="Load"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
     <div id="control" class="content-centered-big">
       <h2>Timeline settings</h2>
diff --git a/runtime/observatory/lib/src/elements/view_footer.dart b/runtime/observatory/lib/src/elements/view_footer.dart
index a182511..7493a7a 100644
--- a/runtime/observatory/lib/src/elements/view_footer.dart
+++ b/runtime/observatory/lib/src/elements/view_footer.dart
@@ -4,10 +4,50 @@
 
 library view_footer_element;
 
-import 'package:polymer/polymer.dart';
-import 'observatory_element.dart';
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
 
-@CustomTag('view-footer')
-class ViewFooterElement extends ObservatoryElement {
-  ViewFooterElement.created() : super.created();
+class ViewFooterElement extends HtmlElement implements Renderable {
+  static const tag = const Tag<ViewFooterElement>('view-footer');
+
+  RenderingScheduler _r;
+
+  Stream<RenderedEvent<ViewFooterElement>> get onRendered => _r.onRendered;
+
+  factory ViewFooterElement({RenderingQueue queue}) {
+    ViewFooterElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    return e;
+  }
+
+  ViewFooterElement.created() : super.created() {
+    // TODO(cbernaschina) remove this when no more needed.
+    _r = new RenderingScheduler(this);
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = [];
+  }
+
+  void render() {
+    children = [
+        new AnchorElement()
+          ..href = 'https://www.dartlang.org/tools/observatory'
+          ..text = 'View documentation',
+        new AnchorElement()
+          ..href = 'https://github.com/dart-lang/sdk/issues/new?title=Observatory:&amp;body=Observatory%20Feedback'
+          ..text = 'File a bug report'
+    ];
+  }
 }
diff --git a/runtime/observatory/lib/src/elements/view_footer.html b/runtime/observatory/lib/src/elements/view_footer.html
deleted file mode 100644
index 59862b5..0000000
--- a/runtime/observatory/lib/src/elements/view_footer.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="observatory_element.html">
-
-<polymer-element name="view-footer" extends="observatory-element">
-  <template><link rel="stylesheet" href="css/shared.css">
-    <br><br><br><br>
-    <br><br><br><br>
-    <div align="right" style="padding: 1em">
-    <p>
-      <a href="https://www.dartlang.org/tools/observatory/" style="font-size:90%">
-	View documentation
-      </a>
-    </p>
-    <p>
-      <a href="https://github.com/dart-lang/sdk/issues/new?title=Observatory:&amp;body=Observatory%20Feedback" style="font-size:90%">
-        File a bug report
-      </a>
-    </p>
-   </div>
-  </template>
-</polymer-element>
-
-<script type="application/dart" src="view_footer.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/vm_connect.dart b/runtime/observatory/lib/src/elements/vm_connect.dart
index 5d42edc..37cc2a2 100644
--- a/runtime/observatory/lib/src/elements/vm_connect.dart
+++ b/runtime/observatory/lib/src/elements/vm_connect.dart
@@ -8,51 +8,10 @@
 import 'dart:html';
 
 import 'observatory_element.dart';
-import 'package:observatory/app.dart';
 import 'package:observatory/elements.dart';
 import 'package:observatory/service_html.dart';
 import 'package:polymer/polymer.dart';
 
-void _connectToVM(ObservatoryApplication app, WebSocketVMTarget target) {
-  app.vm = new WebSocketVM(target);
-}
-
-@CustomTag('vm-connect-target')
-class VMConnectTargetElement extends ObservatoryElement {
-  @published WebSocketVMTarget target;
-
-  VMConnectTargetElement.created() : super.created();
-
-  bool get isCurrentTarget {
-    if (app.vm == null) {
-      return false;
-    }
-    return (app.vm as WebSocketVM).target == target;
-  }
-
-  void connectToVm(MouseEvent event, var detail, Element node) {
-    if (event.button > 0 || event.metaKey || event.ctrlKey ||
-        event.shiftKey || event.altKey) {
-      // Not a left-click or a left-click with a modifier key:
-      // Let browser handle.
-      return;
-    }
-    event.preventDefault();
-    WebSocketVM currentVM = app.vm;
-    if ((currentVM == null) ||
-        currentVM.isDisconnected ||
-        (currentVM.target != target)) {
-      _connectToVM(app, target);
-    }
-    var href = node.attributes['href'];
-    app.locationManager.go(href);
-  }
-
-  void deleteVm(MouseEvent event, var detail, Element node) {
-    app.targets.remove(target);
-  }
-}
-
 @CustomTag('vm-connect')
 class VMConnectElement extends ObservatoryElement {
   @published String standaloneVmAddress = '';
@@ -61,7 +20,7 @@
   }
 
   void _connect(WebSocketVMTarget target) {
-    _connectToVM(app, target);
+    app.vm = new WebSocketVM(target);
     app.locationManager.goForwardingParameters('/vm');
   }
 
diff --git a/runtime/observatory/lib/src/elements/vm_connect.html b/runtime/observatory/lib/src/elements/vm_connect.html
index 0bae096..53be73d 100644
--- a/runtime/observatory/lib/src/elements/vm_connect.html
+++ b/runtime/observatory/lib/src/elements/vm_connect.html
@@ -1,34 +1,6 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="nav_bar.html">
-<link rel="import" href="observatory_element.html">
-<link rel="import" href="view_footer.html">
 
-<polymer-element name="vm-connect-target" extends="observatory-element">
-  <template>
-    <style>
-      .delete-button {
-        padding: 4px;
-        background: transparent;
-        border: none !important;
-      }
-      .delete-button:hover {
-        background: #ff0000;
-      }
-    </style>
-    <link rel="stylesheet" href="css/shared.css">
-    <span>
-      <template if="{{ isCurrentTarget }}">
-        <a on-click="{{ connectToVm }}" _href="{{ gotoLinkForwardingParameters('/vm') }}">{{ target.name }} (Connected)</a>
-      </template>
-      <template if="{{ !isCurrentTarget }}">
-        <a on-click="{{ connectToVm }}" _href="{{ gotoLinkForwardingParameters('/vm') }}">{{ target.name }}</a>
-      </template>
-      <button class="delete-button" on-click="{{ deleteVm }}">&#10006; Remove</button>
-    </span>
-  </template>
-</polymer-element>
-
-<polymer-element name="vm-connect" extends="observatory-element">
+<polymer-element name="vm-connect">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
@@ -40,6 +12,7 @@
 
     <nav-bar>
       <top-nav-menu last="{{ true }}"></top-nav-menu>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content-centered">
diff --git a/runtime/observatory/lib/src/elements/vm_connect_target.dart b/runtime/observatory/lib/src/elements/vm_connect_target.dart
new file mode 100644
index 0000000..befe6dd
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/vm_connect_target.dart
@@ -0,0 +1,101 @@
+// 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 'dart:async';
+import 'dart:html';
+import 'package:observatory/models.dart' as M show Target;
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
+
+class TargetEvent {
+  final M.Target target;
+
+  TargetEvent(this.target);
+}
+
+class VMConnectTargetElement extends HtmlElement implements Renderable{
+
+  static const tag =
+    const Tag<VMConnectTargetElement>('vm-connect-target-wrapped');
+
+  RenderingScheduler<VMConnectTargetElement> _r;
+
+  Stream<RenderedEvent<VMConnectTargetElement>> get onRendered => _r.onRendered;
+
+  final StreamController<TargetEvent> _onConnect =
+      new StreamController<TargetEvent>.broadcast();
+  Stream<TargetEvent> get onConnect => _onConnect.stream;
+  final StreamController<TargetEvent> _onDelete =
+      new StreamController<TargetEvent>.broadcast();
+  Stream<TargetEvent> get onDelete => _onDelete.stream;
+
+  M.Target _target;
+  bool _current;
+
+  M.Target get target => _target;
+  bool get current => _current;
+
+  factory VMConnectTargetElement(M.Target target, {bool current: false,
+      RenderingQueue queue}) {
+    assert(target != null);
+    assert(current != null);
+    VMConnectTargetElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._target = target;
+    e._current = current;
+    return e;
+  }
+
+  VMConnectTargetElement.created() : super.created();
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = [];
+    _r.disable(notify: true);
+  }
+
+  void connect() {
+    _connect(new TargetEvent(target));
+  }
+
+  void delete() {
+    _delete(new TargetEvent(target));
+  }
+
+  void render() {
+    children = [
+      new AnchorElement(href: Uris.vm())
+        ..text = current ? '${target.name} (Connected)' : '${target.name}'
+        ..onClick.where(_filter).map(_toEvent).listen(_connect),
+      new ButtonElement()
+        ..text = '✖ Remove' ..classes = ['delete-button']
+        ..onClick.map(_toEvent).listen(_delete)
+    ];
+  }
+
+  void _connect(TargetEvent e) {
+    _onConnect.add(e);
+  }
+
+  void _delete(TargetEvent e) {
+    _onDelete.add(e);
+  }
+
+  TargetEvent _toEvent(_) {
+    return new TargetEvent(target);
+  }
+
+  static bool _filter(MouseEvent event) {
+    return !(event.button > 0 || event.metaKey || event.ctrlKey ||
+        event.shiftKey || event.altKey);
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/vm_connect_target_wrapper.dart b/runtime/observatory/lib/src/elements/vm_connect_target_wrapper.dart
new file mode 100644
index 0000000..1034061
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/vm_connect_target_wrapper.dart
@@ -0,0 +1,77 @@
+// 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 'dart:html';
+import 'package:observatory/app.dart';
+import 'package:observatory/service_html.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/shims/binding.dart';
+import 'package:observatory/src/elements/vm_connect_target.dart';
+
+class VMConnectTargetElementWrapper extends HtmlElement {
+  static final binder = new Binder<VMConnectTargetElementWrapper>(
+    const [const Binding('target')]);
+
+  static const tag =
+    const Tag<VMConnectTargetElementWrapper>('vm-connect-target');
+
+  WebSocketVMTarget _target;
+  WebSocketVMTarget get target => _target;
+  void set target(WebSocketVMTarget target) { _target = target; render(); }
+
+  VMConnectTargetElementWrapper.created() : super.created() {
+    binder.registerCallback(this);
+    createShadowRoot();
+    render();
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    render();
+  }
+
+  void render() {
+    if (target == null) return;
+
+    shadowRoot.children = [
+      new StyleElement()
+        ..text = '''
+        vm-connect-target-wrapped > button.delete-button {
+          margin-left: 0.28em;
+          padding: 4px;
+          background: transparent;
+          border: none !important;
+        }
+
+        vm-connect-target-wrapped > button.delete-button:hover {
+          background: #ff0000;
+        }''',
+      new VMConnectTargetElement(target, current: current,
+          queue: application.queue)
+        ..onConnect.listen(connectToVm)
+        ..onDelete.listen(deleteVm)
+    ];
+  }
+
+  static ObservatoryApplication get application => ObservatoryApplication.app;
+
+  bool get current {
+    if (application.vm == null) { return false; }
+    return (application.vm as WebSocketVM).target == target;
+  }
+
+  static void connectToVm(TargetEvent event) {
+    WebSocketVM currentVM = application.vm;
+    if ((currentVM == null) ||
+        currentVM.isDisconnected ||
+        (currentVM.target != event.target)) {
+      application.vm = new WebSocketVM(event.target);
+    }
+  }
+
+  static void deleteVm(TargetEvent event) {
+    application.targets.remove(event.target);
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/vm_ref.dart b/runtime/observatory/lib/src/elements/vm_ref.dart
deleted file mode 100644
index 56fab8a..0000000
--- a/runtime/observatory/lib/src/elements/vm_ref.dart
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library vm_ref_element;
-
-import 'package:polymer/polymer.dart';
-import 'service_ref.dart';
-
-@CustomTag('vm-ref')
-class VMRefElement extends ServiceRefElement {
-  VMRefElement.created() : super.created();
-}
diff --git a/runtime/observatory/lib/src/elements/vm_ref.html b/runtime/observatory/lib/src/elements/vm_ref.html
deleted file mode 100644
index e7cb8e4..0000000
--- a/runtime/observatory/lib/src/elements/vm_ref.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="service_ref.html">
-
-<polymer-element name="vm-ref" extends="service-ref">
-  <template><link rel="stylesheet" href="css/shared.css">
-    <a on-click="{{ goto }}" _href="{{ url }}">{{ ref.name }}</a>
-  </template>
-</polymer-element>
-
-<script type="application/dart" src="vm_ref.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/vm_view.html b/runtime/observatory/lib/src/elements/vm_view.html
index 2934009..a078f04 100644
--- a/runtime/observatory/lib/src/elements/vm_view.html
+++ b/runtime/observatory/lib/src/elements/vm_view.html
@@ -1,15 +1,11 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="curly_block.html">
 <link rel="import" href="eval_box.html">
 <link rel="import" href="function_ref.html">
 <link rel="import" href="isolate_summary.html">
 <link rel="import" href="library_ref.html">
-<link rel="import" href="nav_bar.html">
-<link rel="import" href="observatory_element.html">
 <link rel="import" href="script_ref.html">
-<link rel="import" href="view_footer.html">
 
-<polymer-element name="vm-view" extends="observatory-element">
+<polymer-element name="vm-view">
   <template>
     <link rel="stylesheet" href="css/shared.css">
 
@@ -17,6 +13,7 @@
       <top-nav-menu last="{{ false }}"></top-nav-menu>
       <vm-nav-menu vm="{{ vm }}" last="{{ true }}"></vm-nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
     </nav-bar>
 
     <div class="content-centered">
diff --git a/runtime/observatory/lib/src/mocks/exceptions/connection_exception.dart b/runtime/observatory/lib/src/mocks/exceptions/connection_exception.dart
new file mode 100644
index 0000000..127cb20
--- /dev/null
+++ b/runtime/observatory/lib/src/mocks/exceptions/connection_exception.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of mocks;
+
+class ConnectionExceptionMock implements M.ConnectionException {
+  final String message;
+  const ConnectionExceptionMock({this.message});
+}
diff --git a/runtime/observatory/lib/src/mocks/objects/class.dart b/runtime/observatory/lib/src/mocks/objects/class.dart
new file mode 100644
index 0000000..33eb764
--- /dev/null
+++ b/runtime/observatory/lib/src/mocks/objects/class.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of mocks;
+
+class ClassRefMock implements M.ClassRef {
+  final String id;
+  final String name;
+  const ClassRefMock({this.id, this.name});
+}
+
+class ClassMock implements M.ClassRef {
+  final String id;
+  final String name;
+  final bool isAbstract;
+  final bool isConst;
+  final M.ClassRef superclass;
+  final Iterable<M.ClassRef> subclasses;
+  const ClassMock({this.id, this.name, this.isAbstract, this.isConst,
+      this.superclass, this.subclasses: const []});
+}
diff --git a/runtime/observatory/lib/src/mocks/objects/error.dart b/runtime/observatory/lib/src/mocks/objects/error.dart
new file mode 100644
index 0000000..8b47830
--- /dev/null
+++ b/runtime/observatory/lib/src/mocks/objects/error.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of mocks;
+
+class ErrorRefMock implements M.ErrorRef {
+  final String id;
+  final M.ErrorKind kind;
+  final String message;
+  const ErrorRefMock({this.id, this.kind, this.message});
+}
+
+class ErrorMock implements M.Error {
+  final String id;
+  final M.ErrorKind kind;
+  final String message;
+  final int size;
+  const ErrorMock({this.id, this.kind, this.message, this.size});
+}
diff --git a/runtime/observatory/lib/src/mocks/objects/event.dart b/runtime/observatory/lib/src/mocks/objects/event.dart
new file mode 100644
index 0000000..6a646f3
--- /dev/null
+++ b/runtime/observatory/lib/src/mocks/objects/event.dart
@@ -0,0 +1,142 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of mocks;
+
+class VMUpdateEventMock implements M.VMUpdateEvent {
+  final M.VMRef vm;
+  final DateTime timestamp;
+  const VMUpdateEventMock({this.timestamp, this.vm});
+}
+class IsolateStartEventMock implements M.IsolateStartEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  const IsolateStartEventMock({this.timestamp, this.isolate});
+}
+class IsolateRunnableEventMock implements M.IsolateRunnableEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  const IsolateRunnableEventMock({this.timestamp, this.isolate});
+}
+class IsolateExitEventMock implements M.IsolateExitEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  const IsolateExitEventMock({this.timestamp, this.isolate});
+}
+class IsolateUpdateEventMock implements M.IsolateUpdateEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  const IsolateUpdateEventMock({this.timestamp, this.isolate});
+}
+class IsolateRealodEventMock implements M.IsolateReloadEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final M.Error error;
+  const IsolateRealodEventMock({this.timestamp, this.isolate, this.error});
+}
+class ServiceExtensionAddedEventMock implements M.ServiceExtensionAddedEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final String extensionRPC;
+  const ServiceExtensionAddedEventMock({this.extensionRPC, this.isolate,
+      this.timestamp});
+}
+class PauseStartEventMock implements M.PauseStartEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  const PauseStartEventMock({this.isolate, this.timestamp});
+}
+class PauseExitEventMock implements M.PauseExitEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  const PauseExitEventMock({this.isolate, this.timestamp});
+}
+class PauseBreakpointEventMock implements M.PauseBreakpointEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final M.Breakpoint breakpoint;
+  final List<M.Breakpoint> pauseBreakpoints;
+  final M.Frame topFrame;
+  final bool atAsyncSuspension;
+  const PauseBreakpointEventMock({this.timestamp, this.isolate, this.breakpoint,
+      this.pauseBreakpoints, this.topFrame, this.atAsyncSuspension});
+}
+class PauseInterruptedEventMock implements M.PauseInterruptedEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final M.Frame topFrame;
+  final bool atAsyncSuspension;
+  const PauseInterruptedEventMock({this.timestamp, this.isolate, this.topFrame,
+      this.atAsyncSuspension});
+}
+class PauseExceptionEventMock implements M.PauseExceptionEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final M.Frame topFrame;
+  final M.InstanceRef exception;
+  const PauseExceptionEventMock({this.timestamp, this.isolate, this.topFrame,
+      this.exception});
+}
+class ResumeEventMock implements M.ResumeEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  const ResumeEventMock({this.timestamp, this.isolate});
+}
+class BreakpointAddedEventMock implements M.BreakpointAddedEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final M.Breakpoint breakpoint;
+  const BreakpointAddedEventMock({this.timestamp, this.isolate,
+      this.breakpoint});
+}
+class BreakpointResolvedEventMock implements M.BreakpointResolvedEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final M.Breakpoint breakpoint;
+  const BreakpointResolvedEventMock({this.timestamp, this.isolate,
+      this.breakpoint});
+}
+class BreakpointRemovedEventMock implements M.BreakpointRemovedEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final M.Breakpoint breakpoint;
+  const BreakpointRemovedEventMock({this.timestamp, this.isolate,
+      this.breakpoint});
+}
+class InspectEventMock implements M.InspectEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final M.InstanceRef inspectee;
+  const InspectEventMock({this.timestamp, this.isolate, this.inspectee});
+}
+class NoneEventMock implements M.NoneEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  const NoneEventMock({this.timestamp, this.isolate});
+}
+class GCEventMock implements M.GCEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  const GCEventMock({this.timestamp, this.isolate});
+}
+class ExtensionEventMock implements M.ExtensionEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final String extensionKind;
+  final M.ExtensionData extensionData;
+  const ExtensionEventMock({this.timestamp, this.isolate, this.extensionKind,
+      this.extensionData});
+}
+class TimelineEventsEventMock implements M.TimelineEventsEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final List<M.TimelineEvent> timelineEvents;
+  const TimelineEventsEventMock({this.timestamp, this.isolate,
+      this.timelineEvents});
+}
+class ConnectionClockedEventMock implements M.ConnectionClosedEvent {
+  final DateTime timestamp;
+  final String reason;
+  const ConnectionClockedEventMock({this.timestamp, this.reason});
+}
diff --git a/runtime/observatory/lib/src/mocks/objects/isolate.dart b/runtime/observatory/lib/src/mocks/objects/isolate.dart
new file mode 100644
index 0000000..9f5ba80
--- /dev/null
+++ b/runtime/observatory/lib/src/mocks/objects/isolate.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of mocks;
+
+class IsolateRefMock implements M.IsolateRef {
+  final String id;
+  final int number;
+  final String name;
+
+  const IsolateRefMock({this.id, this.number, this.name});
+}
+
+class IsolateMock implements M.Isolate {
+  final String id;
+  final int number;
+  final String name;
+  final DateTime startTime;
+  final bool runnable;
+
+  const IsolateMock({this.id, this.number, this.name, this.startTime,
+      this.runnable});
+  // TODO(cbernaschina) add other properties.
+}
diff --git a/runtime/observatory/lib/src/mocks/objects/library.dart b/runtime/observatory/lib/src/mocks/objects/library.dart
new file mode 100644
index 0000000..2932efa
--- /dev/null
+++ b/runtime/observatory/lib/src/mocks/objects/library.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of mocks;
+
+class LibraryRefMock implements M.LibraryRef {
+  final String id;
+  final String name;
+  final String uri;
+  const LibraryRefMock({this.id, this.name, this.uri});
+}
+
+class LibraryMock implements M.Library {
+  final String id;
+  final String name;
+  final String uri;
+  final bool debuggable;
+  final Iterable<M.ScriptRef> scripts;
+  final Iterable<M.ClassRef> classes;
+  const LibraryMock({this.id, this.name, this.uri, this.debuggable,
+      this.scripts: const [], this.classes: const []});
+}
diff --git a/runtime/observatory/lib/src/mocks/objects/notification.dart b/runtime/observatory/lib/src/mocks/objects/notification.dart
new file mode 100644
index 0000000..68bfd75
--- /dev/null
+++ b/runtime/observatory/lib/src/mocks/objects/notification.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of mocks;
+
+class ExceptionNotificationMock implements M.ExceptionNotification {
+  final Exception exception;
+  final StackTrace stacktrace;
+  const ExceptionNotificationMock({this.exception, this.stacktrace});
+}
+
+class EventNotificationMock implements M.EventNotification {
+  final M.Event event;
+  const EventNotificationMock({this.event});
+}
diff --git a/runtime/observatory/lib/src/mocks/objects/script.dart b/runtime/observatory/lib/src/mocks/objects/script.dart
new file mode 100644
index 0000000..bb264dc
--- /dev/null
+++ b/runtime/observatory/lib/src/mocks/objects/script.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of mocks;
+
+class ScriptRefMock implements M.ScriptRef {
+  final String id;
+  final String uri;
+  const ScriptRefMock({this.id, this.uri});
+}
+
+typedef int TokenToInt(int token);
+
+class ScriptMock implements M.Script {
+  final String id;
+  final int size;
+  final String uri;
+  final String source;
+
+  final TokenToInt _tokenToLine;
+  final TokenToInt _tokenToCol;
+
+  int tokenToLine(int token) => _tokenToLine(token);
+  int tokenToCol(int token) => _tokenToCol(token);
+
+  const ScriptMock({this.id, this.size, this.uri, this.source,
+      TokenToInt tokenToLine, TokenToInt tokenToCol})
+    : _tokenToLine = tokenToLine,
+      _tokenToCol = tokenToCol;
+}
diff --git a/runtime/observatory/lib/src/mocks/objects/source_location.dart b/runtime/observatory/lib/src/mocks/objects/source_location.dart
new file mode 100644
index 0000000..481b44b
--- /dev/null
+++ b/runtime/observatory/lib/src/mocks/objects/source_location.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of mocks;
+
+class SourceLocationMock implements M.SourceLocation {
+  final M.ScriptRef script;
+  final int tokenPos;
+  final int endTokenPos;
+  const SourceLocationMock({this.script, this.tokenPos, this.endTokenPos});
+}
diff --git a/runtime/observatory/lib/src/mocks/objects/target.dart b/runtime/observatory/lib/src/mocks/objects/target.dart
new file mode 100644
index 0000000..c5ae189
--- /dev/null
+++ b/runtime/observatory/lib/src/mocks/objects/target.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of mocks;
+
+class TargetMock implements M.Target {
+  final String name;
+  const TargetMock({this.name});
+}
diff --git a/runtime/observatory/lib/src/mocks/objects/vm.dart b/runtime/observatory/lib/src/mocks/objects/vm.dart
new file mode 100644
index 0000000..a58272e
--- /dev/null
+++ b/runtime/observatory/lib/src/mocks/objects/vm.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of mocks;
+
+class VMRefMock implements M.VMRef {
+  final String name;
+  const VMRefMock({this.name});
+}
+
+class VMMock implements M.VM {
+  final String name;
+  final int architectureBits;
+  final String targetCPU;
+  final String hostCPU;
+  final String version;
+  final int pid;
+  final DateTime startTime;
+  final Iterable<M.IsolateRef> isolates;
+  const VMMock({this.name, this.architectureBits, this.targetCPU, this.hostCPU,
+      this.version, this.pid, this.startTime, this.isolates : const []});
+}
diff --git a/runtime/observatory/lib/src/mocks/repositories/notification.dart b/runtime/observatory/lib/src/mocks/repositories/notification.dart
new file mode 100644
index 0000000..cf7f2b9
--- /dev/null
+++ b/runtime/observatory/lib/src/mocks/repositories/notification.dart
@@ -0,0 +1,58 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of mocks;
+
+class NotificationChangeEventMock implements M.NotificationChangeEvent {
+  final NotificationRepositoryMock repository;
+  const NotificationChangeEventMock({this.repository});
+}
+
+typedef void NotificationRepositoryMockCallback(M.Notification notification);
+
+class NotificationRepositoryMock implements M.NotificationRepository {
+  final StreamController<M.NotificationChangeEvent> _onChange =
+      new StreamController<M.NotificationChangeEvent>.broadcast();
+  Stream<M.NotificationChangeEvent> get onChange => _onChange.stream;
+
+  bool get hasListeners => _onChange.hasListener;
+
+  final Iterable<M.Notification> _list;
+  final NotificationRepositoryMockCallback _add;
+  final NotificationRepositoryMockCallback _delete;
+
+  bool addInvoked = false;
+  bool listInvoked = false;
+  bool deleteInvoked = false;
+  bool deleteAllInvoked = false;
+
+
+  void add(M.Notification notification) {
+    addInvoked = true;
+    if (_add != null) _add(notification);
+  }
+
+  Iterable<M.Notification> list() {
+    listInvoked = true;
+    return _list;
+  }
+
+  void delete(M.Notification notification) {
+    deleteInvoked = true;
+    if (_add != null) _delete(notification);
+  }
+
+  void deleteAll() { deleteAllInvoked = true; }
+
+  void triggerChangeEvent() {
+    _onChange.add(new NotificationChangeEventMock(repository: this));
+  }
+
+  NotificationRepositoryMock({Iterable<M.Notification> list : const [],
+      NotificationRepositoryMockCallback add,
+      NotificationRepositoryMockCallback delete})
+    : _list = list,
+      _add = add,
+      _delete = delete;
+}
diff --git a/runtime/observatory/lib/src/models/exceptions.dart b/runtime/observatory/lib/src/models/exceptions.dart
new file mode 100644
index 0000000..871c095
--- /dev/null
+++ b/runtime/observatory/lib/src/models/exceptions.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class BasicException implements Exception {
+  String get message;
+}
+
+abstract class ConnectionException implements BasicException {}
+
+abstract class ResponseException implements BasicException {}
+
+abstract class RequestException implements BasicException {}
+
+abstract class ParseErrorException implements RequestException {}
+
+abstract class InvalidRequestException implements RequestException {}
+
+abstract class MethodNotFoundException implements RequestException {}
+
+abstract class InvalidParamsException implements RequestException {}
+
+abstract class InternalErrorException implements RequestException {}
+
+abstract class FeatureDisabledException implements RequestException {}
+
+abstract class CannotAddBreakpointException implements RequestException {}
+
+abstract class StreamAlreadySubscribedException implements RequestException {}
+
+abstract class StreamNotSubscribedException implements RequestException {}
+
+abstract class IsolateMustBeRunnableException implements RequestException {}
+
+abstract class IsolateMustBePausedException implements RequestException {}
+
+abstract class IsolateIsReloadingException implements RequestException {}
+
+abstract class FileSystemAlreadyExistsException implements RequestException {}
+
+abstract class FileSystemDoesNotExistException implements RequestException {}
+
+abstract class FileDoesNotExistException implements RequestException {}
+
+abstract class IsolateReloadFailedException implements RequestException {}
+
+abstract class UnknownException implements RequestException {}
diff --git a/runtime/observatory/lib/src/models/objects/breakpoint.dart b/runtime/observatory/lib/src/models/objects/breakpoint.dart
new file mode 100644
index 0000000..e5e9324
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/breakpoint.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class Breakpoint extends Object {
+  /// A number identifying this breakpoint to the user.
+  int get number;
+
+  /// Has this breakpoint been assigned to a specific program location?
+  bool get resolved;
+}
diff --git a/runtime/observatory/lib/src/models/objects/class.dart b/runtime/observatory/lib/src/models/objects/class.dart
new file mode 100644
index 0000000..a2a9007
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/class.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class ClassRef extends ObjectRef {
+  /// The name of this class.
+  String get name;
+}
+
+abstract class Class extends ObjectRef implements ClassRef {
+  /// The error which occurred during class finalization, if it exists.
+  /// [optional]
+  ErrorRef get error;
+
+  /// Is this an abstract class?
+  bool get isAbstract;
+
+  /// Is this a const class?
+  bool get isConst;
+
+  /// The library which contains this class.
+  LibraryRef get library;
+
+  /// The location of this class in the source code.[optional]
+  SourceLocation get location;
+
+  /// The superclass of this class, if any. [optional]
+  ClassRef get superclass;
+
+  /// The supertype for this class, if any.
+  ///
+  /// The value will be of the kind: Type. [optional]
+  InstanceRef get superType;
+
+  /// A list of interface types for this class.
+  ///
+  /// The values will be of the kind: Type.
+  Iterable<InstanceRef> get interfaces;
+
+  /// The mixin type for this class, if any.
+  ///
+  /// The value will be of the kind: Type. [optional]
+  Iterable<InstanceRef> get mixin;
+
+  /// A list of fields in this class. Does not include fields from
+  /// superclasses.
+  //List<FieldRef> get fields;
+
+  /// A list of functions in this class. Does not include functions
+  /// from superclasses.
+  //List<FunctionRef> get functions;
+
+  // A list of subclasses of this class.
+  Iterable<ClassRef> get subclasses;
+}
diff --git a/runtime/observatory/lib/src/models/objects/error.dart b/runtime/observatory/lib/src/models/objects/error.dart
new file mode 100644
index 0000000..b5d1bbd
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/error.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+enum ErrorKind {
+  /// The isolate has encountered an unhandled Dart exception.
+  UnhandledException,
+  /// The isolate has encountered a Dart language error in the program.
+  LanguageError,
+  /// The isolate has encounted an internal error. These errors should be
+  /// reported as bugs.
+  InternalError,
+  /// The isolate has been terminated by an external source.
+  TerminationError
+}
+
+abstract class ErrorRef extends ObjectRef {
+  String get id;
+  ErrorKind get kind;
+  String get message;
+}
+
+abstract class Error extends Object implements ErrorRef {
+
+}
diff --git a/runtime/observatory/lib/src/models/objects/event.dart b/runtime/observatory/lib/src/models/objects/event.dart
new file mode 100644
index 0000000..aff1946
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/event.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class Event {
+  DateTime get timestamp;
+  static bool isPauseEvent(Event event) {
+    return event is PauseStartEvent || event is PauseExitEvent ||
+        event is PauseBreakpointEvent || event is PauseInterruptedEvent ||
+        event is PauseExceptionEvent || event is NoneEvent;
+  }
+}
+abstract class VMEvent extends Event {
+  VMRef get vm;
+}
+abstract class VMUpdateEvent extends VMEvent {}
+abstract class IsolateEvent extends Event {
+  IsolateRef get isolate;
+}
+abstract class IsolateStartEvent extends IsolateEvent {}
+abstract class IsolateRunnableEvent extends IsolateEvent {}
+abstract class IsolateExitEvent extends IsolateEvent {}
+abstract class IsolateUpdateEvent extends IsolateEvent {}
+abstract class IsolateReloadEvent extends IsolateEvent {
+  ErrorRef get error;
+}
+abstract class ServiceExtensionAddedEvent extends IsolateEvent {
+  String get extensionRPC;
+}
+abstract class DebugEvent extends IsolateEvent {}
+abstract class PauseStartEvent extends DebugEvent {}
+abstract class PauseExitEvent extends DebugEvent {}
+abstract class PauseBreakpointEvent extends DebugEvent {
+  /// [optional]
+  Breakpoint get breakpoint;
+  Iterable<Breakpoint> get pauseBreakpoints;
+  Frame get topFrame;
+  bool get atAsyncSuspension;
+}
+abstract class PauseInterruptedEvent extends DebugEvent {
+  Frame get topFrame;
+  bool get atAsyncSuspension;
+}
+abstract class PauseExceptionEvent extends DebugEvent {
+  Frame get topFrame;
+  InstanceRef get exception;
+}
+abstract class ResumeEvent extends DebugEvent {}
+abstract class BreakpointAddedEvent extends DebugEvent {
+  Breakpoint get breakpoint;
+}
+abstract class BreakpointResolvedEvent extends DebugEvent {
+  Breakpoint get breakpoint;
+}
+abstract class BreakpointRemovedEvent extends DebugEvent {
+  Breakpoint get breakpoint;
+}
+abstract class InspectEvent extends DebugEvent {
+  InstanceRef get inspectee;
+}
+abstract class NoneEvent extends DebugEvent {}
+abstract class GCEvent extends IsolateEvent {}
+abstract class ExtensionEvent extends Event {
+  IsolateRef get isolate;
+  String get extensionKind;
+  ExtensionData get extensionData;
+}
+abstract class TimelineEventsEvent extends IsolateEvent {
+  Iterable<TimelineEvent> get timelineEvents;
+}
+abstract class ConnectionClosedEvent extends Event {
+  String get reason;
+}
diff --git a/runtime/observatory/lib/src/models/objects/extension_data.dart b/runtime/observatory/lib/src/models/objects/extension_data.dart
new file mode 100644
index 0000000..5000a9b
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/extension_data.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class ExtensionData implements Map<String, dynamic> {}
diff --git a/runtime/observatory/lib/src/models/objects/frame.dart b/runtime/observatory/lib/src/models/objects/frame.dart
new file mode 100644
index 0000000..d8e87cd
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/frame.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class Frame {}
diff --git a/runtime/observatory/lib/src/models/objects/instance.dart b/runtime/observatory/lib/src/models/objects/instance.dart
new file mode 100644
index 0000000..b337f79
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/instance.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class InstanceRef extends ObjectRef {}
diff --git a/runtime/observatory/lib/src/models/objects/isolate.dart b/runtime/observatory/lib/src/models/objects/isolate.dart
new file mode 100644
index 0000000..007a6f4
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/isolate.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class IsolateRef {
+  String get id;
+  int get number;
+  String get name;
+}
+
+abstract class Isolate extends IsolateRef {
+  DateTime get startTime;
+  bool get runnable;
+}
diff --git a/runtime/observatory/lib/src/models/objects/library.dart b/runtime/observatory/lib/src/models/objects/library.dart
new file mode 100644
index 0000000..6543ef9
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/library.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
+
+part of models;
+
+abstract class LibraryRef extends ObjectRef {
+  /// The name of this library.
+  String get name;
+
+  /// The uri of this library.
+  String get uri;
+}
+
+abstract class Library extends Object implements LibraryRef {
+  /// Is this library debuggable? Default true.
+  bool get debuggable;
+
+  /// A list of the imports for this library.
+  //LibraryDependency[] dependencies;
+
+  // A list of the scripts which constitute this library.
+  Iterable<ScriptRef> get scripts;
+
+  // A list of the top-level variables in this library.
+  //List<FieldRef> get variables;
+
+  // A list of the top-level functions in this library.
+  //List<FunctionRef> get functions;
+
+  // A list of all classes in this library.
+  Iterable<ClassRef> get classes;
+}
diff --git a/runtime/observatory/lib/src/models/objects/notification.dart b/runtime/observatory/lib/src/models/objects/notification.dart
new file mode 100644
index 0000000..9a9f8af
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/notification.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class Notification {}
+
+abstract class ExceptionNotification implements Notification{
+  Exception get exception;
+  /// [optional]
+  StackTrace get stacktrace;
+}
+
+abstract class EventNotification implements Notification{
+  Event get event;
+}
diff --git a/runtime/observatory/lib/src/models/objects/object.dart b/runtime/observatory/lib/src/models/objects/object.dart
new file mode 100644
index 0000000..76b2393
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/object.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class ObjectRef {
+  /// A unique identifier for an Object.
+  String get id;
+}
+
+abstract class Object implements ObjectRef {}
diff --git a/runtime/observatory/lib/src/models/objects/script.dart b/runtime/observatory/lib/src/models/objects/script.dart
new file mode 100644
index 0000000..274fb08
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/script.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class ScriptRef extends ObjectRef {
+  /// The uri from which this script was loaded.
+  String get uri;
+}
+
+abstract class Script extends Object implements ScriptRef {
+  /// The library which owns this script.
+  // LibraryRef get library;
+
+  /// The source code for this script. For certain built-in scripts,
+  /// this may be reconstructed without source comments.
+  String get source;
+
+  int tokenToLine(int token);
+  int tokenToCol(int token);
+}
diff --git a/runtime/observatory/lib/src/models/objects/source_location.dart b/runtime/observatory/lib/src/models/objects/source_location.dart
new file mode 100644
index 0000000..5d35d57
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/source_location.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class SourceLocation {
+  /// The script containing the source location.
+  ScriptRef get script;
+  /// The first token of the location.
+  int get tokenPos;
+  /// The last token of the location if this is a range. [optional]
+  int get endTokenPos;
+}
diff --git a/runtime/observatory/lib/src/models/objects/target.dart b/runtime/observatory/lib/src/models/objects/target.dart
new file mode 100644
index 0000000..f2a1658
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/target.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class Target {
+  String get name;
+}
diff --git a/runtime/observatory/lib/src/models/objects/timeline_event.dart b/runtime/observatory/lib/src/models/objects/timeline_event.dart
new file mode 100644
index 0000000..6cac6d1
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/timeline_event.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class TimelineEvent implements Map<String, dynamic> {}
diff --git a/runtime/observatory/lib/src/models/objects/vm.dart b/runtime/observatory/lib/src/models/objects/vm.dart
new file mode 100644
index 0000000..051a9fa
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/vm.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class VMRef {
+  String get name;
+}
+
+abstract class VM implements VMRef {
+  /// Word length on target architecture (e.g. 32, 64).
+  int get architectureBits;
+
+  /// The CPU we are generating code for.
+  String get targetCPU;
+
+  /// The CPU we are actually running on.
+  String get hostCPU;
+
+  /// The Dart VM version string.
+  String get version;
+
+  /// The process id for the VM.
+  int get pid;
+
+  /// The time that the VM started in milliseconds since the epoch.
+  ///
+  /// Suitable to pass to DateTime.fromMillisecondsSinceEpoch.
+  DateTime get startTime;
+
+  // A list of isolates running in the VM.
+  Iterable<IsolateRef> get isolates;
+}
diff --git a/runtime/observatory/lib/src/models/repositories/notification.dart b/runtime/observatory/lib/src/models/repositories/notification.dart
new file mode 100644
index 0000000..9ab3543
--- /dev/null
+++ b/runtime/observatory/lib/src/models/repositories/notification.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class NotificationChangeEvent {
+  NotificationRepository get repository;
+}
+
+abstract class NotificationRepository {
+  Stream<NotificationChangeEvent> get onChange;
+  Iterable<Notification> list();
+  void delete(Notification);
+  void deleteAll();
+}
diff --git a/runtime/observatory/lib/src/repositories/notification.dart b/runtime/observatory/lib/src/repositories/notification.dart
new file mode 100644
index 0000000..348dbca
--- /dev/null
+++ b/runtime/observatory/lib/src/repositories/notification.dart
@@ -0,0 +1,72 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class NotificationChangeEvent implements M.NotificationChangeEvent {
+  final NotificationRepository repository;
+  NotificationChangeEvent(this.repository);
+}
+
+class NotificationRepository implements M.NotificationRepository {
+  final List<M.Notification> _list = new List<M.Notification>();
+
+  final StreamController<M.NotificationChangeEvent> _onChange =
+      new StreamController<M.NotificationChangeEvent>.broadcast();
+  Stream<M.NotificationChangeEvent> get onChange => _onChange.stream;
+
+  void add(M.Notification notification) {
+    assert(notification != null);
+    _list.add(notification);
+    _notify();
+  }
+
+  Iterable<M.Notification> list() => _list;
+
+  void delete(M.Notification notification) {
+    if (_list.remove(notification))
+    _notify();
+  }
+
+  void deleteAll() {
+    if (_list.isNotEmpty) {
+      _list.clear();
+      _notify();
+    }
+  }
+
+  NotificationRepository();
+
+  void _notify() {
+    _onChange.add(new NotificationChangeEvent(this));
+  }
+
+  void deleteWhere(bool test(M.Notification element)) {
+    int length = _list.length;
+    _list.removeWhere(test);
+    if (_list.length != length) _notify();
+  }
+
+  void deletePauseEvents({M.Isolate isolate}) {
+    if (isolate == null) {
+      deleteWhere((notification) {
+        return notification is M.EventNotification &&
+               M.Event.isPauseEvent(notification.event);
+      });
+    } else {
+      deleteWhere((notification) {
+        return notification is M.EventNotification &&
+               M.Event.isPauseEvent(notification.event) &&
+               notification.event.isolate == isolate;
+      });
+    }
+  }
+
+  void deleteDisconnectEvents() {
+    deleteWhere((notification) {
+      return notification is M.EventNotification &&
+             notification.event is M.ConnectionClosedEvent;
+    });
+  }
+}
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index 18d29bf..85574fe 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -22,14 +22,14 @@
 
 /// An RpcException represents an exceptional event that happened
 /// while invoking an rpc.
-abstract class RpcException implements Exception {
+abstract class RpcException implements Exception, M.BasicException {
   RpcException(this.message);
 
   String message;
 }
 
 /// A ServerRpcException represents an error returned by the VM.
-class ServerRpcException extends RpcException {
+class ServerRpcException extends RpcException implements M.RequestException {
   /// A list of well-known server error codes.
   static const kParseError     = -32700;
   static const kInvalidRequest = -32600;
@@ -70,7 +70,8 @@
 
 /// A NetworkRpcException is used to indicate that an rpc has
 /// been canceled due to network error.
-class NetworkRpcException extends RpcException {
+class NetworkRpcException extends RpcException
+                          implements M.ConnectionException {
   NetworkRpcException(String message) : super(message);
 
   String toString() => 'NetworkRpcException(${message})';
@@ -424,7 +425,8 @@
 }
 
 /// A [SourceLocation] represents a location or range in the source code.
-class SourceLocation extends ServiceObject implements Location {
+class SourceLocation extends ServiceObject implements Location,
+                                                          M.SourceLocation {
   Script script;
   int tokenPos;
   int endTokenPos;
@@ -603,7 +605,7 @@
 }
 
 /// State for a VM being inspected.
-abstract class VM extends ServiceObjectOwner {
+abstract class VM extends ServiceObjectOwner implements M.VM {
   @reflectable VM get vm => this;
   @reflectable Isolate get isolate => null;
 
@@ -622,6 +624,7 @@
   final ObservableList<Isolate> isolates = new ObservableList<Isolate>();
 
   @observable String version = 'unknown';
+  @observable String hostCPU;
   @observable String targetCPU;
   @observable int architectureBits;
   @observable bool assertsEnabled = false;
@@ -896,6 +899,7 @@
 
     _loaded = true;
     version = map['version'];
+    hostCPU = map['hostCPU'];
     targetCPU = map['targetCPU'];
     architectureBits = map['architectureBits'];
     int startTimeMillis = map['startTime'];
@@ -1117,7 +1121,7 @@
 }
 
 /// State for a running isolate.
-class Isolate extends ServiceObjectOwner {
+class Isolate extends ServiceObjectOwner implements M.Isolate {
   static const kLoggingStream = '_Logging';
   static const kExtensionStream = 'Extension';
 
@@ -1451,7 +1455,11 @@
 
     updateHeapsFromMap(map['_heaps']);
     _updateBreakpoints(map['breakpoints']);
-    exceptionsPauseInfo = map['_debuggerSettings']['_exceptions'];
+    if (map['_debuggerSettings'] != null) {
+      exceptionsPauseInfo = map['_debuggerSettings']['_exceptions'];
+    } else {
+      exceptionsPauseInfo = "none";
+    }
 
     var newPauseEvent = map['pauseEvent'];
     assert((pauseEvent == null) ||
@@ -1886,6 +1894,7 @@
   static const kIsolateExit            = 'IsolateExit';
   static const kIsolateUpdate          = 'IsolateUpdate';
   static const kIsolateReload          = 'IsolateReload';
+  static const kIsolateSpawn           = 'IsolateSpawn';
   static const kServiceExtensionAdded  = 'ServiceExtensionAdded';
   static const kPauseStart             = 'PauseStart';
   static const kPauseExit              = 'PauseExit';
@@ -1929,6 +1938,8 @@
   @observable String extensionKind;
   @observable Map extensionData;
   @observable List timelineEvents;
+  @observable String spawnToken;
+  @observable String spawnError;
 
   int chunkIndex, chunkCount, nodeCount;
 
@@ -2011,6 +2022,12 @@
     if (map['timelineEvents'] != null) {
       timelineEvents = map['timelineEvents'];
     }
+    if (map['spawnToken'] != null) {
+      spawnToken = map['spawnToken'];
+    }
+    if (map['spawnError'] != null) {
+      spawnError = map['spawnError'];
+    }
   }
 
   String toString() {
@@ -2025,7 +2042,7 @@
   }
 }
 
-class Breakpoint extends ServiceObject {
+class Breakpoint extends ServiceObject implements M.Breakpoint {
   Breakpoint._empty(ServiceObjectOwner owner) : super._empty(owner);
 
   // TODO(turnidge): Add state to track if a breakpoint has been
@@ -2121,7 +2138,7 @@
 }
 
 
-class Library extends HeapObject {
+class Library extends HeapObject implements M.LibraryRef {
   @observable String uri;
   @reflectable final dependencies = new ObservableList<LibraryDependency>();
   @reflectable final scripts = new ObservableList<Script>();
@@ -2223,7 +2240,7 @@
   bool get empty => accumulated.empty && current.empty;
 }
 
-class Class extends HeapObject {
+class Class extends HeapObject implements M.ClassRef {
   @observable Library library;
 
   @observable bool isAbstract;
@@ -2918,7 +2935,7 @@
   LocalVarLocation(this.line, this.column, this.endColumn);
 }
 
-class Script extends HeapObject {
+class Script extends HeapObject implements M.Script {
   final lines = new ObservableList<ScriptLine>();
   @observable String uri;
   @observable String kind;
@@ -2929,6 +2946,8 @@
   @observable int columnOffset;
   @observable Library library;
 
+  String source;
+
   bool get immutable => true;
 
   String _shortUri;
@@ -3030,6 +3049,7 @@
     lineOffset = map['lineOffset'];
     columnOffset = map['columnOffset'];
     _parseTokenPosTable(map['tokenPosTable']);
+    source = map['source'];
     _processSource(map['source']);
     library = map['library'];
   }
@@ -3987,7 +4007,7 @@
   }
 }
 
-class Frame extends ServiceObject {
+class Frame extends ServiceObject implements M.Frame {
   @observable int index;
   @observable ServiceFunction function;
   @observable SourceLocation location;
diff --git a/runtime/observatory/observatory_sources.gypi b/runtime/observatory/observatory_sources.gypi
index c2084e1..30659e0 100644
--- a/runtime/observatory/observatory_sources.gypi
+++ b/runtime/observatory/observatory_sources.gypi
@@ -11,7 +11,10 @@
     'lib/debugger.dart',
     'lib/elements.dart',
     'lib/elements.html',
+    'lib/mocks.dart',
+    'lib/models.dart',
     'lib/object_graph.dart',
+    'lib/repositories.dart',
     'lib/service.dart',
     'lib/service_common.dart',
     'lib/service_html.dart',
@@ -19,6 +22,7 @@
     'lib/src/app/analytics.dart',
     'lib/src/app/application.dart',
     'lib/src/app/location_manager.dart',
+    'lib/src/app/notification.dart',
     'lib/src/app/page.dart',
     'lib/src/app/settings.dart',
     'lib/src/app/target_manager.dart',
@@ -47,7 +51,7 @@
     'lib/src/elements/cpu_profile.html',
     'lib/src/elements/css/shared.css',
     'lib/src/elements/curly_block.dart',
-    'lib/src/elements/curly_block.html',
+    'lib/src/elements/curly_block_wrapper.dart',
     'lib/src/elements/debugger.dart',
     'lib/src/elements/debugger.html',
     'lib/src/elements/error_ref.dart',
@@ -76,6 +80,10 @@
     'lib/src/elements/heap_profile.html',
     'lib/src/elements/heap_snapshot.dart',
     'lib/src/elements/heap_snapshot.html',
+    'lib/src/elements/helpers/rendering_queue.dart',
+    'lib/src/elements/helpers/rendering_scheduler.dart',
+    'lib/src/elements/helpers/tag.dart',
+    'lib/src/elements/helpers/uris.dart',
     'lib/src/elements/icdata_view.dart',
     'lib/src/elements/icdata_view.html',
     'lib/src/elements/img/chromium_icon.png',
@@ -94,7 +102,7 @@
     'lib/src/elements/isolate_reconnect.dart',
     'lib/src/elements/isolate_reconnect.html',
     'lib/src/elements/isolate_ref.dart',
-    'lib/src/elements/isolate_ref.html',
+    'lib/src/elements/isolate_ref_wrapper.dart',
     'lib/src/elements/isolate_summary.dart',
     'lib/src/elements/isolate_summary.html',
     'lib/src/elements/isolate_view.dart',
@@ -113,8 +121,27 @@
     'lib/src/elements/megamorphiccache_view.html',
     'lib/src/elements/metrics.dart',
     'lib/src/elements/metrics.html',
-    'lib/src/elements/nav_bar.dart',
-    'lib/src/elements/nav_bar.html',
+    'lib/src/elements/nav/bar.dart',
+    'lib/src/elements/nav/class_menu.dart',
+    'lib/src/elements/nav/class_menu_wrapper.dart',
+    'lib/src/elements/nav/isolate_menu.dart',
+    'lib/src/elements/nav/isolate_menu_wrapper.dart',
+    'lib/src/elements/nav/library_menu.dart',
+    'lib/src/elements/nav/library_menu_wrapper.dart',
+    'lib/src/elements/nav/menu_item.dart',
+    'lib/src/elements/nav/menu_item_wrapper.dart',
+    'lib/src/elements/nav/menu.dart',
+    'lib/src/elements/nav/menu_wrapper.dart',
+    'lib/src/elements/nav/notify_event.dart',
+    'lib/src/elements/nav/notify_exception.dart',
+    'lib/src/elements/nav/notify.dart',
+    'lib/src/elements/nav/notify_wrapper.dart',
+    'lib/src/elements/nav/refresh.dart',
+    'lib/src/elements/nav/refresh_wrapper.dart',
+    'lib/src/elements/nav/top_menu.dart',
+    'lib/src/elements/nav/top_menu_wrapper.dart',
+    'lib/src/elements/nav/vm_menu.dart',
+    'lib/src/elements/nav/vm_menu_wrapper.dart',
     'lib/src/elements/object_common.dart',
     'lib/src/elements/object_common.html',
     'lib/src/elements/object_view.dart',
@@ -124,7 +151,6 @@
     'lib/src/elements/observatory_application.dart',
     'lib/src/elements/observatory_application.html',
     'lib/src/elements/observatory_element.dart',
-    'lib/src/elements/observatory_element.html',
     'lib/src/elements/persistent_handles.dart',
     'lib/src/elements/persistent_handles.html',
     'lib/src/elements/ports.dart',
@@ -139,18 +165,47 @@
     'lib/src/elements/service_ref.html',
     'lib/src/elements/service_view.dart',
     'lib/src/elements/service_view.html',
-    'lib/src/elements/sliding_checkbox.dart',
-    'lib/src/elements/sliding_checkbox.html',
+    'lib/src/elements/shims/binding.dart',
     'lib/src/elements/timeline_page.dart',
     'lib/src/elements/timeline_page.html',
     'lib/src/elements/view_footer.dart',
-    'lib/src/elements/view_footer.html',
+    'lib/src/elements/vm_connect_target.dart',
+    'lib/src/elements/vm_connect_target_wrapper.dart',
     'lib/src/elements/vm_connect.dart',
     'lib/src/elements/vm_connect.html',
-    'lib/src/elements/vm_ref.dart',
-    'lib/src/elements/vm_ref.html',
     'lib/src/elements/vm_view.dart',
     'lib/src/elements/vm_view.html',
+    'lib/src/mocks/exceptions/connection_exception.dart',
+    'lib/src/mocks/objects/error.dart',
+    'lib/src/mocks/objects/event.dart',
+    'lib/src/mocks/objects/class.dart',
+    'lib/src/mocks/objects/isolate.dart',
+    'lib/src/mocks/objects/library.dart',
+    'lib/src/mocks/objects/notification.dart',
+    'lib/src/mocks/objects/script.dart',
+    'lib/src/mocks/objects/source_location.dart',
+    'lib/src/mocks/objects/target.dart',
+    'lib/src/mocks/objects/vm.dart',
+    'lib/src/mocks/repositories/notification.dart',
+    'lib/src/models/exceptions.dart',
+    'lib/src/models/objects/breakpoint.dart',
+    'lib/src/models/objects/class.dart',
+    'lib/src/models/objects/error.dart',
+    'lib/src/models/objects/event.dart',
+    'lib/src/models/objects/extension_data.dart',
+    'lib/src/models/objects/frame.dart',
+    'lib/src/models/objects/instance.dart',
+    'lib/src/models/objects/isolate.dart',
+    'lib/src/models/objects/library.dart',
+    'lib/src/models/objects/notification.dart',
+    'lib/src/models/objects/object.dart',
+    'lib/src/models/objects/script.dart',
+    'lib/src/models/objects/source_location.dart',
+    'lib/src/models/objects/target.dart',
+    'lib/src/models/objects/timeline_event.dart',
+    'lib/src/models/objects/vm.dart',
+    'lib/src/models/repositories/notification.dart',
+    'lib/src/repositories/notification.dart',
     'lib/src/service/object.dart',
     'lib/tracer.dart',
     'lib/utils.dart',
diff --git a/runtime/observatory/tests/observatory_ui/curly_block/element_test.dart b/runtime/observatory/tests/observatory_ui/curly_block/element_test.dart
new file mode 100644
index 0000000..fe1ca8f
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/curly_block/element_test.dart
@@ -0,0 +1,179 @@
+// 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 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/src/elements/curly_block.dart';
+
+main() {
+  CurlyBlockElement.tag.ensureRegistration();
+
+  group('instantiation', () {
+    test('default', () {
+      final CurlyBlockElement e = new CurlyBlockElement();
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.expanded, isFalse);
+      expect(e.disabled, isFalse);
+    });
+    test('not expanded', () {
+      final CurlyBlockElement e = new CurlyBlockElement(expanded: false);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.expanded, isFalse);
+      expect(e.disabled, isFalse);
+    });
+    test('not expanded / not disabled', () {
+      final CurlyBlockElement e = new CurlyBlockElement(expanded: false,
+                                                        disabled: false);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.expanded, isFalse);
+      expect(e.disabled, isFalse);
+    });
+    test('not expanded / disabled', () {
+      final CurlyBlockElement e = new CurlyBlockElement(expanded: false,
+                                                        disabled: true);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.expanded, isFalse);
+      expect(e.disabled, isTrue);
+    });
+    test('expanded', () {
+      final CurlyBlockElement e = new CurlyBlockElement(expanded: true);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.expanded, isTrue);
+      expect(e.disabled, isFalse);
+    });
+    test('expanded / not disabled', () {
+      final CurlyBlockElement e = new CurlyBlockElement(expanded: true,
+                                                        disabled: false);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.expanded, isTrue);
+      expect(e.disabled, isFalse);
+    });
+    test('expanded / disabled', () {
+      final CurlyBlockElement e = new CurlyBlockElement(expanded: true,
+                                                        disabled: true);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.expanded, isTrue);
+      expect(e.disabled, isTrue);
+    });
+    test('not disabled', () {
+      final CurlyBlockElement e = new CurlyBlockElement(disabled: false);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.expanded, isFalse);
+      expect(e.disabled, isFalse);
+    });
+    test('disabled', () {
+      final CurlyBlockElement e = new CurlyBlockElement(disabled: true);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.expanded, isFalse);
+      expect(e.disabled, isTrue);
+    });
+  });
+  test('elements created', () async {
+    final CurlyBlockElement e = new CurlyBlockElement();
+    expect(e.shadowRoot, isNotNull, reason: 'shadowRoot is created');
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.shadowRoot.children.length, isNonZero,
+      reason: 'shadowRoot has elements');
+    e.remove();
+    await e.onRendered.first;
+    expect(e.shadowRoot.children.length, isZero, reason: 'shadowRoot is empty');
+  });
+  group('content', () {
+    CurlyBlockElement e;
+    setUp(() async {
+      e = new CurlyBlockElement();
+      document.body.append(e);
+      await e.onRendered.first;
+    });
+    tearDown(() {
+      e.remove();
+    });
+    test('toggles visibility', () async {
+      expect(e.shadowRoot.querySelector('content'), isNull);
+      e.toggle();
+      await e.onRendered.first;
+      expect(e.shadowRoot.querySelector('content'), isNotNull);
+      e.toggle();
+      await e.onRendered.first;
+      expect(e.shadowRoot.querySelector('content'), isNull);
+      e.remove();
+    });
+    test('toggles visibility (manually)', () async {
+      expect(e.shadowRoot.querySelector('content'), isNull);
+      e.expanded = true;
+      await e.onRendered.first;
+      expect(e.shadowRoot.querySelector('content'), isNotNull);
+      e.expanded = false;
+      await e.onRendered.first;
+      expect(e.shadowRoot.querySelector('content'), isNull);
+      e.remove();
+    });
+    test('does not toggle if disabled', () async {
+      e.disabled = true;
+      await e.onRendered.first;
+      expect(e.expanded, isFalse);
+      expect(e.shadowRoot.querySelector('content'), isNull);
+      e.toggle();
+      await e.onRendered.first;
+      expect(e.expanded, isFalse);
+      expect(e.shadowRoot.querySelector('content'), isNull);
+      e.disabled = false;
+      e.toggle();
+      await e.onRendered.first;
+      expect(e.expanded, isTrue);
+      expect(e.shadowRoot.querySelector('content'), isNotNull);
+      e.disabled = true;
+      e.toggle();
+      await e.onRendered.first;
+      expect(e.expanded, isTrue);
+      expect(e.shadowRoot.querySelector('content'), isNotNull);
+      e.remove();
+    });
+    test('toggles visibility (manually) if disabled', () async {
+      e.disabled = true;
+      await e.onRendered.first;
+      expect(e.shadowRoot.querySelector('content'), isNull);
+      e.expanded = true;
+      await e.onRendered.first;
+      expect(e.shadowRoot.querySelector('content'), isNotNull);
+      e.expanded = false;
+      await e.onRendered.first;
+      expect(e.shadowRoot.querySelector('content'), isNull);
+      e.remove();
+    });
+  });
+  group('event', () {
+    CurlyBlockElement e;
+    setUp(() async {
+      e = new CurlyBlockElement();
+      document.body.append(e);
+      await e.onRendered.first;
+    });
+    tearDown(() async {
+      e.remove();
+      await e.onRendered.first;
+    });
+    test('fires on toggle', () async {
+      e.onToggle.listen(expectAsync((CurlyBlockToggleEvent event){
+        expect(event, isNotNull);
+        expect(event.control, equals(e));
+      }, count: 1));
+      e.toggle();
+      await e.onRendered.first;
+    });
+    test('fires on manual toggle', () async {
+      e.onToggle.listen(expectAsync((CurlyBlockToggleEvent event){
+        expect(event, isNotNull);
+        expect(event.control, equals(e));
+      }, count: 1));
+      e.expanded = !e.expanded;
+      await e.onRendered.first;
+    });
+    test('does not fire if setting same expanded value', () async {
+      e.onToggle.listen(expectAsync((_){}, count: 0));
+      e.expanded = e.expanded;
+      await e.onRendered.first;
+    });
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/curly_block/element_test.html b/runtime/observatory/tests/observatory_ui/curly_block/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/curly_block/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/nav/bar/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/bar/element_test.dart
new file mode 100644
index 0000000..fe54785
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/bar/element_test.dart
@@ -0,0 +1,26 @@
+// 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 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/src/elements/nav/bar.dart';
+
+main() {
+  NavBarElement.tag.ensureRegistration();
+
+  test('instantiation', () {
+    final NavBarElement e = new NavBarElement();
+    expect(e, isNotNull, reason: 'element correctly created');
+  });
+  test('elements created', () async {
+    final NavBarElement e = new NavBarElement();
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.shadowRoot.children.length, isNonZero, reason: 'has elements');
+    expect(e.shadowRoot.querySelector('content'), isNotNull,
+                                               reason: 'has content elements');
+    e.remove();
+    await e.onRendered.first;
+    expect(e.shadowRoot.children.length, isZero, reason: 'is empty');
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/nav/bar/element_test.html b/runtime/observatory/tests/observatory_ui/nav/bar/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/bar/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/nav/class-menu/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/class-menu/element_test.dart
new file mode 100644
index 0000000..df83ea4
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/class-menu/element_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 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/src/elements/nav/class_menu.dart';
+
+main(){
+  NavClassMenuElement.tag.ensureRegistration();
+
+  final IsolateRefMock i_ref = const IsolateRefMock(id: 'i-id', name: 'i-name');
+  final ClassRefMock c_ref = const ClassRefMock(id: 'c-id', name: 'c-name');
+  test('instantiation', () {
+    final NavClassMenuElement e = new NavClassMenuElement(i_ref, c_ref);
+    expect(e, isNotNull, reason: 'element correctly created');
+    expect(e.isolate, equals(i_ref));
+    expect(e.cls, equals(c_ref));
+  });
+  test('elements created after attachment', () async {
+    final NavClassMenuElement e = new NavClassMenuElement(i_ref, c_ref);
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.shadowRoot.children.length, isNonZero, reason: 'has elements');
+    e.remove();
+    await e.onRendered.first;
+    expect(e.shadowRoot.children.length, isZero, reason: 'is empty');
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/nav/class-menu/element_test.html b/runtime/observatory/tests/observatory_ui/nav/class-menu/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/class-menu/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/nav/isolate-menu/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/isolate-menu/element_test.dart
new file mode 100644
index 0000000..27bf79c
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/isolate-menu/element_test.dart
@@ -0,0 +1,75 @@
+// 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 'dart:html';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/models.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/src/elements/nav/menu.dart';
+import 'package:observatory/src/elements/nav/isolate_menu.dart';
+
+main(){
+  NavIsolateMenuElement.tag.ensureRegistration();
+
+  final String tag = NavMenuElement.tag.name;
+
+  StreamController<IsolateUpdateEvent> updatesController;
+  final IsolateRefMock ref = const IsolateRefMock(id: 'i-id', name: 'old-name');
+  final IsolateMock obj = const IsolateMock(id: 'i-id', name: 'new-name');
+  setUp(() {
+    updatesController = new StreamController<IsolateUpdateEvent>();
+  });
+  group('instantiation', () {
+    test('IsolateRef', () {
+      final NavIsolateMenuElement e = new NavIsolateMenuElement(ref,
+                                      updatesController.stream);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.isolate, equals(ref));
+    });
+    test('Isolate', () {
+      final NavIsolateMenuElement e = new NavIsolateMenuElement(obj,
+                                      updatesController.stream);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.isolate, equals(obj));
+    });
+  });
+  test('elements created after attachment', () async {
+    final NavIsolateMenuElement e = new NavIsolateMenuElement(ref,
+                                    updatesController.stream);
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.shadowRoot.children.length, isNonZero, reason: 'has elements');
+    e.remove();
+    await e.onRendered.first;
+    expect(e.shadowRoot.children.length, isZero, reason: 'is empty');
+  });
+  group('updates', () {
+    test('are correctly listen', () async {
+      final NavIsolateMenuElement e = new NavIsolateMenuElement(ref,
+                                      updatesController.stream);
+      expect(updatesController.hasListener, isFalse);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(updatesController.hasListener, isTrue);
+      e.remove();
+      await e.onRendered.first;
+      expect(updatesController.hasListener, isFalse);
+    });
+    test('have effects', () async {
+      final NavIsolateMenuElement e = new NavIsolateMenuElement(ref,
+                                      updatesController.stream);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect((e.shadowRoot.querySelector(tag) as NavMenuElement)
+             .label.contains(ref.name), isTrue);
+      updatesController.add(new IsolateUpdateEventMock(isolate: obj));
+      await e.onRendered.first;
+      expect((e.shadowRoot.querySelector(tag) as NavMenuElement)
+             .label.contains(ref.name), isFalse);
+      expect((e.shadowRoot.querySelector(tag) as NavMenuElement)
+            .label.contains(obj.name), isTrue);
+      e.remove();
+    });
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/nav/isolate-menu/element_test.html b/runtime/observatory/tests/observatory_ui/nav/isolate-menu/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/isolate-menu/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/nav/library-menu/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/library-menu/element_test.dart
new file mode 100644
index 0000000..f6967c9
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/library-menu/element_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 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/src/elements/nav/library_menu.dart';
+
+main(){
+  NavLibraryMenuElement.tag.ensureRegistration();
+
+  final IsolateRefMock i_ref = const IsolateRefMock(id: 'i-id', name: 'i-name');
+  final LibraryRefMock l_ref = const LibraryRefMock(id: 'l-id', name: 'l-name');
+  test('instantiation', () {
+    final NavLibraryMenuElement e = new NavLibraryMenuElement(i_ref, l_ref);
+    expect(e, isNotNull, reason: 'element correctly created');
+    expect(e.isolate, equals(i_ref));
+    expect(e.library, equals(l_ref));
+  });
+  test('elements created after attachment', () async {
+    final NavLibraryMenuElement e = new NavLibraryMenuElement(i_ref, l_ref);
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.shadowRoot.children.length, isNonZero, reason: 'has elements');
+    e.remove();
+    await e.onRendered.first;
+    expect(e.shadowRoot.children.length, isZero, reason: 'is empty');
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/nav/library-menu/element_test.html b/runtime/observatory/tests/observatory_ui/nav/library-menu/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/library-menu/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/nav/menu-item/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/menu-item/element_test.dart
new file mode 100644
index 0000000..f4ee551
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/menu-item/element_test.dart
@@ -0,0 +1,70 @@
+// 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 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/src/elements/nav/menu_item.dart';
+
+main() {
+  NavMenuItemElement.tag.ensureRegistration();
+
+  group('instantiation', () {
+    final label = 'custom-label';
+    final link = 'link-to-target';
+    test('label', () {
+      final NavMenuItemElement e = new NavMenuItemElement(label);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.label, equals(label), reason: 'element correctly created');
+    });
+    test('label', () {
+      final NavMenuItemElement e = new NavMenuItemElement(label, link: link);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.link, equals(link), reason: 'element correctly created');
+    });
+  });
+  group('elements', () {
+    test('created', () async {
+      final label = 'custom-label';
+      final NavMenuItemElement e = new NavMenuItemElement(label);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.shadowRoot.children.length, isNonZero, reason: 'has elements');
+      expect(e.shadowRoot.querySelector('content'), isNotNull,
+                                                 reason: 'has content elements');
+      e.remove();
+      await e.onRendered.first;
+      expect(e.shadowRoot.children.length, isZero, reason: 'is empty');
+    });
+    test('react to label change', () async {
+      final label1 = 'custom-label-1';
+      final label2 = 'custom-label-2';
+      final NavMenuItemElement e = new NavMenuItemElement(label1);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.shadowRoot.innerHtml.contains(label1), isTrue);
+      expect(e.shadowRoot.innerHtml.contains(label2), isFalse);
+      e.label = label2;
+      await e.onRendered.first;
+      expect(e.shadowRoot.innerHtml.contains(label1), isFalse);
+      expect(e.shadowRoot.innerHtml.contains(label2), isTrue);
+      e.remove();
+      await e.onRendered.first;
+    });
+    test('react to link change', () async {
+      final label = 'custom-label';
+      final link1 = 'custom-label-1';
+      final link2 = 'custom-label-2';
+      final NavMenuItemElement e = new NavMenuItemElement(label, link: link1);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.shadowRoot.innerHtml.contains(link1), isTrue);
+      expect(e.shadowRoot.innerHtml.contains(link2), isFalse);
+      e.link = link2;
+      await e.onRendered.first;
+      expect(e.shadowRoot.innerHtml.contains(link1), isFalse);
+      expect(e.shadowRoot.innerHtml.contains(link2), isTrue);
+      e.remove();
+      await e.onRendered.first;
+    });
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/nav/menu-item/element_test.html b/runtime/observatory/tests/observatory_ui/nav/menu-item/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/menu-item/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/nav/menu/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/menu/element_test.dart
new file mode 100644
index 0000000..0cabc3c
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/menu/element_test.dart
@@ -0,0 +1,73 @@
+// 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 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/src/elements/nav/menu.dart';
+
+main() {
+  NavMenuElement.tag.ensureRegistration();
+
+  group('instantiation', () {
+    final label = 'custom-label';
+    test('label', () {
+      final NavMenuElement e = new NavMenuElement(label);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.label, equals(label), reason: 'element correctly created');
+    });
+    test('not last', () {
+      final NavMenuElement e = new NavMenuElement(label, last: false);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.last, isFalse, reason: 'element correctly created');
+    });
+    test('last', () {
+      final NavMenuElement e = new NavMenuElement(label, last: true);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.last, isTrue, reason: 'element correctly created');
+    });
+  });
+  group('elements', () {
+    test('created', () async {
+      final label = 'custom-label';
+      final NavMenuElement e = new NavMenuElement(label);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.shadowRoot.children.length, isNonZero, reason: 'has elements');
+      expect(e.shadowRoot.querySelector('content'), isNotNull,
+                                                 reason: 'has content elements');
+      e.remove();
+      await e.onRendered.first;
+      expect(e.shadowRoot.children.length, isZero, reason: 'is empty');
+    });
+    test('react to label change', () async {
+      final label1 = 'custom-label-1';
+      final label2 = 'custom-label-2';
+      final NavMenuElement e = new NavMenuElement(label1);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.shadowRoot.innerHtml.contains(label1), isTrue);
+      expect(e.shadowRoot.innerHtml.contains(label2), isFalse);
+      e.label = label2;
+      await e.onRendered.first;
+      expect(e.shadowRoot.innerHtml.contains(label1), isFalse);
+      expect(e.shadowRoot.innerHtml.contains(label2), isTrue);
+      e.remove();
+      await e.onRendered.first;
+    });
+    test('react to last change', () async {
+      final label = 'custom-label';
+      final NavMenuElement e = new NavMenuElement(label, last: false);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.shadowRoot.innerHtml.contains('&gt;'), isTrue);
+      e.last = true;
+      await e.onRendered.first;
+      expect(e.shadowRoot.innerHtml.contains('&gt;'), isFalse);
+      e.last = false;
+      await e.onRendered.first;
+      expect(e.shadowRoot.innerHtml.contains('&gt;'), isTrue);
+      e.remove();
+      await e.onRendered.first;
+    });
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/nav/menu/element_test.html b/runtime/observatory/tests/observatory_ui/nav/menu/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/menu/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/nav/notify/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/notify/element_test.dart
new file mode 100644
index 0000000..64adcfb
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/notify/element_test.dart
@@ -0,0 +1,121 @@
+// 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 'dart:html' hide Notification, NotificationEvent;
+import 'package:unittest/unittest.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/nav/notify.dart';
+import 'package:observatory/src/elements/nav/notify_event.dart';
+import 'package:observatory/src/elements/nav/notify_exception.dart';
+
+main() {
+  NavNotifyElement.tag.ensureRegistration();
+
+  final evTag = NavNotifyEventElement.tag.name;
+  final exTag = NavNotifyExceptionElement.tag.name;
+
+  const vm = const VMRefMock();
+  const isolate = const IsolateRefMock(id: 'i-id', name: 'i-name');
+
+  group('instantiation', () {
+    test('default', () {
+      final NavNotifyElement e = new NavNotifyElement(
+          new NotificationRepositoryMock());
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.notifyOnPause, isTrue, reason: 'notifyOnPause is default');
+    });
+    test('notify on pause', () {
+      final NavNotifyElement e = new NavNotifyElement(
+          new NotificationRepositoryMock(), notifyOnPause: true);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.notifyOnPause, isTrue, reason: 'notifyOnPause is the same');
+    });
+    test('do not notify on pause', () {
+      final NavNotifyElement e = new NavNotifyElement(
+          new NotificationRepositoryMock(), notifyOnPause: false);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.notifyOnPause, isFalse, reason: 'notifyOnPause is the same');
+    });
+  });
+  test('is correctly listening', () async {
+    final NotificationRepositoryMock repository =
+        new NotificationRepositoryMock();
+    final NavNotifyElement e = new NavNotifyElement(repository);
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(repository.hasListeners, isTrue, reason: 'is listening');
+    e.remove();
+    await e.onRendered.first;
+    expect(repository.hasListeners, isFalse, reason: 'is no more listening');
+  });
+  group('elements', () {
+    test('created after attachment', () async {
+      final NotificationRepositoryMock repository =
+          new NotificationRepositoryMock(list: [
+            new ExceptionNotificationMock(exception: new Exception("ex")),
+            const EventNotificationMock(event: const VMUpdateEventMock(vm: vm)),
+            const EventNotificationMock(event: const VMUpdateEventMock(vm: vm))
+          ]);
+      final NavNotifyElement e = new NavNotifyElement(repository);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(repository.listInvoked, isTrue, reason: 'should invoke list()');
+      expect(e.children.length, isNonZero, reason: 'has elements');
+      expect(e.querySelectorAll(evTag).length, equals(2));
+      expect(e.querySelectorAll(exTag).length, equals(1));
+      e.remove();
+      await e.onRendered.first;
+      expect(e.children.length, isZero, reason: 'is empty');
+    });
+    test('react to notifyOnPause change', () async {
+      final NotificationRepositoryMock repository =
+          new NotificationRepositoryMock(list: [
+            new ExceptionNotificationMock(exception: new Exception("ex")),
+            const EventNotificationMock(event: const VMUpdateEventMock()),
+            const EventNotificationMock(
+                event: const PauseStartEventMock(isolate: isolate))
+          ]);
+      final NavNotifyElement e = new NavNotifyElement(repository,
+          notifyOnPause: true);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.querySelectorAll(evTag).length, equals(2));
+      expect(e.querySelectorAll(exTag).length, equals(1));
+      e.notifyOnPause = false;
+      await e.onRendered.first;
+      expect(e.querySelectorAll(evTag).length, equals(1));
+      expect(e.querySelectorAll(exTag).length, equals(1));
+      e.notifyOnPause = true;
+      await e.onRendered.first;
+      expect(e.querySelectorAll(evTag).length, equals(2));
+      expect(e.querySelectorAll(exTag).length, equals(1));
+      e.remove();
+      await e.onRendered.first;
+      expect(e.children.length, isZero, reason: 'is empty');
+    });
+    test('react to update event', () async {
+      final List<M.Notification> list = [
+        new ExceptionNotificationMock(exception: new Exception("ex")),
+        const EventNotificationMock(event: const VMUpdateEventMock()),
+      ];
+      final NotificationRepositoryMock repository =
+          new NotificationRepositoryMock(list: list);
+      final NavNotifyElement e = new NavNotifyElement(repository,
+          notifyOnPause: true);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.querySelectorAll(evTag).length, equals(1));
+      expect(e.querySelectorAll(exTag).length, equals(1));
+      list.add(const EventNotificationMock(
+          event: const PauseStartEventMock(isolate: isolate)));
+      repository.triggerChangeEvent();
+      await e.onRendered.first;
+      expect(e.querySelectorAll(evTag).length, equals(2));
+      expect(e.querySelectorAll(exTag).length, equals(1));
+      e.remove();
+      await e.onRendered.first;
+      expect(e.children.length, isZero, reason: 'is empty');
+    });
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/nav/notify/element_test.html b/runtime/observatory/tests/observatory_ui/nav/notify/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/notify/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/nav/notify_event/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/notify_event/element_test.dart
new file mode 100644
index 0000000..5d5de5c
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/notify_event/element_test.dart
@@ -0,0 +1,65 @@
+// 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 'dart:html';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/src/elements/nav/notify_event.dart';
+
+main() {
+  NavNotifyEventElement.tag.ensureRegistration();
+
+  final PauseStartEventMock event = new PauseStartEventMock(
+              isolate: new IsolateMock(id: 'isolate-id', name: 'isolate-name'));
+  group('instantiation', () {
+    final NavNotifyEventElement e = new NavNotifyEventElement(event);
+    expect(e, isNotNull, reason: 'element correctly created');
+    expect(e.event, equals(event));
+  });
+  group('elements', () {
+    test('created after attachment', () async {
+      final NavNotifyEventElement e = new NavNotifyEventElement(event);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.children.length, isNonZero, reason: 'has elements');
+      e.remove();
+      await e.onRendered.first;
+      expect(e.children.length, isZero, reason: 'is empty');
+    });
+  });
+  group('events are fired', () {
+    NavNotifyEventElement e;
+    StreamSubscription sub;
+    setUp(() async {
+      e = new NavNotifyEventElement(event);
+      document.body.append(e);
+      await e.onRendered.first;
+    });
+    tearDown(() {
+      sub.cancel();
+      e.remove();
+    });
+    test('navigation after connect', () async {
+      sub = window.onPopState.listen(expectAsync((_) {}, count: 1,
+        reason: 'event is fired'));
+      e.querySelector('a').click();
+    });
+    test('onDelete events (DOM)', () async {
+      sub = e.onDelete.listen(expectAsync((EventDeleteEvent ev) {
+        expect(ev, isNotNull, reason: 'event is passed');
+        expect(ev.event, equals(event),
+                                            reason: 'exception is the same');
+      }, count: 1, reason: 'event is fired'));
+      e.querySelector('button').click();
+    });
+    test('onDelete events (code)', () async {
+      sub = e.onDelete.listen(expectAsync((EventDeleteEvent ev) {
+        expect(ev, isNotNull, reason: 'event is passed');
+        expect(ev.event, equals(event),
+                                            reason: 'exception is the same');
+      }, count: 1, reason: 'event is fired'));
+      e.delete();
+    });
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/nav/notify_event/element_test.html b/runtime/observatory/tests/observatory_ui/nav/notify_event/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/notify_event/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/nav/notify_exception/connection_exception_test.dart b/runtime/observatory/tests/observatory_ui/nav/notify_exception/connection_exception_test.dart
new file mode 100644
index 0000000..e6b3bc2
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/notify_exception/connection_exception_test.dart
@@ -0,0 +1,67 @@
+// 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 'dart:html';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/models.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/src/elements/nav/notify_exception.dart';
+
+main() {
+  NavNotifyExceptionElement.tag.ensureRegistration();
+
+  final ConnectionException exception =
+      new ConnectionExceptionMock(message: 'message');
+  test('instantiation', () {
+    final NavNotifyExceptionElement e =
+                                new NavNotifyExceptionElement(exception);
+    expect(e, isNotNull, reason: 'element correctly created');
+  });
+  test('elements created after attachment', () async {
+    final NavNotifyExceptionElement e =
+                                new NavNotifyExceptionElement(exception);
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.children.length, isNonZero, reason: 'has elements');
+    e.remove();
+    await e.onRendered.first;
+    expect(e.children.length, isZero, reason: 'is empty');
+  });
+  group('events are fired', () {
+    NavNotifyExceptionElement e;
+    StreamSubscription sub;
+    setUp(() async {
+      e = new NavNotifyExceptionElement(exception);
+      document.body.append(e);
+      await e.onRendered.first;
+    });
+    tearDown(() {
+      sub.cancel();
+      e.remove();
+    });
+    test('navigation after connect', () async {
+      sub = window.onPopState.listen(expectAsync((_) {}, count: 1,
+        reason: 'event is fired'));
+      e.querySelector('a').click();
+    });
+    test('onDelete events (DOM)', () async {
+      sub = e.onDelete.listen(expectAsync((ExceptionDeleteEvent event) {
+        expect(event, isNotNull, reason: 'event is passed');
+        expect(event.exception, equals(exception),
+                                              reason: 'exception is the same');
+        expect(event.stacktrace, isNull);
+      }, count: 1, reason: 'event is fired'));
+      e.querySelector('button').click();
+    });
+    test('onDelete events (code)', () async {
+      sub = e.onDelete.listen(expectAsync((ExceptionDeleteEvent event) {
+        expect(event, isNotNull, reason: 'event is passed');
+        expect(event.exception, equals(exception),
+                                              reason: 'exception is the same');
+        expect(event.stacktrace, isNull);
+      }, count: 1, reason: 'event is fired'));
+      e.delete();
+    });
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/nav/notify_exception/connection_exception_test.html b/runtime/observatory/tests/observatory_ui/nav/notify_exception/connection_exception_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/notify_exception/connection_exception_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/nav/notify_exception/exception_test.dart b/runtime/observatory/tests/observatory_ui/nav/notify_exception/exception_test.dart
new file mode 100644
index 0000000..be9fdc5
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/notify_exception/exception_test.dart
@@ -0,0 +1,96 @@
+// 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 'dart:html';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/src/elements/nav/notify_exception.dart';
+
+main() {
+  NavNotifyExceptionElement.tag.ensureRegistration();
+
+  final StackTrace stacktrace = new StackTrace.fromString('stacktrace string');
+  group('normal exception', () {
+    final Exception exception = new Exception('exception message');
+    group('instantiation', () {
+      test('no stacktrace', () {
+        final NavNotifyExceptionElement e =
+                                      new NavNotifyExceptionElement(exception);
+        expect(e, isNotNull, reason: 'element correctly created');
+        expect(e.exception, equals(exception));
+        expect(e.stacktrace, isNull);
+      });
+      test('with stacktrace', () {
+        final NavNotifyExceptionElement e =
+              new NavNotifyExceptionElement(exception, stacktrace: stacktrace);
+        expect(e, isNotNull, reason: 'element correctly created');
+        expect(e.exception, equals(exception));
+        expect(e.stacktrace, equals(stacktrace));
+      });
+    });
+    group('elements', () {
+      test('created after attachment (no stacktrace)', () async {
+        final NavNotifyExceptionElement e =
+                                      new NavNotifyExceptionElement(exception);
+        document.body.append(e);
+        await e.onRendered.first;
+        expect(e.children.length, isNonZero, reason: 'has elements');
+        expect(e.innerHtml.contains(exception.toString()), isTrue);
+        expect(e.innerHtml.contains(stacktrace.toString()), isFalse);
+        e.remove();
+        await e.onRendered.first;
+        expect(e.children.length, isZero, reason: 'is empty');
+      });
+      test('created after attachment (with stacktrace)', () async {
+        final NavNotifyExceptionElement e =
+              new NavNotifyExceptionElement(exception, stacktrace: stacktrace);
+        document.body.append(e);
+        await e.onRendered.first;
+        expect(e.children.length, isNonZero, reason: 'has elements');
+        expect(e.innerHtml.contains(exception.toString()), isTrue);
+        expect(e.innerHtml.contains(stacktrace.toString()), isTrue);
+        e.remove();
+        await e.onRendered.first;
+        expect(e.children.length, isZero, reason: 'is empty');
+      });
+    });
+    group('events are fired', () {
+      NavNotifyExceptionElement e;
+      StreamSubscription sub;
+      setUp(() async {
+        e = new NavNotifyExceptionElement(exception, stacktrace: stacktrace);
+        document.body.append(e);
+        await e.onRendered.first;
+      });
+      tearDown(() {
+        sub.cancel();
+        e.remove();
+      });
+      test('navigation after connect', () async {
+        sub = window.onPopState.listen(expectAsync((_) {}, count: 1,
+          reason: 'event is fired'));
+        e.querySelector('a').click();
+      });
+      test('onDelete events (DOM)', () async {
+        sub = e.onDelete.listen(expectAsync((ExceptionDeleteEvent event) {
+          expect(event, isNotNull, reason: 'event is passed');
+          expect(event.exception, equals(exception),
+                                              reason: 'exception is the same');
+          expect(event.stacktrace, equals(stacktrace),
+                                            reason: 'stacktrace is the same');
+        }, count: 1, reason: 'event is fired'));
+        e.querySelector('button').click();
+      });
+      test('onDelete events (code)', () async {
+        sub = e.onDelete.listen(expectAsync((ExceptionDeleteEvent event) {
+          expect(event, isNotNull, reason: 'event is passed');
+          expect(event.exception, equals(exception),
+                                              reason: 'exception is the same');
+          expect(event.stacktrace, equals(stacktrace),
+                                            reason: 'stacktrace is the same');
+        }, count: 1, reason: 'event is fired'));
+        e.delete();
+      });
+    });
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/nav/notify_exception/exception_test.html b/runtime/observatory/tests/observatory_ui/nav/notify_exception/exception_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/notify_exception/exception_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/nav/refresh/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/refresh/element_test.dart
new file mode 100644
index 0000000..26c3ada
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/refresh/element_test.dart
@@ -0,0 +1,122 @@
+// 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 'dart:html';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/src/elements/nav/refresh.dart';
+
+main() {
+  NavRefreshElement.tag.ensureRegistration();
+  group('instantiation', () {
+    test('no parameters', () {
+      final NavRefreshElement e = new NavRefreshElement();
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.label, isNotNull, reason: 'label is set to default');
+      expect(e.disabled, isFalse, reason: 'element correctly created');
+    });
+    test('label', () {
+      final label = 'custom-label';
+      final NavRefreshElement e = new NavRefreshElement(label: label);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.label, isNotNull, reason: 'label is set');
+      expect(e.label, equals(label), reason: 'label is set to value');
+    });
+    test('not disabled', () {
+      final NavRefreshElement e = new NavRefreshElement(disabled: false);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.disabled, isFalse, reason: 'element correctly created');
+    });
+    test('disabled', () {
+      final NavRefreshElement e = new NavRefreshElement(disabled: true);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.disabled, isTrue, reason: 'element correctly created');
+    });
+  });
+  group('elements', () {
+    test('created after attachment', () async {
+      final NavRefreshElement e = new NavRefreshElement();
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.children.length, isNonZero, reason: 'has elements');
+      e.remove();
+      await e.onRendered.first;
+      expect(e.children.length, isZero, reason: 'is empty');
+    });
+    test('contain custom label', () async {
+      final label = 'custom-label';
+      final NavRefreshElement e = new NavRefreshElement(label: label);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.innerHtml.contains(label), isTrue);
+      e.remove();
+      await e.onRendered.first;
+    });
+    test('react to label change', () async {
+      final label1 = 'custom-label-1';
+      final label2 = 'custom-label-2';
+      final NavRefreshElement e = new NavRefreshElement(label: label1);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.innerHtml.contains(label1), isTrue);
+      expect(e.innerHtml.contains(label2), isFalse);
+      e.label = label2;
+      await e.onRendered.first;
+      expect(e.innerHtml.contains(label2), isTrue);
+      expect(e.innerHtml.contains(label1), isFalse);
+      e.remove();
+      await e.onRendered.first;
+    });
+    test('react to disabled change', () async {
+      final NavRefreshElement e = new NavRefreshElement(disabled: false);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.disabled, isFalse);
+      e.disabled = true;
+      await e.onRendered.first;
+      expect(e.disabled, isTrue);
+      e.remove();
+      await e.onRendered.first;
+    });
+  });
+  group('event', () {
+    NavRefreshElement e;
+    StreamSubscription sub;
+    setUp(() async {
+      e = new NavRefreshElement();
+      document.body.append(e);
+      await e.onRendered.first;
+    });
+    tearDown(() async {
+      sub.cancel();
+      e.remove();
+      await e.onRendered.first;
+    });
+    test('fires', () async {
+      sub = e.onRefresh.listen(expectAsync((event) {
+        expect(event, isNotNull, reason: 'event passed');
+        expect(event is RefreshEvent, isTrue, reason: 'is the right event');
+        expect(event.element, equals(e), reason: 'is related to the element');
+      }, count: 1));
+      e.refresh();
+    });
+    test('fires on click', () async {
+      sub = e.onRefresh.listen(expectAsync((event) {
+        expect(event, isNotNull, reason: 'event passed');
+        expect(event is RefreshEvent, isTrue, reason: 'is the right event');
+        expect(event.element, equals(e), reason: 'is related to the element');
+      }, count: 1));
+      e.querySelector('button').click();
+    });
+    test('does not fire if disabled', () async {
+      e.disabled = true;
+      sub = e.onRefresh.listen(expectAsync((_) {}, count: 0));
+      e.refresh();
+    });
+    test('does not fires on click if disabled', () async {
+      e.disabled = true;
+      sub = e.onRefresh.listen(expectAsync((_) {}, count: 0));
+      e.querySelector('button').click();
+    });
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/nav/refresh/element_test.html b/runtime/observatory/tests/observatory_ui/nav/refresh/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/refresh/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/nav/top-menu/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/top-menu/element_test.dart
new file mode 100644
index 0000000..df9f88c
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/top-menu/element_test.dart
@@ -0,0 +1,57 @@
+// 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 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/src/elements/nav/menu.dart';
+import 'package:observatory/src/elements/nav/top_menu.dart';
+
+main() {
+  NavTopMenuElement.tag.ensureRegistration();
+
+  final String tag = NavMenuElement.tag.name;
+
+  group('instantiation', () {
+    test('default', () {
+      final NavTopMenuElement e = new NavTopMenuElement();
+      expect(e, isNotNull, reason: 'element correctly created');
+    });
+    test('not last', () {
+      final NavTopMenuElement e = new NavTopMenuElement(last: false);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.last, isFalse, reason: 'element correctly created');
+    });
+    test('last', () {
+      final NavTopMenuElement e = new NavTopMenuElement(last: true);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.last, isTrue, reason: 'element correctly created');
+    });
+  });
+  group('elements', () {
+    test('created', () async {
+      final NavTopMenuElement e = new NavTopMenuElement();
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.shadowRoot.children.length, isNonZero, reason: 'has elements');
+      expect(e.shadowRoot.querySelector('content'), isNotNull,
+                                                 reason: 'has content elements');
+      e.remove();
+      await e.onRendered.first;
+      expect(e.shadowRoot.children.length, isZero, reason: 'is empty');
+    });
+    test('react to last change', () async {
+      final NavTopMenuElement e = new NavTopMenuElement(last: false);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect((e.shadowRoot.querySelector(tag) as NavMenuElement).last, isFalse);
+      e.last = true;
+      await e.onRendered.first;
+      expect((e.shadowRoot.querySelector(tag) as NavMenuElement).last, isTrue);
+      e.last = false;
+      await e.onRendered.first;
+      expect((e.shadowRoot.querySelector(tag) as NavMenuElement).last, isFalse);
+      e.remove();
+      await e.onRendered.first;
+    });
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/nav/top-menu/element_test.html b/runtime/observatory/tests/observatory_ui/nav/top-menu/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/top-menu/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/nav/vm_menu/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/vm_menu/element_test.dart
new file mode 100644
index 0000000..b0539ff
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/vm_menu/element_test.dart
@@ -0,0 +1,85 @@
+// 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 'dart:html';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/nav/menu.dart';
+import 'package:observatory/src/elements/nav/menu_item.dart';
+import 'package:observatory/src/elements/nav/vm_menu.dart';
+
+main(){
+  NavVMMenuElement.tag.ensureRegistration();
+
+  final mTag = NavMenuElement.tag.name;
+  final miTag = NavMenuItemElement.tag.name;
+
+  StreamController<M.VMUpdateEvent> updatesController;
+  final TargetMock target = new TargetMock(name: 'target-name');
+  final VMMock vm1 = const VMMock(name: 'vm-name-1',
+      isolates: const [const IsolateRefMock(id: 'i-id-1', name: 'i-name-1')]);
+  final VMMock vm2 = const VMMock(name: 'vm-name-2',
+      isolates: const [const IsolateRefMock(id: 'i-id-1', name: 'i-name-1'),
+                       const IsolateRefMock(id: 'i-id-2', name: 'i-name-2')]);
+  setUp(() {
+    updatesController = new StreamController<M.VMUpdateEvent>.broadcast();
+  });
+  group('instantiation', () {
+    test('no target', () {
+      final NavVMMenuElement e = new NavVMMenuElement(vm1,
+          updatesController.stream);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.vm, equals(vm1));
+      expect(e.target, isNull);
+    });
+    test('target', () {
+      final NavVMMenuElement e = new NavVMMenuElement(vm1,
+          updatesController.stream, target: target);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.vm, equals(vm1));
+      expect(e.target, equals(target));
+    });
+  });
+  test('elements created after attachment', () async {
+    final NavVMMenuElement e = new NavVMMenuElement(vm1,
+        updatesController.stream);
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.shadowRoot.children.length, isNonZero, reason: 'has elements');
+    e.remove();
+    await e.onRendered.first;
+    expect(e.shadowRoot.children.length, isZero, reason: 'is empty');
+  });
+  group('updates', () {
+    test('are correctly listen', () async {
+      final NavVMMenuElement e = new NavVMMenuElement(vm1,
+          updatesController.stream);
+      expect(updatesController.hasListener, isFalse);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(updatesController.hasListener, isTrue);
+      e.remove();
+      await e.onRendered.first;
+      expect(updatesController.hasListener, isFalse);
+    });
+    test('have effects', () async {
+      final NavVMMenuElement e = new NavVMMenuElement(vm1,
+          updatesController.stream);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect((e.shadowRoot.querySelector(mTag) as NavMenuElement).label,
+          equals(vm1.name));
+      expect(e.shadowRoot.querySelectorAll(miTag).length,
+          equals(vm1.isolates.length));
+      updatesController.add(new VMUpdateEventMock(vm: vm2));
+      await e.onRendered.first;
+      expect((e.shadowRoot.querySelector(mTag) as NavMenuElement).label,
+          equals(vm2.name));
+      expect(e.shadowRoot.querySelectorAll(miTag).length,
+          equals(vm2.isolates.length));
+      e.remove();
+    });
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/nav/vm_menu/element_test.html b/runtime/observatory/tests/observatory_ui/nav/vm_menu/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/nav/vm_menu/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/observatory_ui.status b/runtime/observatory/tests/observatory_ui/observatory_ui.status
index 4d08c8a..0675fff 100644
--- a/runtime/observatory/tests/observatory_ui/observatory_ui.status
+++ b/runtime/observatory/tests/observatory_ui/observatory_ui.status
@@ -2,5 +2,5 @@
 # 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.
 
-[ $browser == false ]
+[ $browser == false || $runtime == drt ]
 *: SkipByDesign
diff --git a/runtime/observatory/tests/observatory_ui/view_footer/element_test.dart b/runtime/observatory/tests/observatory_ui/view_footer/element_test.dart
new file mode 100644
index 0000000..f3ab727
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/view_footer/element_test.dart
@@ -0,0 +1,24 @@
+// 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 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/src/elements/view_footer.dart';
+
+main() {
+  ViewFooterElement.tag.ensureRegistration();
+
+  test('instantiation', () {
+    final ViewFooterElement e = new ViewFooterElement();
+    expect(e, isNotNull, reason: 'element correctly created');
+  });
+  test('elements created', () async {
+    final ViewFooterElement e = new ViewFooterElement();
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.children.length, isNonZero, reason: 'has elements');
+    e.remove();
+    await e.onRendered.first;
+    expect(e.children.length, isZero, reason: 'is empty');
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/view_footer/element_test.html b/runtime/observatory/tests/observatory_ui/view_footer/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/view_footer/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/vm_connect_target/element_test.dart b/runtime/observatory/tests/observatory_ui/vm_connect_target/element_test.dart
new file mode 100644
index 0000000..a4340e8
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/vm_connect_target/element_test.dart
@@ -0,0 +1,87 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/src/elements/vm_connect_target.dart';
+
+main() {
+  VMConnectTargetElement.tag.ensureRegistration();
+
+  TargetMock t;
+  setUp(() {
+    t = new TargetMock(name: "a network address");
+  });
+  group('instantiation', () {
+    test('no other parameters', () {
+      final VMConnectTargetElement e = new VMConnectTargetElement(t);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.target, t, reason: 'target not setted');
+      expect(e.current, isFalse, reason: 'default to not current');
+    });
+    test('isCurrent: false', () {
+      final VMConnectTargetElement e = new VMConnectTargetElement(t,
+                                            current:false);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.target, t, reason: 'target not setted');
+      expect(e.current, isFalse, reason: 'default to not current');
+    });
+    test('isCurrent: true', () {
+      final VMConnectTargetElement e = new VMConnectTargetElement(t,
+                                            current:true);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.target, t, reason: 'target not setted');
+      expect(e.current, isTrue, reason: 'default to not current');
+    });
+  });
+  test('elements created after attachment', () async {
+    final VMConnectTargetElement e = new VMConnectTargetElement(t);
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.children.length, isNonZero, reason: 'has elements');
+    e.remove();
+    await e.onRendered.first;
+    expect(e.children.length, isZero, reason: 'is empty');
+  });
+  group('events are fired', () {
+    VMConnectTargetElement e;
+    setUp(() async {
+      e = new VMConnectTargetElement(t);
+      document.body.append(e);
+      await e.onRendered.first;
+    });
+    tearDown(() async {
+      e.remove();
+      await e.onRendered.first;
+    });
+    test('onConnect events (DOM)', () async {
+      e.onConnect.listen(expectAsync((TargetEvent event) {
+        expect(event, isNotNull, reason: 'event is passed');
+        expect(event.target, t, reason: 'target is the same');
+      }, count: 1, reason: 'event is fired'));
+      e.querySelector('a').click();
+    });
+    test('onConnect events (code)', () async {
+      e.onConnect.listen(expectAsync((TargetEvent event) {
+        expect(event, isNotNull, reason: 'event is passed');
+        expect(event.target, t, reason: 'target is the same');
+      }, count: 1, reason: 'event is fired'));
+      e.connect();
+    });
+    test('onRemove events (DOM)', () async {
+      e.onDelete.listen(expectAsync((TargetEvent event) {
+        expect(event, isNotNull, reason: 'event is passed');
+        expect(event.target, t, reason: 'target is the same');
+      }, count: 1, reason: 'event is fired'));
+      e.querySelector('button').click();
+    });
+    test('onRemove events (code)', () async {
+      e.onDelete.listen(expectAsync((TargetEvent event) {
+        expect(event, isNotNull, reason: 'event is passed');
+        expect(event.target, t, reason: 'target is the same');
+      }, count: 1, reason: 'event is fired'));
+      e.delete();
+    });
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/vm_connect_target/element_test.html b/runtime/observatory/tests/observatory_ui/vm_connect_target/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/vm_connect_target/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/service/dev_fs_spawn_test.dart b/runtime/observatory/tests/service/dev_fs_spawn_test.dart
new file mode 100644
index 0000000..6537d54
--- /dev/null
+++ b/runtime/observatory/tests/service/dev_fs_spawn_test.dart
@@ -0,0 +1,219 @@
+// 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 'dart:async';
+import 'dart:convert';
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+var tests = [
+  (VM vm) async {
+    // Create a new fs.
+    var fsName = 'scratch';
+    var result = await vm.invokeRpcNoUpgrade('_createDevFS', {
+        'fsName': fsName,
+      });
+    expect(result['type'], equals('FileSystem'));
+    expect(result['name'], equals('scratch'));
+    expect(result['uri'], new isInstanceOf<String>());
+    var fsUri = result['uri'];
+
+    // Spawn a script with a bad uri and make sure that the error is
+    // delivered asynchronously.
+    Completer completer = new Completer();
+    var sub;
+    sub = await vm.listenEventStream(
+      VM.kIsolateStream,
+      (ServiceEvent event) {
+        if (event.kind == ServiceEvent.kIsolateSpawn) {
+          expect(event.spawnToken, equals('someSpawnToken'));
+          expect(event.spawnError, startsWith(
+              'IsolateSpawnException: Unable to spawn isolate: '));
+          expect(event.isolate, isNull);
+          completer.complete();
+          sub.cancel();
+        }
+      });
+
+    result = await vm.invokeRpcNoUpgrade('_spawnUri', {
+        'token': 'someSpawnToken',
+        'uri': '${fsUri}doesnotexist.dart',
+    });
+    expect(result['type'], equals('Success'));
+    await completer.future;
+
+    // Delete the fs.
+    result = await vm.invokeRpcNoUpgrade('_deleteDevFS', {
+        'fsName': fsName,
+    });
+    expect(result['type'], equals('Success'));
+  },
+
+  (VM vm) async {
+    // Create a new fs.
+    var fsName = 'scratch';
+    var result = await vm.invokeRpcNoUpgrade('_createDevFS', {
+        'fsName': fsName,
+      });
+    expect(result['type'], equals('FileSystem'));
+    expect(result['name'], equals('scratch'));
+    expect(result['uri'], new isInstanceOf<String>());
+    var fsUri = result['uri'];
+
+    var filePaths = [
+        'devfs_file0.dart',
+        'devfs_file1.dart',
+        'devfs_file2.dart'
+    ];
+    var scripts = [
+'''
+import 'dart:developer';
+proofOfLife() => 'I live!';
+main() {
+  print('HELLO WORLD 1');
+  debugger();
+}
+''',
+'''
+import 'dart:developer';
+var globalArgs;
+proofOfLife() => 'I live, \${globalArgs}!';
+main(args) {
+  globalArgs = args;
+  print('HELLO WORLD 2');
+  debugger();
+}
+''',
+'''
+import 'dart:developer';
+var globalArgs;
+var globalMsg;
+proofOfLife() => 'I live, \${globalArgs}, \${globalMsg}!';
+main(args, msg) {
+  globalArgs = args;
+  globalMsg = msg;
+  print('HELLO WORLD 3');
+  debugger();
+}
+''',
+    ];
+
+    // Write three scripts to the fs.
+    for (int i = 0; i < 3; i++) {
+      var fileContents = BASE64.encode(UTF8.encode(scripts[i]));
+      result = await vm.invokeRpcNoUpgrade('_writeDevFSFile', {
+        'fsName': fsName,
+        'path': filePaths[i],
+        'fileContents': fileContents
+      });
+      expect(result['type'], equals('Success'));
+    }
+
+    // Spawn the script with no arguments or message and make sure
+    // that we are notified.
+    Completer completer = new Completer();
+    var sub;
+    sub = await vm.listenEventStream(
+      VM.kIsolateStream,
+      (ServiceEvent event) {
+        if (event.kind == ServiceEvent.kIsolateSpawn) {
+          expect(event.spawnToken, equals('mySpawnToken0'));
+          expect(event.isolate, isNotNull);
+          expect(event.isolate.name, equals('devfs_file0.dart\$main'));
+          completer.complete(event.isolate);
+          sub.cancel();
+        }
+      });
+    result = await vm.invokeRpcNoUpgrade('_spawnUri', {
+        'token': 'mySpawnToken0',
+        'uri': '${fsUri}${filePaths[0]}',
+    });
+    expect(result['type'], equals('Success'));
+    var spawnedIsolate = await completer.future;
+
+    // Wait for the spawned isolate to hit a breakpoint.
+    await spawnedIsolate.load();
+    await hasStoppedAtBreakpoint(spawnedIsolate);
+
+    // Make sure that we are running code from the spawned isolate.
+    result = await spawnedIsolate.rootLibrary.evaluate('proofOfLife()');
+    expect(result.type, equals('Instance'));
+    expect(result.kind, equals('String'));
+    expect(result.valueAsString, equals('I live!'));
+
+    // Spawn the script with arguments.
+    completer = new Completer();
+    sub = await vm.listenEventStream(
+      VM.kIsolateStream,
+      (ServiceEvent event) {
+        if (event.kind == ServiceEvent.kIsolateSpawn) {
+          expect(event.spawnToken, equals('mySpawnToken1'));
+          expect(event.isolate, isNotNull);
+          expect(event.isolate.name, equals('devfs_file1.dart\$main'));
+          completer.complete(event.isolate);
+          sub.cancel();
+        }
+      });
+    result = await vm.invokeRpcNoUpgrade('_spawnUri', {
+        'token': 'mySpawnToken1',
+        'uri': '${fsUri}${filePaths[1]}',
+        'args': ['one', 'two', 'three']
+    });
+    expect(result['type'], equals('Success'));
+    spawnedIsolate = await completer.future;
+
+    // Wait for the spawned isolate to hit a breakpoint.
+    await spawnedIsolate.load();
+    await hasStoppedAtBreakpoint(spawnedIsolate);
+
+    // Make sure that we are running code from the spawned isolate.
+    result = await spawnedIsolate.rootLibrary.evaluate('proofOfLife()');
+    expect(result.type, equals('Instance'));
+    expect(result.kind, equals('String'));
+    expect(result.valueAsString, equals('I live, [one, two, three]!'));
+
+    // Spawn the script with arguments and message
+    completer = new Completer();
+    sub = await vm.listenEventStream(
+      VM.kIsolateStream,
+      (ServiceEvent event) {
+        if (event.kind == ServiceEvent.kIsolateSpawn) {
+          expect(event.spawnToken, equals('mySpawnToken2'));
+          expect(event.isolate, isNotNull);
+          expect(event.isolate.name, equals('devfs_file2.dart\$main'));
+          completer.complete(event.isolate);
+          sub.cancel();
+        }
+      });
+    result = await vm.invokeRpcNoUpgrade('_spawnUri', {
+        'token': 'mySpawnToken2',
+        'uri': '${fsUri}${filePaths[2]}',
+        'args': ['A', 'B', 'C'],
+        'message': 'test'
+    });
+    expect(result['type'], equals('Success'));
+    spawnedIsolate = await completer.future;
+
+    // Wait for the spawned isolate to hit a breakpoint.
+    await spawnedIsolate.load();
+    await hasStoppedAtBreakpoint(spawnedIsolate);
+
+    // Make sure that we are running code from the spawned isolate.
+    result = await spawnedIsolate.rootLibrary.evaluate('proofOfLife()');
+    expect(result.type, equals('Instance'));
+    expect(result.kind, equals('String'));
+    expect(result.valueAsString, equals('I live, [A, B, C], test!'));
+
+    // Delete the fs.
+    result = await vm.invokeRpcNoUpgrade('_deleteDevFS', {
+        'fsName': fsName,
+    });
+    expect(result['type'], equals('Success'));
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory/tests/service/dev_fs_test.dart b/runtime/observatory/tests/service/dev_fs_test.dart
index 08e5a5e..5b2930d 100644
--- a/runtime/observatory/tests/service/dev_fs_test.dart
+++ b/runtime/observatory/tests/service/dev_fs_test.dart
@@ -58,7 +58,7 @@
 
   (VM vm) async {
     var fsId = 'banana';
-    var filePath = '/foobar.dat';
+    var filePath = '/foo/bar.dat';
     var fileContents = BASE64.encode(UTF8.encode('fileContents'));
 
     var result;
diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status
index b18b6ce..6318dfa 100644
--- a/runtime/observatory/tests/service/service.status
+++ b/runtime/observatory/tests/service/service.status
@@ -56,17 +56,5 @@
 *: Skip
 
 [ $hot_reload ]
-add_breakpoint_rpc_test: Pass, Timeout, Fail, Crash
-code_test: Fail, Crash
-debugger_location_test: Timeout, Fail, Crash
-debugging_inlined_finally_test: Pass, Timeout, Fail, Crash
-dominator_tree_test: Timeout, Crash
-eval_test: Timeout, Fail, Crash
-evaluate_in_frame_rpc_test: Timeout, Fail, Crash
-get_cpu_profile_timeline_rpc_test: Pass, Timeout, Crash
-get_heap_map_rpc_test: Pass, Timeout, Fail, Crash
-get_vm_timeline_rpc_test: Timeout, Fail, Crash
-graph_test: Pass, Timeout, Fail, Crash
-smart_next_test: Pass, Timeout, Fail, Crash
-step_over_await_test: Pass, Timeout, Fail, Crash
-vm_timeline_events_test: Timeout, Fail, Crash
+# Skip all service tests because random reloads interfere.
+*: SkipByDesign # The service tests should run without being reloaded.
diff --git a/runtime/observatory/tests/service/test_helper.dart b/runtime/observatory/tests/service/test_helper.dart
index 0e8b6e9..df140c5 100644
--- a/runtime/observatory/tests/service/test_helper.dart
+++ b/runtime/observatory/tests/service/test_helper.dart
@@ -102,10 +102,6 @@
     assert(trace_service != null);
     assert(trace_compiler != null);
 
-    // TODO(turnidge): I have temporarily turned on service tracing for
-    // all tests to help diagnose flaky tests.
-    trace_service = true;
-
     if (_shouldLaunchSkyShell()) {
       return _spawnSkyProcess(pause_on_start,
                               pause_on_exit,
@@ -255,6 +251,67 @@
   }
 }
 
+// A tester runner that doesn't spawn a process but instead connects to
+// an already running flutter application running on a device. Assumes
+// port 8100. This is only useful for debugging.
+class _FlutterDeviceServiceTesterRunner {
+  void run({List<String> mainArgs,
+            List<VMTest> vmTests,
+            List<IsolateTest> isolateTests,
+            bool pause_on_start: false,
+            bool pause_on_exit: false,
+            bool trace_service: false,
+            bool trace_compiler: false,
+            bool verbose_vm: false,
+            bool pause_on_unhandled_exceptions: false}) {
+    var port = 8100;
+    serviceWebsocketAddress = 'ws://localhost:$port/ws';
+    serviceHttpAddress = 'http://localhost:$port';
+    var name = Platform.script.pathSegments.last;
+    runZoned(() async {
+      var vm =
+          new WebSocketVM(new WebSocketVMTarget(serviceWebsocketAddress));
+      print('Loading VM...');
+      await vm.load();
+      print('Done loading VM');
+
+      // Run vm tests.
+      if (vmTests != null) {
+        var testIndex = 1;
+        var totalTests = vmTests.length;
+        for (var test in vmTests) {
+          vm.verbose = verbose_vm;
+          print('Running $name [$testIndex/$totalTests]');
+          testIndex++;
+          await test(vm);
+        }
+      }
+
+      // Run isolate tests.
+      if (isolateTests != null) {
+        var isolate = await vm.isolates.first.load();
+        var testIndex = 1;
+        var totalTests = isolateTests.length;
+        for (var test in isolateTests) {
+          vm.verbose = verbose_vm;
+          print('Running $name [$testIndex/$totalTests]');
+          testIndex++;
+          await test(isolate);
+        }
+      }
+    }, onError: (e, st) {
+        if (!_isWebSocketDisconnect(e)) {
+          print('Unexpected exception in service tests: $e $st');
+          throw e;
+        }
+    });
+  }
+}
+
+void suppressWarning() {
+  new _FlutterDeviceServiceTesterRunner();
+}
+
 class _ServiceTesterRunner {
   void run({List<String> mainArgs,
             List<VMTest> vmTests,
diff --git a/runtime/observatory/web/index.html b/runtime/observatory/web/index.html
index d318cf7..0659525 100644
--- a/runtime/observatory/web/index.html
+++ b/runtime/observatory/web/index.html
@@ -6,6 +6,7 @@
   <link rel="import" href="packages/polymer/polymer.html">
   <link rel="stylesheet" href="packages/observatory/src/elements/css/shared.css">
   <link rel="import" href="packages/observatory/elements.html">
+  <script src="packages/js_util/dist/js_util.js"></script>
   <script type="application/dart" src="main.dart"></script>
   <script src="packages/browser/dart.js"></script>
 </head>
diff --git a/runtime/observatory/web/main.dart b/runtime/observatory/web/main.dart
index 238bf97..41f3dc7 100644
--- a/runtime/observatory/web/main.dart
+++ b/runtime/observatory/web/main.dart
@@ -4,8 +4,9 @@
 
 import 'package:logging/logging.dart';
 import 'package:polymer/polymer.dart';
+import 'package:observatory/elements.dart';
 
-main() {
+main() async {
   Logger.root.level = Level.INFO;
   Logger.root.onRecord.listen((LogRecord rec) {
       if (rec.level == Level.WARNING &&
@@ -17,13 +18,10 @@
       }
       print('${rec.level.name}: ${rec.time}: ${rec.message}');
   });
+  await initElements();
   Logger.root.info('Starting Observatory');
-  initPolymer().then((zone) {
-    Logger.root.info('Polymer initialized');
-    // Code here is in the polymer Zone, which ensures that
-    // @observable properties work correctly.
-    Polymer.onReady.then((_) {
-      Logger.root.info('Polymer elements have been upgraded');
-    });
-  });
+  await initPolymer();
+  Logger.root.info('Polymer initialized');
+  await Polymer.onReady;
+  Logger.root.info('Polymer elements have been upgraded');
 }
diff --git a/runtime/platform/assert.cc b/runtime/platform/assert.cc
index c5b91e7..ff71e3f 100644
--- a/runtime/platform/assert.cc
+++ b/runtime/platform/assert.cc
@@ -34,9 +34,8 @@
             arguments);
   va_end(arguments);
 
-  // Print the buffer on stderr.
-  fprintf(stderr, "%s\n", buffer);
-  fflush(stderr);
+  // Print the buffer on stderr and/or syslog.
+  OS::PrintErr("%s\n", buffer);
 
   // In case of failed assertions, abort right away. Otherwise, wait
   // until the program is exiting before producing a non-zero exit
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 5e3b011..3a3ed26 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -113,6 +113,9 @@
 // Windows, both 32- and 64-bit, regardless of the check for _WIN32.
 #define TARGET_OS_WINDOWS 1
 
+#elif defined(__Fuchsia__)
+#define TARGET_OS_FUCHSIA
+
 #elif !defined(TARGET_OS_FUCHSIA)
 #error Automatic target os detection failed.
 #endif
diff --git a/runtime/platform/utils_fuchsia.h b/runtime/platform/utils_fuchsia.h
index 7054225..0129bfe 100644
--- a/runtime/platform/utils_fuchsia.h
+++ b/runtime/platform/utils_fuchsia.h
@@ -10,14 +10,24 @@
 namespace dart {
 
 inline int Utils::CountLeadingZeros(uword x) {
-  UNIMPLEMENTED();
-  return 0;
+#if defined(ARCH_IS_32_BIT)
+  return __builtin_clzl(x);
+#elif defined(ARCH_IS_64_BIT)
+  return __builtin_clzll(x);
+#else
+#error Architecture is not 32-bit or 64-bit.
+#endif
 }
 
 
 inline int Utils::CountTrailingZeros(uword x) {
-  UNIMPLEMENTED();
-  return 0;
+#if defined(ARCH_IS_32_BIT)
+  return __builtin_ctzl(x);
+#elif defined(ARCH_IS_64_BIT)
+  return __builtin_ctzll(x);
+#else
+#error Architecture is not 32-bit or 64-bit.
+#endif
 }
 
 
@@ -58,8 +68,8 @@
 
 
 inline char* Utils::StrError(int err, char* buffer, size_t bufsize) {
-  UNIMPLEMENTED();
-  return NULL;
+  snprintf(buffer, bufsize, "errno = %d", err);
+  return buffer;
 }
 
 }  // namespace dart
diff --git a/runtime/tests/vm/dart/double_materialize_test.dart b/runtime/tests/vm/dart/double_materialize_test.dart
new file mode 100644
index 0000000..2cab01c
--- /dev/null
+++ b/runtime/tests/vm/dart/double_materialize_test.dart
@@ -0,0 +1,23 @@
+// 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=--optimization_counter_threshold=10 --no-use-osr --no-background-compilation
+
+import "package:expect/expect.dart";
+
+double f(double x, double five, dynamic y) {
+  double z = x + five;
+  var a = y + 5;
+  return z + a.toDouble();
+}
+
+void main() {
+  double x = 1.0;
+  for (int i = 0; i < 1000; i++) {
+    x = f(x, 5.0, i);
+  }
+  x = f(x, 5.0, 1.0);
+  Expect.equals(509512.0, x);
+}
+
diff --git a/runtime/tests/vm/dart/double_to_smi_test.dart b/runtime/tests/vm/dart/double_to_smi_test.dart
new file mode 100644
index 0000000..06d6139
--- /dev/null
+++ b/runtime/tests/vm/dart/double_to_smi_test.dart
@@ -0,0 +1,23 @@
+// 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=--optimization_counter_threshold=10 --no-use-osr --no-background-compilation
+
+import "package:expect/expect.dart";
+
+int convert(dynamic d) {
+  return d.toInt();
+}
+
+main() {
+  double x = -100.0;
+  int count = 0;
+  while (x < 100.0) {
+    count = count + convert(x);
+    x = x + 0.5;
+  }
+  Expect.equals(-100, count);
+  count = convert(42);
+  Expect.equals(42, count);
+}
diff --git a/runtime/tests/vm/dart/hello_fuchsia_test.dart b/runtime/tests/vm/dart/hello_fuchsia_test.dart
new file mode 100644
index 0000000..501ffe7
--- /dev/null
+++ b/runtime/tests/vm/dart/hello_fuchsia_test.dart
@@ -0,0 +1,7 @@
+// 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.
+
+main() {
+  print("Hello, Fuchsia!");
+}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 1faa41c..7053458 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -163,9 +163,6 @@
 cc/RegExp_OneByteString: Skip
 cc/RegExp_TwoByteString: Skip
 
-# TODO(vegorov) Optimizing compiler is disabled for the SIMDBC
-cc/CompileFunctionOnHelperThread: Skip
-
 # TODO(vegorov) Field guards are disabled for SIMDBC
 cc/GuardFieldConstructor2Test: Skip
 cc/GuardFieldConstructorTest: Skip
@@ -186,33 +183,6 @@
 # This test is meaningless for DBC as allocation stubs are not used.
 cc/RegenerateAllocStubs: Skip
 
-# TODO(vegorov) Enable when DBC supports optimizing compiler.
-cc/Debug_InspectStack_Optimized: Skip
-cc/Debug_InspectStackWithClosure_Optimized: Skip
-
-# Isolate reload code assumes that all static calls have ICData attached to
-# them. However this is not the case on DBC.
-cc/IsolateReload_LiveStack: Skip
-cc/IsolateReload_StaticValuePreserved: Skip
-cc/IsolateReload_TopLevelFieldAdded: Skip
-cc/IsolateReload_ConstructorChanged: Skip
-cc/IsolateReload_ImplicitConstructorChanged: Skip
-cc/IsolateReload_MixinChanged: Skip
-cc/IsolateReload_SuperClassChanged: Skip
-cc/IsolateReload_ComplexInheritanceChange: Skip
-cc/IsolateReload_LibraryImportAdded: Skip
-cc/IsolateReload_LibraryHide: Skip
-cc/IsolateReload_LibraryLookup: Skip
-cc/IsolateReload_LibraryShow: Skip
-cc/IsolateReload_LiveStack: Skip
-cc/IsolateReload_StaticValuePreserved: Skip
-cc/IsolateReload_TopLevelFieldAdded: Skip
-cc/IsolateReload_ConstructorChanged: Skip
-cc/IsolateReload_ImplicitConstructorChanged: Skip
-cc/IsolateReload_MixinChanged: Skip
-cc/IsolateReload_SuperClassChanged: Skip
-cc/IsolateReload_ComplexInheritanceChange: Skip
-cc/IsolateReload_LibraryImportAdded: Skip
-cc/IsolateReload_LibraryHide: Skip
-cc/IsolateReload_LibraryLookup: Skip
-cc/IsolateReload_LibraryShow: Skip
+[ $hot_reload ]
+dart/spawn_shutdown_test: Skip # We can shutdown an isolate before it reloads.
+dart/spawn_infinite_loop_test: Skip # We can shutdown an isolate before it reloads.
diff --git a/runtime/tools/create_resources.py b/runtime/tools/create_resources.py
old mode 100644
new mode 100755
index 27c9d78..1e97496
--- a/runtime/tools/create_resources.py
+++ b/runtime/tools/create_resources.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
 # Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
diff --git a/runtime/tools/gen_library_src_paths.py b/runtime/tools/gen_library_src_paths.py
old mode 100644
new mode 100755
diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn
index f1c2da4..b22a9d5 100644
--- a/runtime/vm/BUILD.gn
+++ b/runtime/vm/BUILD.gn
@@ -3,15 +3,17 @@
 # BSD-style license that can be found in the LICENSE file.
 
 config("libdart_vm_config") {
-  libs = [
-    "dl",
-  ]
+  # TODO(zra, jamesr): This check can go away after some problems with the
+  # fuchsia toolchain definition are fixed.
+  if (!defined(is_fuchsia) || !is_fuchsia) {
+    libs = [ "dl" ]
 
-  if (!is_android) {
-    libs += [ "pthread" ]
+    if (!is_android) {
+      libs += [ "pthread" ]
 
-    if (is_linux) {
-      libs += [ "rt" ]
+      if (is_linux) {
+        libs += [ "rt" ]
+      }
     }
   }
 }
diff --git a/runtime/vm/aot_optimizer.cc b/runtime/vm/aot_optimizer.cc
index cdc4753..3d4b07f 100644
--- a/runtime/vm/aot_optimizer.cc
+++ b/runtime/vm/aot_optimizer.cc
@@ -1674,8 +1674,8 @@
 bool AotOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) {
   ASSERT(call->HasICData());
   const ICData& ic_data = *call->ic_data();
-  if ((ic_data.NumberOfUsedChecks() == 0) || !ic_data.HasOneTarget()) {
-    // No type feedback collected or multiple targets found.
+  if (ic_data.NumberOfUsedChecks() != 1) {
+    // No type feedback collected or multiple receivers/targets found.
     return false;
   }
 
@@ -1690,14 +1690,13 @@
       (recognized_kind == MethodRecognizer::kExternalOneByteStringCodeUnitAt) ||
       (recognized_kind == MethodRecognizer::kExternalTwoByteStringCodeUnitAt) ||
       (recognized_kind == MethodRecognizer::kGrowableArraySetData) ||
-      (recognized_kind == MethodRecognizer::kGrowableArraySetLength)) {
-      ASSERT(ic_data.NumberOfChecks() == 1);
+      (recognized_kind == MethodRecognizer::kGrowableArraySetLength) ||
+      (recognized_kind == MethodRecognizer::kSmi_bitAndFromSmi)) {
     return FlowGraphInliner::TryReplaceInstanceCallWithInline(
         flow_graph_, current_iterator(), call);
   }
 
-  if ((recognized_kind == MethodRecognizer::kStringBaseCharAt) &&
-      (ic_data.NumberOfChecks() == 1)) {
+  if (recognized_kind == MethodRecognizer::kStringBaseCharAt) {
       ASSERT((class_ids[0] == kOneByteStringCid) ||
              (class_ids[0] == kTwoByteStringCid) ||
              (class_ids[0] == kExternalOneByteStringCid) ||
@@ -1706,7 +1705,7 @@
         flow_graph_, current_iterator(), call);
   }
 
-  if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) {
+  if (class_ids[0] == kOneByteStringCid) {
     if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) {
       // This is an internal method, no need to check argument types nor
       // range.
@@ -1729,8 +1728,7 @@
   }
 
   if (CanUnboxDouble() &&
-      (recognized_kind == MethodRecognizer::kIntegerToDouble) &&
-      (ic_data.NumberOfChecks() == 1)) {
+      (recognized_kind == MethodRecognizer::kIntegerToDouble)) {
     if (class_ids[0] == kSmiCid) {
       AddReceiverCheck(call);
       ReplaceCall(call,
@@ -1799,21 +1797,20 @@
     }
   }
 
-  if (IsSupportedByteArrayViewCid(class_ids[0]) &&
-      (ic_data.NumberOfChecks() == 1)) {
+  if (IsSupportedByteArrayViewCid(class_ids[0])) {
     return FlowGraphInliner::TryReplaceInstanceCallWithInline(
         flow_graph_, current_iterator(), call);
   }
 
-  if ((class_ids[0] == kFloat32x4Cid) && (ic_data.NumberOfChecks() == 1)) {
+  if (class_ids[0] == kFloat32x4Cid) {
     return TryInlineFloat32x4Method(call, recognized_kind);
   }
 
-  if ((class_ids[0] == kInt32x4Cid) && (ic_data.NumberOfChecks() == 1)) {
+  if (class_ids[0] == kInt32x4Cid) {
     return TryInlineInt32x4Method(call, recognized_kind);
   }
 
-  if ((class_ids[0] == kFloat64x2Cid) && (ic_data.NumberOfChecks() == 1)) {
+  if (class_ids[0] == kFloat64x2Cid) {
     return TryInlineFloat64x2Method(call, recognized_kind);
   }
 
@@ -2050,6 +2047,10 @@
   return true;  // May deoptimize since we have not identified all 'true' tests.
 }
 
+// Tells whether the function of the call matches the core private name.
+static bool matches_core(InstanceCallInstr* call, const String& name) {
+  return call->function_name().raw() == Library::PrivateCoreLibName(name).raw();
+}
 
 // TODO(srdjan): Use ICData to check if always true or false.
 void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
@@ -2060,26 +2061,27 @@
   bool negate = false;
   if (call->ArgumentCount() == 2) {
     type_args = flow_graph()->constant_null();
-    if (call->function_name().raw() ==
-        Library::PrivateCoreLibName(Symbols::_instanceOfNum()).raw()) {
-      type = Type::Number();
-    } else if (call->function_name().raw() ==
-        Library::PrivateCoreLibName(Symbols::_instanceOfInt()).raw()) {
-      type = Type::IntType();
-    } else if (call->function_name().raw() ==
-        Library::PrivateCoreLibName(Symbols::_instanceOfSmi()).raw()) {
-      type = Type::SmiType();
-    } else if (call->function_name().raw() ==
-        Library::PrivateCoreLibName(Symbols::_instanceOfDouble()).raw()) {
-      type = Type::Double();
-    } else if (call->function_name().raw() ==
-        Library::PrivateCoreLibName(Symbols::_instanceOfString()).raw()) {
-      type = Type::StringType();
+    if (matches_core(call, Symbols::_simpleInstanceOf())) {
+      type =
+          AbstractType::Cast(call->ArgumentAt(1)->AsConstant()->value()).raw();
+      negate = false;  // Just to be sure.
     } else {
-      UNIMPLEMENTED();
+      if (matches_core(call, Symbols::_instanceOfNum())) {
+        type = Type::Number();
+      } else if (matches_core(call, Symbols::_instanceOfInt())) {
+        type = Type::IntType();
+      } else if (matches_core(call, Symbols::_instanceOfSmi())) {
+        type = Type::SmiType();
+      } else if (matches_core(call, Symbols::_instanceOfDouble())) {
+        type = Type::Double();
+      } else if (matches_core(call, Symbols::_instanceOfString())) {
+        type = Type::StringType();
+      } else {
+        UNIMPLEMENTED();
+      }
+      negate = Bool::Cast(call->ArgumentAt(1)->OriginalDefinition()
+                          ->AsConstant()->value()).value();
     }
-    negate = Bool::Cast(call->ArgumentAt(1)->OriginalDefinition()
-        ->AsConstant()->value()).value();
   } else {
     type_args = call->ArgumentAt(1);
     type = AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()).raw();
@@ -2746,4 +2748,26 @@
 }
 
 
+void AotOptimizer::ReplaceArrayBoundChecks() {
+  for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
+       !block_it.Done();
+       block_it.Advance()) {
+    ForwardInstructionIterator it(block_it.Current());
+    current_iterator_ = &it;
+    for (; !it.Done(); it.Advance()) {
+      CheckArrayBoundInstr* check = it.Current()->AsCheckArrayBound();
+      if (check != NULL) {
+        GenericCheckBoundInstr* new_check = new(Z) GenericCheckBoundInstr(
+            new(Z) Value(check->length()->definition()),
+            new(Z) Value(check->index()->definition()),
+            check->deopt_id());
+        flow_graph_->InsertBefore(check, new_check,
+                                  check->env(), FlowGraph::kEffect);
+        current_iterator()->RemoveCurrentFromGraph();
+      }
+    }
+  }
+}
+
+
 }  // namespace dart
diff --git a/runtime/vm/aot_optimizer.h b/runtime/vm/aot_optimizer.h
index 1afdadd..6c4586e 100644
--- a/runtime/vm/aot_optimizer.h
+++ b/runtime/vm/aot_optimizer.h
@@ -46,6 +46,8 @@
   // Merge instructions (only per basic-block).
   void TryOptimizePatterns();
 
+  void ReplaceArrayBoundChecks();
+
   virtual void VisitStaticCall(StaticCallInstr* instr);
   virtual void VisitInstanceCall(InstanceCallInstr* instr);
   virtual void VisitLoadCodeUnits(LoadCodeUnitsInstr* instr);
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index 2e39e22..db7881d 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -1921,47 +1921,6 @@
 }
 
 
-void Assembler::ComputeRange(Register result,
-                             Register value,
-                             Register scratch,
-                             Label* not_mint) {
-  const Register hi = TMP;
-  const Register lo = scratch;
-
-  Label done;
-  mov(result, Operand(value, LSR, kBitsPerWord - 1));
-  tst(value, Operand(kSmiTagMask));
-  b(&done, EQ);
-  CompareClassId(value, kMintCid, result);
-  b(not_mint, NE);
-  ldr(hi, FieldAddress(value, Mint::value_offset() + kWordSize));
-  ldr(lo, FieldAddress(value, Mint::value_offset()));
-  rsb(result, hi, Operand(ICData::kInt32RangeBit));
-  cmp(hi, Operand(lo, ASR, kBitsPerWord - 1));
-  b(&done, EQ);
-  LoadImmediate(result, ICData::kUint32RangeBit);  // Uint32
-  tst(hi, Operand(hi));
-  LoadImmediate(result, ICData::kInt64RangeBit, NE);  // Int64
-  Bind(&done);
-}
-
-
-void Assembler::UpdateRangeFeedback(Register value,
-                                    intptr_t index,
-                                    Register ic_data,
-                                    Register scratch1,
-                                    Register scratch2,
-                                    Label* miss) {
-  ASSERT(ICData::IsValidRangeFeedbackIndex(index));
-  ComputeRange(scratch1, value, scratch2, miss);
-  ldr(scratch2, FieldAddress(ic_data, ICData::state_bits_offset()));
-  orr(scratch2,
-      scratch2,
-      Operand(scratch1, LSL, ICData::RangeFeedbackShift(index)));
-  str(scratch2, FieldAddress(ic_data, ICData::state_bits_offset()));
-}
-
-
 static bool CanEncodeBranchOffset(int32_t offset) {
   ASSERT(Utils::IsAligned(offset, 4));
   return Utils::IsInt(Utils::CountOneBits(kBranchOffsetMask), offset);
@@ -3278,6 +3237,18 @@
 }
 
 
+#ifndef PRODUCT
+void Assembler::MaybeTraceAllocation(intptr_t cid,
+                                     Register temp_reg,
+                                     Label* trace) {
+  LoadAllocationStatsAddress(temp_reg, cid);
+  const uword state_offset = ClassHeapStats::state_offset();
+  ldr(temp_reg, Address(temp_reg, state_offset));
+  tst(temp_reg, Operand(ClassHeapStats::TraceAllocationMask()));
+  b(trace, NE);
+}
+
+
 void Assembler::LoadAllocationStatsAddress(Register dest,
                                            intptr_t cid) {
   ASSERT(dest != kNoRegister);
@@ -3292,17 +3263,6 @@
 }
 
 
-void Assembler::MaybeTraceAllocation(intptr_t cid,
-                                     Register temp_reg,
-                                     Label* trace) {
-  LoadAllocationStatsAddress(temp_reg, cid);
-  const uword state_offset = ClassHeapStats::state_offset();
-  ldr(temp_reg, Address(temp_reg, state_offset));
-  tst(temp_reg, Operand(ClassHeapStats::TraceAllocationMask()));
-  b(trace, NE);
-}
-
-
 void Assembler::IncrementAllocationStats(Register stats_addr_reg,
                                          intptr_t cid,
                                          Heap::Space space) {
@@ -3339,6 +3299,7 @@
   add(TMP, TMP, Operand(size_reg));
   str(TMP, size_address);
 }
+#endif  // !PRODUCT
 
 
 void Assembler::TryAllocate(const Class& cls,
diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h
index cac760b..184f28d 100644
--- a/runtime/vm/assembler_arm.h
+++ b/runtime/vm/assembler_arm.h
@@ -794,18 +794,6 @@
   void LoadClassIdMayBeSmi(Register result, Register object);
   void LoadTaggedClassIdMayBeSmi(Register result, Register object);
 
-  void ComputeRange(Register result,
-                    Register value,
-                    Register scratch,
-                    Label* miss);
-
-  void UpdateRangeFeedback(Register value,
-                           intptr_t idx,
-                           Register ic_data,
-                           Register scratch1,
-                           Register scratch2,
-                           Label* miss);
-
   intptr_t FindImmediate(int32_t imm);
   bool CanLoadFromObjectPool(const Object& object) const;
   void LoadFromOffset(OperandSize type,
@@ -919,6 +907,11 @@
     b(is_smi, CC);
   }
 
+  void BranchIfNotSmi(Register reg, Label* label) {
+    tst(reg, Operand(kSmiTagMask));
+    b(label, NE);
+  }
+
   void CheckCodePointer();
 
   // Function frame setup and tear down.
diff --git a/runtime/vm/assembler_arm64.cc b/runtime/vm/assembler_arm64.cc
index 26c0b4a..54dcabb 100644
--- a/runtime/vm/assembler_arm64.cc
+++ b/runtime/vm/assembler_arm64.cc
@@ -1036,51 +1036,6 @@
 }
 
 
-void Assembler::ComputeRange(Register result,
-                             Register value,
-                             Register scratch,
-                             Label* not_mint) {
-  Label done, not_smi;
-  tsti(value, Immediate(kSmiTagMask));
-  b(&not_smi, NE);
-
-  AsrImmediate(scratch, value, 32);
-  LoadImmediate(result, ICData::kUint32RangeBit);
-  cmp(scratch, Operand(1));
-  b(&done, EQ);
-
-  neg(scratch, scratch);
-  add(result, scratch, Operand(ICData::kInt32RangeBit));
-  cmp(scratch, Operand(1));
-  LoadImmediate(TMP, ICData::kSignedRangeBit);
-  csel(result, result, TMP, LS);
-  b(&done);
-
-  Bind(&not_smi);
-  CompareClassId(value, kMintCid);
-  b(not_mint, NE);
-
-  LoadImmediate(result, ICData::kInt64RangeBit);
-  Bind(&done);
-}
-
-
-void Assembler::UpdateRangeFeedback(Register value,
-                                    intptr_t index,
-                                    Register ic_data,
-                                    Register scratch1,
-                                    Register scratch2,
-                                    Label* miss) {
-  ASSERT(ICData::IsValidRangeFeedbackIndex(index));
-  ComputeRange(scratch1, value, scratch2, miss);
-  ldr(scratch2, FieldAddress(ic_data, ICData::state_bits_offset()), kWord);
-  orrw(scratch2,
-       scratch2,
-       Operand(scratch1, LSL, ICData::RangeFeedbackShift(index)));
-  str(scratch2, FieldAddress(ic_data, ICData::state_bits_offset()), kWord);
-}
-
-
 // Frame entry and exit.
 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) {
   // Reserve space for arguments and align frame before entering
@@ -1288,6 +1243,23 @@
 }
 
 
+#ifndef PRODUCT
+void Assembler::MaybeTraceAllocation(intptr_t cid,
+                                     Register temp_reg,
+                                     Label* trace) {
+  ASSERT(cid > 0);
+  intptr_t state_offset = ClassTable::StateOffsetFor(cid);
+  LoadIsolate(temp_reg);
+  intptr_t table_offset =
+      Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+  ldr(temp_reg, Address(temp_reg, table_offset));
+  AddImmediate(temp_reg, temp_reg, state_offset);
+  ldr(temp_reg, Address(temp_reg, 0));
+  tsti(temp_reg, Immediate(ClassHeapStats::TraceAllocationMask()));
+  b(trace, NE);
+}
+
+
 void Assembler::UpdateAllocationStats(intptr_t cid,
                                       Heap::Space space) {
   ASSERT(cid > 0);
@@ -1327,22 +1299,7 @@
   add(TMP, TMP, Operand(size_reg));
   str(TMP, Address(TMP2, size_field_offset));
 }
-
-
-void Assembler::MaybeTraceAllocation(intptr_t cid,
-                                     Register temp_reg,
-                                     Label* trace) {
-  ASSERT(cid > 0);
-  intptr_t state_offset = ClassTable::StateOffsetFor(cid);
-  LoadIsolate(temp_reg);
-  intptr_t table_offset =
-      Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
-  ldr(temp_reg, Address(temp_reg, table_offset));
-  AddImmediate(temp_reg, temp_reg, state_offset);
-  ldr(temp_reg, Address(temp_reg, 0));
-  tsti(temp_reg, Immediate(ClassHeapStats::TraceAllocationMask()));
-  b(trace, NE);
-}
+#endif  // !PRODUCT
 
 
 void Assembler::TryAllocate(const Class& cls,
diff --git a/runtime/vm/assembler_arm64.h b/runtime/vm/assembler_arm64.h
index 8080ab8..c39e8e3 100644
--- a/runtime/vm/assembler_arm64.h
+++ b/runtime/vm/assembler_arm64.h
@@ -1219,6 +1219,11 @@
     LslImmediate(dst, src, kSmiTagSize);
   }
 
+  void BranchIfNotSmi(Register reg, Label* label) {
+    tsti(reg, Immediate(kSmiTagMask));
+    b(label, NE);
+  }
+
   void Branch(const StubEntry& stub_entry,
               Register pp,
               Patchability patchable = kNotPatchable);
@@ -1337,18 +1342,6 @@
   void LoadClassIdMayBeSmi(Register result, Register object);
   void LoadTaggedClassIdMayBeSmi(Register result, Register object);
 
-  void ComputeRange(Register result,
-                    Register value,
-                    Register scratch,
-                    Label* miss);
-
-  void UpdateRangeFeedback(Register value,
-                           intptr_t idx,
-                           Register ic_data,
-                           Register scratch1,
-                           Register scratch2,
-                           Label* miss);
-
   void SetupDartSP();
   void RestoreCSP();
 
diff --git a/runtime/vm/assembler_arm64_test.cc b/runtime/vm/assembler_arm64_test.cc
index 7c7a620..329466a 100644
--- a/runtime/vm/assembler_arm64_test.cc
+++ b/runtime/vm/assembler_arm64_test.cc
@@ -3634,68 +3634,6 @@
   __ ret();
 }
 
-
-ASSEMBLER_TEST_GENERATE(ComputeRange, assembler) {
-  __ SetupDartSP();
-  EnterTestFrame(assembler);
-  Label miss, done;
-  __ ComputeRange(R0, R2, R3, &miss);
-  __ b(&done);
-
-  __ Bind(&miss);
-  __ LoadImmediate(R0, -1);
-
-  __ Bind(&done);
-  LeaveTestFrame(assembler);
-  __ RestoreCSP();
-  __ ret();
-}
-
-
-ASSEMBLER_TEST_RUN(ComputeRange, test) {
-#define RANGE_OF(arg_type, v)                                                  \
-  test->InvokeWithCodeAndThread<intptr_t, arg_type>(v)
-
-  EXPECT_EQ(ICData::kInt32RangeBit, RANGE_OF(RawSmi*, Smi::New(0)));
-  EXPECT_EQ(ICData::kInt32RangeBit, RANGE_OF(RawSmi*, Smi::New(1)));
-  EXPECT_EQ(ICData::kInt32RangeBit, RANGE_OF(RawSmi*, Smi::New(kMaxInt32)));
-  EXPECT_EQ(ICData::kInt32RangeBit | ICData::kSignedRangeBit,
-            RANGE_OF(RawSmi*, Smi::New(-1)));
-  EXPECT_EQ(ICData::kInt32RangeBit | ICData::kSignedRangeBit,
-            RANGE_OF(RawSmi*, Smi::New(kMinInt32)));
-
-  EXPECT_EQ(ICData::kUint32RangeBit,
-            RANGE_OF(RawSmi*, Smi::New(static_cast<int64_t>(kMaxInt32) + 1)));
-  EXPECT_EQ(ICData::kUint32RangeBit,
-            RANGE_OF(RawSmi*, Smi::New(kMaxUint32)));
-
-  // On 64-bit platforms we don't track the sign of the smis outside of
-  // int32 range because it is not needed to distinguish kInt32Range from
-  // kUint32Range.
-  EXPECT_EQ(ICData::kSignedRangeBit,
-            RANGE_OF(RawSmi*, Smi::New(static_cast<int64_t>(kMinInt32) - 1)));
-  EXPECT_EQ(ICData::kSignedRangeBit,
-            RANGE_OF(RawSmi*, Smi::New(static_cast<int64_t>(kMaxUint32) + 1)));
-  EXPECT_EQ(ICData::kSignedRangeBit,
-            RANGE_OF(RawSmi*, Smi::New(Smi::kMaxValue)));
-  EXPECT_EQ(ICData::kSignedRangeBit, RANGE_OF(RawSmi*,
-            Smi::New(Smi::kMinValue)));
-
-  EXPECT_EQ(ICData::kInt64RangeBit,
-            RANGE_OF(RawInteger*, Integer::New(Smi::kMaxValue + 1)));
-  EXPECT_EQ(ICData::kInt64RangeBit,
-            RANGE_OF(RawInteger*, Integer::New(Smi::kMinValue - 1)));
-  EXPECT_EQ(ICData::kInt64RangeBit,
-            RANGE_OF(RawInteger*, Integer::New(kMaxInt64)));
-  EXPECT_EQ(ICData::kInt64RangeBit,
-            RANGE_OF(RawInteger*, Integer::New(kMinInt64)));
-
-  EXPECT_EQ(-1, RANGE_OF(RawBool*, Bool::True().raw()));
-
-#undef RANGE_OF
-}
-
-
 }  // namespace dart
 
 #endif  // defined(TARGET_ARCH_ARM64)
diff --git a/runtime/vm/assembler_arm_test.cc b/runtime/vm/assembler_arm_test.cc
index 1e6e6ef..7eca350 100644
--- a/runtime/vm/assembler_arm_test.cc
+++ b/runtime/vm/assembler_arm_test.cc
@@ -3961,58 +3961,6 @@
   __ Ret();
 }
 
-
-ASSEMBLER_TEST_GENERATE(ComputeRange, assembler) {
-  Label miss, done;
-  __ mov(R1, Operand(R0));
-  __ ComputeRange(R0, R1, R2, &miss);
-  __ b(&done);
-
-  __ Bind(&miss);
-  __ LoadImmediate(R0, -1);
-
-  __ Bind(&done);
-  __ Ret();
-}
-
-
-ASSEMBLER_TEST_RUN(ComputeRange, test) {
-  typedef intptr_t (*ComputeRange)(intptr_t value) DART_UNUSED;
-
-#define RANGE_OF(v)                                              \
-  (EXECUTE_TEST_CODE_INTPTR_INTPTR(                              \
-    ComputeRange, test->entry(), reinterpret_cast<intptr_t>(v)))
-
-  EXPECT_EQ(0, RANGE_OF(Smi::New(0)));
-  EXPECT_EQ(0, RANGE_OF(Smi::New(1)));
-  EXPECT_EQ(ICData::kSignedRangeBit, RANGE_OF(Smi::New(-1)));
-  EXPECT_EQ(0, RANGE_OF(Smi::New(Smi::kMaxValue)));
-  EXPECT_EQ(ICData::kSignedRangeBit, RANGE_OF(Smi::New(Smi::kMinValue)));
-
-  EXPECT_EQ(ICData::kInt32RangeBit, RANGE_OF(Integer::New(Smi::kMaxValue + 1)));
-  EXPECT_EQ(ICData::kInt32RangeBit | ICData::kSignedRangeBit,
-            RANGE_OF(Integer::New(Smi::kMinValue - 1)));
-  EXPECT_EQ(ICData::kInt32RangeBit, RANGE_OF(Integer::New(kMaxInt32)));
-  EXPECT_EQ(ICData::kInt32RangeBit | ICData::kSignedRangeBit,
-            RANGE_OF(Integer::New(kMinInt32)));
-
-  EXPECT_EQ(ICData::kUint32RangeBit,
-            RANGE_OF(Integer::New(static_cast<int64_t>(kMaxInt32) + 1)));
-  EXPECT_EQ(ICData::kUint32RangeBit,
-            RANGE_OF(Integer::New(kMaxUint32)));
-
-  EXPECT_EQ(ICData::kInt64RangeBit,
-            RANGE_OF(Integer::New(static_cast<int64_t>(kMaxUint32) + 1)));
-  EXPECT_EQ(ICData::kInt64RangeBit,
-            RANGE_OF(Integer::New(static_cast<int64_t>(kMinInt32) - 1)));
-  EXPECT_EQ(ICData::kInt64RangeBit, RANGE_OF(Integer::New(kMaxInt64)));
-  EXPECT_EQ(ICData::kInt64RangeBit, RANGE_OF(Integer::New(kMinInt64)));
-
-  EXPECT_EQ(-1, RANGE_OF(Bool::True().raw()));
-
-#undef RANGE_OF
-}
-
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_ARM
diff --git a/runtime/vm/assembler_dbc.h b/runtime/vm/assembler_dbc.h
index 590dd5c..7e23863 100644
--- a/runtime/vm/assembler_dbc.h
+++ b/runtime/vm/assembler_dbc.h
@@ -166,6 +166,8 @@
 
   intptr_t AddConstant(const Object& obj);
 
+  void Nop(intptr_t d) { Nop(0, d); }
+
  private:
   AssemblerBuffer buffer_;  // Contains position independent code.
   ObjectPoolWrapper object_pool_wrapper_;
diff --git a/runtime/vm/assembler_dbc_test.cc b/runtime/vm/assembler_dbc_test.cc
index 180437e..254f638 100644
--- a/runtime/vm/assembler_dbc_test.cc
+++ b/runtime/vm/assembler_dbc_test.cc
@@ -28,6 +28,8 @@
     (Bool::RawCast(ExecuteTest(code)) == Bool::True().raw())
 #define EXECUTE_TEST_CODE_OBJECT(code)                                         \
     Object::Handle(ExecuteTest(code))
+#define EXECUTE_TEST_CODE_DOUBLE(code)                                         \
+    bit_cast<double, RawObject*>(ExecuteTest(code))
 
 #define __ assembler->
 
@@ -1650,6 +1652,91 @@
 }
 
 
+//  - TestCids rA, D
+//
+//    The next D instructions must be Nops whose D field encodes a class id. If
+//    the class id of FP[rA] matches, jump to PC + N + 1 if the matching Nop's
+//    A != 0 or PC + N + 2 if the matching Nop's A = 0. If no match is found,
+//    jump to PC + N.
+ASSEMBLER_TEST_GENERATE(TestCidsTrue, assembler) {
+  Label true_branch, no_match_branch;
+  __ Frame(2);
+  __ LoadConstant(0, Object::Handle(String::New("Hi", Heap::kOld)));
+  const intptr_t num_cases = 2;
+  __ TestCids(0, num_cases);
+  __ Nop(0, static_cast<uint16_t>(kSmiCid));            // Smi    => false
+  __ Nop(1, static_cast<uint16_t>(kOneByteStringCid));  // String => true
+  __ Jump(&no_match_branch);
+  __ Jump(&true_branch);
+  __ LoadConstant(1, Smi::Handle(Smi::New(0)));  // false branch
+  __ Return(1);
+  __ Bind(&true_branch);
+  __ LoadConstant(1, Smi::Handle(Smi::New(1)));
+  __ Return(1);
+  __ Bind(&no_match_branch);
+  __ LoadConstant(1, Smi::Handle(Smi::New(2)));
+  __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(TestCidsTrue, test) {
+  EXPECT_EQ(1, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(TestCidsFalse, assembler) {
+  Label true_branch, no_match_branch;
+  __ Frame(2);
+  __ LoadConstant(0, Object::Handle(Smi::New(42)));
+  const intptr_t num_cases = 2;
+  __ TestCids(0, num_cases);
+  __ Nop(0, static_cast<uint16_t>(kSmiCid));            // Smi    => false
+  __ Nop(1, static_cast<uint16_t>(kOneByteStringCid));  // String => true
+  __ Jump(&no_match_branch);
+  __ Jump(&true_branch);
+  __ LoadConstant(1, Smi::Handle(Smi::New(0)));  // false branch
+  __ Return(1);
+  __ Bind(&true_branch);
+  __ LoadConstant(1, Smi::Handle(Smi::New(1)));
+  __ Return(1);
+  __ Bind(&no_match_branch);
+  __ LoadConstant(1, Smi::Handle(Smi::New(2)));
+  __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(TestCidsFalse, test) {
+  EXPECT_EQ(0, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(TestCidsNoMatch, assembler) {
+  Label true_branch, no_match_branch;
+  __ Frame(2);
+  __ LoadConstant(0, Object::Handle(Array::New(1, Heap::kOld)));
+  const intptr_t num_cases = 2;
+  __ TestCids(0, num_cases);
+  __ Nop(0, static_cast<uint16_t>(kSmiCid));            // Smi    => false
+  __ Nop(1, static_cast<uint16_t>(kOneByteStringCid));  // String => true
+  __ Jump(&no_match_branch);
+  __ Jump(&true_branch);
+  __ LoadConstant(1, Smi::Handle(Smi::New(0)));  // false branch
+  __ Return(1);
+  __ Bind(&true_branch);
+  __ LoadConstant(1, Smi::Handle(Smi::New(1)));
+  __ Return(1);
+  __ Bind(&no_match_branch);
+  __ LoadConstant(1, Smi::Handle(Smi::New(2)));
+  __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(TestCidsNoMatch, test) {
+  EXPECT_EQ(2, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+
 //  - CheckSmi rA
 //
 //    If FP[rA] is a Smi, then skip the next instruction.
@@ -1688,9 +1775,10 @@
 //    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);
+  __ Frame(2);
   __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ CheckClassId(0, kSmiCid);
+  __ LoadClassId(1, 0);
+  __ CheckClassId(1, kSmiCid);
   __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
   __ Return(0);
 }
@@ -1702,9 +1790,10 @@
 
 
 ASSEMBLER_TEST_GENERATE(CheckClassIdNonSmiPass, assembler) {
-  __ Frame(1);
+  __ Frame(2);
   __ LoadConstant(0, Bool::True());
-  __ CheckClassId(0, kBoolCid);
+  __ LoadClassId(1, 0);
+  __ CheckClassId(1, kBoolCid);
   __ LoadConstant(0, Bool::False());
   __ Return(0);
 }
@@ -1716,9 +1805,10 @@
 
 
 ASSEMBLER_TEST_GENERATE(CheckClassIdFail, assembler) {
-  __ Frame(1);
+  __ Frame(2);
   __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ CheckClassId(0, kBoolCid);
+  __ LoadClassId(1, 0);
+  __ CheckClassId(1, kBoolCid);
   __ LoadConstant(0, Smi::Handle(Smi::New(42)));
   __ Return(0);
 }
@@ -1792,6 +1882,948 @@
   EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
 }
 
+//  - If<Cond> rA, rD
+//
+//    Cond is Le, Lt, Ge, Gt, unsigned variants ULe, ULt, UGe, UGt, and
+//    unboxed double variants DEq, DNe, DLe, DLt, DGe, DGt.
+//    Skips the next instruction unless FP[rA] <Cond> FP[rD]. Assumes that
+//    FP[rA] and FP[rD] are Smis or unboxed doubles as inidcated by <Cond>.
+ASSEMBLER_TEST_GENERATE(IfLeTrue, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(-5)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(100)));
+  __ IfLe(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfLeTrue, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfLeFalse, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(100)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-5)));
+  __ IfLe(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfLeFalse, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfLtTrue, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(-5)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(100)));
+  __ IfLt(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfLtTrue, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfLtFalse, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(100)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-5)));
+  __ IfLt(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfLtFalse, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfGeTrue, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(100)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-5)));
+  __ IfGe(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfGeTrue, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfGeFalse, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(-5)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(100)));
+  __ IfGe(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfGeFalse, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfGtTrue, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(100)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-5)));
+  __ IfGt(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfGtTrue, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfGtFalse, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(-5)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(100)));
+  __ IfGt(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfGtFalse, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+#if defined(ARCH_IS_64_BIT)
+ASSEMBLER_TEST_GENERATE(IfDNeTrue, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld)));
+  __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld)));
+  __ UnboxDouble(1, 1);
+  __ UnboxDouble(2, 2);
+  __ IfDNe(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfDNeTrue, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfDNeFalse, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld)));
+  __ LoadConstant(2, Double::Handle(Double::New(-5.0, Heap::kOld)));
+  __ UnboxDouble(1, 1);
+  __ UnboxDouble(2, 2);
+  __ IfDNe(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfDNeFalse, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfDNeNan, assembler) {
+  const double not_a_number = bit_cast<double, intptr_t>(0x7FF8000000000000LL);
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ LoadConstant(1, Double::Handle(Double::New(not_a_number, Heap::kOld)));
+  __ LoadConstant(2, Double::Handle(Double::New(not_a_number, Heap::kOld)));
+  __ UnboxDouble(1, 1);
+  __ UnboxDouble(2, 2);
+  __ IfDNe(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfDNeNan, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfDEqTrue, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld)));
+  __ LoadConstant(2, Double::Handle(Double::New(-5.0, Heap::kOld)));
+  __ UnboxDouble(1, 1);
+  __ UnboxDouble(2, 2);
+  __ IfDEq(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfDEqTrue, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfDEqFalse, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld)));
+  __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld)));
+  __ UnboxDouble(1, 1);
+  __ UnboxDouble(2, 2);
+  __ IfDEq(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfDEqFalse, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfDEqNan, assembler) {
+  const double not_a_number = bit_cast<double, intptr_t>(0x7FF8000000000000LL);
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Double::Handle(Double::New(not_a_number, Heap::kOld)));
+  __ LoadConstant(2, Double::Handle(Double::New(not_a_number, Heap::kOld)));
+  __ UnboxDouble(1, 1);
+  __ UnboxDouble(2, 2);
+  __ IfDEq(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfDEqNan, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfDLeTrue, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld)));
+  __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld)));
+  __ UnboxDouble(1, 1);
+  __ UnboxDouble(2, 2);
+  __ IfDLe(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfDLeTrue, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfDLeFalse, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Double::Handle(Double::New(100.0, Heap::kOld)));
+  __ LoadConstant(2, Double::Handle(Double::New(-5.0, Heap::kOld)));
+  __ UnboxDouble(1, 1);
+  __ UnboxDouble(2, 2);
+  __ IfDLe(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfDLeFalse, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfDLeNan, assembler) {
+  const double not_a_number = bit_cast<double, intptr_t>(0x7FF8000000000000LL);
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Double::Handle(Double::New(not_a_number, Heap::kOld)));
+  __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld)));
+  __ UnboxDouble(1, 1);
+  __ UnboxDouble(2, 2);
+  __ IfDLe(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfDLeNan, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfDLtTrue, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld)));
+  __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld)));
+  __ UnboxDouble(1, 1);
+  __ UnboxDouble(2, 2);
+  __ IfDLt(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfDLtTrue, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfDLtFalse, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Double::Handle(Double::New(100.0, Heap::kOld)));
+  __ LoadConstant(2, Double::Handle(Double::New(-5.0, Heap::kOld)));
+  __ UnboxDouble(1, 1);
+  __ UnboxDouble(2, 2);
+  __ IfDLt(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfDLtFalse, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfDLtNan, assembler) {
+  const double not_a_number = bit_cast<double, intptr_t>(0x7FF8000000000000LL);
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Double::Handle(Double::New(not_a_number, Heap::kOld)));
+  __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld)));
+  __ UnboxDouble(1, 1);
+  __ UnboxDouble(2, 2);
+  __ IfDLt(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfDLtNan, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfDGeTrue, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ LoadConstant(1, Double::Handle(Double::New(100.0, Heap::kOld)));
+  __ LoadConstant(2, Double::Handle(Double::New(-5.0, Heap::kOld)));
+  __ UnboxDouble(1, 1);
+  __ UnboxDouble(2, 2);
+  __ IfDGe(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfDGeTrue, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfDGeFalse, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld)));
+  __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld)));
+  __ UnboxDouble(1, 1);
+  __ UnboxDouble(2, 2);
+  __ IfDGe(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfDGeFalse, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfDGeNan, assembler) {
+  const double not_a_number = bit_cast<double, intptr_t>(0x7FF8000000000000LL);
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Double::Handle(Double::New(not_a_number, Heap::kOld)));
+  __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld)));
+  __ UnboxDouble(1, 1);
+  __ UnboxDouble(2, 2);
+  __ IfDGe(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfDGeNan, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfDGtTrue, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ LoadConstant(1, Double::Handle(Double::New(100.0, Heap::kOld)));
+  __ LoadConstant(2, Double::Handle(Double::New(-5.0, Heap::kOld)));
+  __ UnboxDouble(1, 1);
+  __ UnboxDouble(2, 2);
+  __ IfDGt(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfDGtTrue, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfDGtFalse, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld)));
+  __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld)));
+  __ UnboxDouble(1, 1);
+  __ UnboxDouble(2, 2);
+  __ IfDGt(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfDGtFalse, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfDGtNan, assembler) {
+  const double not_a_number = bit_cast<double, intptr_t>(0x7FF8000000000000LL);
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Double::Handle(Double::New(not_a_number, Heap::kOld)));
+  __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld)));
+  __ UnboxDouble(1, 1);
+  __ UnboxDouble(2, 2);
+  __ IfDGt(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfDGtNan, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+#endif  // defined(ARCH_IS_64_BIT)
+
+
+ASSEMBLER_TEST_GENERATE(IfULeTrue, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(5)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(100)));
+  __ IfULe(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfULeTrue, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfULeFalse, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(100)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(5)));
+  __ IfULe(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfULeFalse, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfULeNegTrue, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(5)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(-5)));
+  __ IfULe(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfULeNegTrue, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfULtTrue, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(5)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(100)));
+  __ IfULt(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfULtTrue, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfULtFalse, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(100)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(5)));
+  __ IfULt(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfULtFalse, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfUGeTrue, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(100)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(5)));
+  __ IfUGe(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfUGeTrue, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfUGeFalse, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(5)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(100)));
+  __ IfUGe(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfUGeFalse, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfUGtTrue, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(100)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(5)));
+  __ IfUGt(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfUGtTrue, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfUGtFalse, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(5)));
+  __ LoadConstant(2, Smi::Handle(Smi::New(100)));
+  __ IfUGt(1, 2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+  __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(IfUGtFalse, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+//  - Min, Max rA, rB, rC
+//
+//    FP[rA] <- {min, max}(FP[rB], FP[rC]). Assumes that FP[rB], and FP[rC] are
+//    Smis.
+ASSEMBLER_TEST_GENERATE(Min, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(500)));
+  __ Min(2, 0, 1);
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(Min, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Max, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(5)));
+  __ Max(2, 0, 1);
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(Max, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+#if defined(ARCH_IS_64_BIT)
+//  - UnboxDouble rA, rD
+//
+//    Unbox the double in FP[rD] into FP[rA]. Assumes FP[rD] is a double.
+//
+//  - CheckedUnboxDouble rA, rD
+//
+//    Unboxes FP[rD] into FP[rA] and skips the following instruction unless
+//    FP[rD] is not a double or a Smi. When FP[rD] is a Smi, converts it to a
+//    double.
+ASSEMBLER_TEST_GENERATE(Unbox, assembler) {
+  __ Frame(2);
+  __ LoadConstant(0, Double::Handle(Double::New(42.0, Heap::kOld)));
+  __ UnboxDouble(1, 0);
+  __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(Unbox, test) {
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(CheckedUnboxDouble, assembler) {
+  __ Frame(2);
+  __ LoadConstant(0, Double::Handle(Double::New(42.0, Heap::kOld)));
+  __ CheckedUnboxDouble(1, 0);
+  __ LoadConstant(1, Smi::Handle(Smi::New(0)));
+  __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(CheckedUnboxDouble, test) {
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(CheckedUnboxSmi, assembler) {
+  __ Frame(2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ CheckedUnboxDouble(1, 0);
+  __ LoadConstant(1, Smi::Handle(Smi::New(0)));
+  __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(CheckedUnboxSmi, test) {
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(CheckedUnboxFail, assembler) {
+  __ Frame(2);
+  __ LoadConstant(0, Bool::True());
+  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+  __ CheckedUnboxDouble(1, 0);
+  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
+  __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(CheckedUnboxFail, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+//  - DAdd, DSub, DMul, DDiv rA, rB, rC
+//
+//    Arithmetic operaions on unboxed doubles. FP[rA] <- FP[rB] op FP[rC].
+ASSEMBLER_TEST_GENERATE(DAdd, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Double::Handle(Double::New(41.0, Heap::kOld)));
+  __ LoadConstant(1, Double::Handle(Double::New(1.0, Heap::kOld)));
+  __ UnboxDouble(0, 0);
+  __ UnboxDouble(1, 1);
+  __ DAdd(2, 1, 0);
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(DAdd, test) {
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(DSub, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Double::Handle(Double::New(1.0, Heap::kOld)));
+  __ LoadConstant(1, Double::Handle(Double::New(43.0, Heap::kOld)));
+  __ UnboxDouble(0, 0);
+  __ UnboxDouble(1, 1);
+  __ DSub(2, 1, 0);
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(DSub, test) {
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(DMul, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Double::Handle(Double::New(6.0, Heap::kOld)));
+  __ LoadConstant(1, Double::Handle(Double::New(7.0, Heap::kOld)));
+  __ UnboxDouble(0, 0);
+  __ UnboxDouble(1, 1);
+  __ DMul(2, 1, 0);
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(DMul, test) {
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(DDiv, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Double::Handle(Double::New(2.0, Heap::kOld)));
+  __ LoadConstant(1, Double::Handle(Double::New(84.0, Heap::kOld)));
+  __ UnboxDouble(0, 0);
+  __ UnboxDouble(1, 1);
+  __ DDiv(2, 1, 0);
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(DDiv, test) {
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(DNeg, assembler) {
+  __ Frame(2);
+  __ LoadConstant(0, Double::Handle(Double::New(-42.0, Heap::kOld)));
+  __ UnboxDouble(0, 0);
+  __ DNeg(1, 0);
+  __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(DNeg, test) {
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(DSqrt, assembler) {
+  __ Frame(2);
+  __ LoadConstant(0, Double::Handle(Double::New(36.0, Heap::kOld)));
+  __ UnboxDouble(0, 0);
+  __ DSqrt(1, 0);
+  __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(DSqrt, test) {
+  EXPECT_EQ(6.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
+}
+
+
+//  - SmiToDouble rA, rD
+//
+//    Convert the Smi in FP[rD] to an unboxed double in FP[rA].
+//
+//  - DoubleToSmi rA, rD
+//
+//    If the unboxed double in FP[rD] can be converted to a Smi in FP[rA], then
+//    this instruction does so, and skips the following instruction. Otherwise,
+//    the following instruction is not skipped.
+ASSEMBLER_TEST_GENERATE(SmiToDouble, assembler) {
+  __ Frame(2);
+  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+  __ SmiToDouble(1, 0);
+  __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(SmiToDouble, test) {
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(DoubleToSmi, assembler) {
+  __ Frame(2);
+  __ LoadConstant(0, Double::Handle(Double::New(42.0, Heap::kOld)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+  __ UnboxDouble(0, 0);
+  __ DoubleToSmi(1, 0);
+  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+  __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(DoubleToSmi, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(DoubleToSmiNearMax, assembler) {
+  const double m = static_cast<double>(Smi::kMaxValue - 1000);
+  __ Frame(2);
+  __ LoadConstant(0, Double::Handle(Double::New(m, Heap::kOld)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
+  __ UnboxDouble(0, 0);
+  __ DoubleToSmi(0, 0);
+  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+  __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(DoubleToSmiNearMax, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(DoubleToSmiNearMin, assembler) {
+  const double m = static_cast<double>(Smi::kMinValue);
+  __ Frame(2);
+  __ LoadConstant(0, Double::Handle(Double::New(m, Heap::kOld)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
+  __ UnboxDouble(0, 0);
+  __ DoubleToSmi(0, 0);
+  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+  __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(DoubleToSmiNearMin, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(DoubleToSmiFailPos, assembler) {
+  const double pos_overflow = static_cast<double>(Smi::kMaxValue + 1);
+  __ Frame(2);
+  __ LoadConstant(0, Double::Handle(Double::New(pos_overflow, Heap::kOld)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+  __ UnboxDouble(0, 0);
+  __ DoubleToSmi(1, 0);
+  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
+  __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(DoubleToSmiFailPos, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(DoubleToSmiFailNeg, assembler) {
+  const double neg_overflow = static_cast<double>(Smi::kMinValue - 1000);
+  __ Frame(2);
+  __ LoadConstant(0, Double::Handle(Double::New(neg_overflow, Heap::kOld)));
+  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+  __ UnboxDouble(0, 0);
+  __ DoubleToSmi(1, 0);
+  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
+  __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(DoubleToSmiFailNeg, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(DMin, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Double::Handle(Double::New(42.0, Heap::kOld)));
+  __ LoadConstant(1, Double::Handle(Double::New(500.0, Heap::kOld)));
+  __ UnboxDouble(0, 0);
+  __ UnboxDouble(1, 1);
+  __ DMin(2, 0, 1);
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(DMin, test) {
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(DMax, assembler) {
+  __ Frame(3);
+  __ LoadConstant(0, Double::Handle(Double::New(42.0, Heap::kOld)));
+  __ LoadConstant(1, Double::Handle(Double::New(5.0, Heap::kOld)));
+  __ UnboxDouble(0, 0);
+  __ UnboxDouble(1, 1);
+  __ DMax(2, 0, 1);
+  __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(DMax, test) {
+  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
+}
+
+#endif  // defined(ARCH_IS_64_BIT)
+
 }  // namespace dart
 
 #endif  // defined(TARGET_ARCH_DBC)
diff --git a/runtime/vm/assembler_ia32.cc b/runtime/vm/assembler_ia32.cc
index 1bc37d8..bb57905 100644
--- a/runtime/vm/assembler_ia32.cc
+++ b/runtime/vm/assembler_ia32.cc
@@ -2569,6 +2569,7 @@
 }
 
 
+#ifndef PRODUCT
 void Assembler::MaybeTraceAllocation(intptr_t cid,
                                      Register temp_reg,
                                      Label* trace,
@@ -2626,6 +2627,7 @@
   intptr_t size_offset = ClassTable::SizeOffsetFor(cid, space == Heap::kNew);
   addl(Address(temp_reg, size_offset), Immediate(size_in_bytes));
 }
+#endif  // !PRODUCT
 
 
 void Assembler::TryAllocate(const Class& cls,
@@ -2939,47 +2941,6 @@
 }
 
 
-void Assembler::ComputeRange(Register result,
-                             Register value,
-                             Register lo_temp,
-                             Register hi_temp,
-                             Label* not_mint) {
-  Label done;
-  movl(result, value);
-  shrl(result, Immediate(kBitsPerWord - 1));  // Sign bit.
-  testl(value, Immediate(kSmiTagMask));
-  j(ZERO, &done, Assembler::kNearJump);
-  CompareClassId(value, kMintCid, result);
-  j(NOT_EQUAL, not_mint);
-  movl(lo_temp, FieldAddress(value, Mint::value_offset()));
-  movl(hi_temp, FieldAddress(value, Mint::value_offset() + kWordSize));
-  movl(result, Immediate(ICData::kInt32RangeBit));
-  subl(result, hi_temp);  // 10 (positive int32), 11 (negative int32)
-  sarl(lo_temp, Immediate(kBitsPerWord - 1));
-  cmpl(lo_temp, hi_temp);
-  j(EQUAL, &done, Assembler::kNearJump);
-  movl(result, Immediate(ICData::kUint32RangeBit));  // Uint32
-  cmpl(hi_temp, Immediate(0));
-  j(EQUAL, &done, Assembler::kNearJump);
-  movl(result, Immediate(ICData::kInt64RangeBit));  // Int64
-  Bind(&done);
-}
-
-
-void Assembler::UpdateRangeFeedback(Register value,
-                                    intptr_t index,
-                                    Register ic_data,
-                                    Register scratch1,
-                                    Register scratch2,
-                                    Register scratch3,
-                                    Label* miss) {
-  ASSERT(ICData::IsValidRangeFeedbackIndex(index));
-  ComputeRange(scratch1, value, scratch2, scratch3, miss);
-  shll(scratch1, Immediate(ICData::RangeFeedbackShift(index)));
-  orl(FieldAddress(ic_data, ICData::state_bits_offset()), scratch1);
-}
-
-
 Address Assembler::ElementAddressForIntIndex(bool is_external,
                                              intptr_t cid,
                                              intptr_t index_scale,
diff --git a/runtime/vm/assembler_ia32.h b/runtime/vm/assembler_ia32.h
index 77f77a6..df3d6ff 100644
--- a/runtime/vm/assembler_ia32.h
+++ b/runtime/vm/assembler_ia32.h
@@ -740,20 +740,6 @@
                             Register scratch,
                             Label* is_smi);
 
-  void ComputeRange(Register result,
-                    Register value,
-                    Register lo_temp,
-                    Register hi_temp,
-                    Label* miss);
-
-  void UpdateRangeFeedback(Register value,
-                           intptr_t index,
-                           Register ic_data,
-                           Register scratch1,
-                           Register scratch2,
-                           Register scratch3,
-                           Label* miss);
-
   static Address ElementAddressForIntIndex(bool is_external,
                                            intptr_t cid,
                                            intptr_t index_scale,
@@ -781,7 +767,11 @@
     sarl(reg, Immediate(kSmiTagSize));
   }
 
-  intptr_t PreferredLoopAlignment() { return 16; }
+  void BranchIfNotSmi(Register reg, Label* label) {
+    testl(reg, Immediate(kSmiTagMask));
+    j(NOT_ZERO, label);
+  }
+
   void Align(intptr_t alignment, intptr_t offset);
   void Bind(Label* label);
   void Jump(Label* label) { jmp(label); }
diff --git a/runtime/vm/assembler_ia32_test.cc b/runtime/vm/assembler_ia32_test.cc
index 2ce9da2..116cc9e 100644
--- a/runtime/vm/assembler_ia32_test.cc
+++ b/runtime/vm/assembler_ia32_test.cc
@@ -3425,58 +3425,6 @@
   EXPECT_EQ(1, reinterpret_cast<BitTest>(test->entry())());
 }
 
-
-ASSEMBLER_TEST_GENERATE(ComputeRange, assembler) {
-  Label miss, done;
-  __ movl(ECX, Address(ESP, 1 * kWordSize));
-
-  __ pushl(ESI);
-  __ pushl(EDI);
-  __ ComputeRange(EAX, ECX, ESI, EDI, &miss);
-  __ jmp(&done);
-
-  __ Bind(&miss);
-  __ movl(EAX, Immediate(-1));
-
-  __ Bind(&done);
-  __ popl(EDI);
-  __ popl(ESI);
-  __ ret();
-}
-
-
-ASSEMBLER_TEST_RUN(ComputeRange, test) {
-  typedef intptr_t (*ComputeRange)(RawObject* value);
-  ComputeRange range_of = reinterpret_cast<ComputeRange>(test->entry());
-
-  EXPECT_EQ(0, range_of(Smi::New(0)));
-  EXPECT_EQ(0, range_of(Smi::New(1)));
-  EXPECT_EQ(ICData::kSignedRangeBit, range_of(Smi::New(-1)));
-  EXPECT_EQ(0, range_of(Smi::New(Smi::kMaxValue)));
-  EXPECT_EQ(ICData::kSignedRangeBit, range_of(Smi::New(Smi::kMinValue)));
-
-  EXPECT_EQ(ICData::kInt32RangeBit, range_of(Integer::New(Smi::kMaxValue + 1)));
-  EXPECT_EQ(ICData::kInt32RangeBit | ICData::kSignedRangeBit,
-            range_of(Integer::New(Smi::kMinValue - 1)));
-  EXPECT_EQ(ICData::kInt32RangeBit, range_of(Integer::New(kMaxInt32)));
-  EXPECT_EQ(ICData::kInt32RangeBit | ICData::kSignedRangeBit,
-            range_of(Integer::New(kMinInt32)));
-
-  EXPECT_EQ(ICData::kUint32RangeBit,
-            range_of(Integer::New(static_cast<int64_t>(kMaxInt32) + 1)));
-  EXPECT_EQ(ICData::kUint32RangeBit, range_of(Integer::New(kMaxUint32)));
-
-  EXPECT_EQ(ICData::kInt64RangeBit,
-            range_of(Integer::New(static_cast<int64_t>(kMaxUint32) + 1)));
-  EXPECT_EQ(ICData::kInt64RangeBit,
-            range_of(Integer::New(static_cast<int64_t>(kMinInt32) - 1)));
-  EXPECT_EQ(ICData::kInt64RangeBit, range_of(Integer::New(kMaxInt64)));
-  EXPECT_EQ(ICData::kInt64RangeBit, range_of(Integer::New(kMinInt64)));
-
-  EXPECT_EQ(-1, range_of(Bool::True().raw()));
-}
-
-
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_IA32
diff --git a/runtime/vm/assembler_mips.cc b/runtime/vm/assembler_mips.cc
index ffd927d..954cea6 100644
--- a/runtime/vm/assembler_mips.cc
+++ b/runtime/vm/assembler_mips.cc
@@ -826,49 +826,6 @@
 }
 
 
-void Assembler::ComputeRange(Register result,
-                             Register value,
-                             Label* miss) {
-  const Register hi = TMP;
-  const Register lo = CMPRES2;
-
-  Label done;
-  srl(result, value, kBitsPerWord - 1);
-  andi(CMPRES1, value, Immediate(kSmiTagMask));
-  beq(CMPRES1, ZR, &done);
-
-  LoadClassId(CMPRES1, value);
-  BranchNotEqual(CMPRES1, Immediate(kMintCid), miss);
-  LoadFieldFromOffset(hi, value, Mint::value_offset() + kWordSize);
-  LoadFieldFromOffset(lo, value, Mint::value_offset());
-  sra(lo, lo, kBitsPerWord - 1);
-
-  LoadImmediate(result, ICData::kInt32RangeBit);
-
-  beq(hi, lo, &done);
-  delay_slot()->subu(result, result, hi);
-
-  beq(hi, ZR, &done);
-  delay_slot()->addiu(result, ZR, Immediate(ICData::kUint32RangeBit));
-  LoadImmediate(result, ICData::kInt64RangeBit);
-  Bind(&done);
-}
-
-
-void Assembler::UpdateRangeFeedback(Register value,
-                                    intptr_t index,
-                                    Register ic_data,
-                                    Register scratch,
-                                    Label* miss) {
-  ASSERT(ICData::IsValidRangeFeedbackIndex(index));
-  ComputeRange(scratch, value, miss);
-  LoadFieldFromOffset(TMP, ic_data, ICData::state_bits_offset());
-  sll(scratch, scratch, ICData::RangeFeedbackShift(index));
-  or_(TMP, TMP, scratch);
-  StoreFieldToOffset(TMP, ic_data, ICData::state_bits_offset());
-}
-
-
 void Assembler::EnterFrame() {
   ASSERT(!in_delay_slot_);
   addiu(SP, SP, Immediate(-2 * kWordSize));
@@ -903,6 +860,26 @@
 }
 
 
+#ifndef PRODUCT
+void Assembler::MaybeTraceAllocation(intptr_t cid,
+                                     Register temp_reg,
+                                     Label* trace) {
+  ASSERT(cid > 0);
+  ASSERT(!in_delay_slot_);
+  ASSERT(temp_reg != kNoRegister);
+  ASSERT(temp_reg != TMP);
+  intptr_t state_offset = ClassTable::StateOffsetFor(cid);
+  LoadIsolate(temp_reg);
+  intptr_t table_offset =
+    Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
+  lw(temp_reg, Address(temp_reg, table_offset));
+  AddImmediate(temp_reg, state_offset);
+  lw(temp_reg, Address(temp_reg, 0));
+  andi(CMPRES1, temp_reg, Immediate(ClassHeapStats::TraceAllocationMask()));
+  bne(CMPRES1, ZR, trace);
+}
+
+
 void Assembler::UpdateAllocationStats(intptr_t cid,
                                       Register temp_reg,
                                       Heap::Space space) {
@@ -950,25 +927,7 @@
   addu(TMP, TMP, size_reg);
   sw(TMP, Address(temp_reg, size_field_offset));
 }
-
-
-void Assembler::MaybeTraceAllocation(intptr_t cid,
-                                     Register temp_reg,
-                                     Label* trace) {
-  ASSERT(cid > 0);
-  ASSERT(!in_delay_slot_);
-  ASSERT(temp_reg != kNoRegister);
-  ASSERT(temp_reg != TMP);
-  intptr_t state_offset = ClassTable::StateOffsetFor(cid);
-  LoadIsolate(temp_reg);
-  intptr_t table_offset =
-    Isolate::class_table_offset() + ClassTable::TableOffsetFor(cid);
-  lw(temp_reg, Address(temp_reg, table_offset));
-  AddImmediate(temp_reg, state_offset);
-  lw(temp_reg, Address(temp_reg, 0));
-  andi(CMPRES1, temp_reg, Immediate(ClassHeapStats::TraceAllocationMask()));
-  bne(CMPRES1, ZR, trace);
-}
+#endif  // !PRODUCT
 
 
 void Assembler::TryAllocate(const Class& cls,
diff --git a/runtime/vm/assembler_mips.h b/runtime/vm/assembler_mips.h
index 39b06a4..87717b6 100644
--- a/runtime/vm/assembler_mips.h
+++ b/runtime/vm/assembler_mips.h
@@ -1472,6 +1472,11 @@
     sra(dst, src, kSmiTagSize);
   }
 
+  void BranchIfNotSmi(Register reg, Label* label) {
+    andi(CMPRES1, reg, Immediate(kSmiTagMask));
+    bne(CMPRES1, ZR, label);
+  }
+
   void LoadFromOffset(Register reg, Register base, int32_t offset) {
     ASSERT(!in_delay_slot_);
     if (Utils::IsInt(kImmBits, offset)) {
@@ -1549,16 +1554,6 @@
   void LoadClassIdMayBeSmi(Register result, Register object);
   void LoadTaggedClassIdMayBeSmi(Register result, Register object);
 
-  void ComputeRange(Register result,
-                    Register value,
-                    Label* miss);
-
-  void UpdateRangeFeedback(Register value,
-                           intptr_t index,
-                           Register ic_data,
-                           Register scratch,
-                           Label* miss);
-
   void StoreIntoObject(Register object,  // Object we are storing into.
                        const Address& dest,  // Where we are storing into.
                        Register value,  // Value we are storing.
diff --git a/runtime/vm/assembler_mips_test.cc b/runtime/vm/assembler_mips_test.cc
index 2072751..2a77101 100644
--- a/runtime/vm/assembler_mips_test.cc
+++ b/runtime/vm/assembler_mips_test.cc
@@ -2141,57 +2141,6 @@
 }
 
 
-ASSEMBLER_TEST_GENERATE(ComputeRange, assembler) {
-  Label miss, done;
-  __ ComputeRange(V0, A0, &miss);
-  __ b(&done);
-
-  __ Bind(&miss);
-  __ LoadImmediate(V0, -1);
-
-  __ Bind(&done);
-  __ Ret();
-}
-
-
-ASSEMBLER_TEST_RUN(ComputeRange, test) {
-  typedef intptr_t (*ComputeRange)(intptr_t value) DART_UNUSED;
-
-#define RANGE_OF(v)                                              \
-  (EXECUTE_TEST_CODE_INTPTR_INTPTR(                              \
-    ComputeRange, test->entry(), reinterpret_cast<intptr_t>(v)))
-
-  EXPECT_EQ(0, RANGE_OF(Smi::New(0)));
-  EXPECT_EQ(0, RANGE_OF(Smi::New(1)));
-  EXPECT_EQ(ICData::kSignedRangeBit, RANGE_OF(Smi::New(-1)));
-  EXPECT_EQ(0, RANGE_OF(Smi::New(Smi::kMaxValue)));
-  EXPECT_EQ(ICData::kSignedRangeBit, RANGE_OF(Smi::New(Smi::kMinValue)));
-
-  EXPECT_EQ(ICData::kInt32RangeBit, RANGE_OF(Integer::New(Smi::kMaxValue + 1)));
-  EXPECT_EQ(ICData::kInt32RangeBit | ICData::kSignedRangeBit,
-            RANGE_OF(Integer::New(Smi::kMinValue - 1)));
-  EXPECT_EQ(ICData::kInt32RangeBit, RANGE_OF(Integer::New(kMaxInt32)));
-  EXPECT_EQ(ICData::kInt32RangeBit | ICData::kSignedRangeBit,
-            RANGE_OF(Integer::New(kMinInt32)));
-
-  EXPECT_EQ(ICData::kUint32RangeBit,
-            RANGE_OF(Integer::New(static_cast<int64_t>(kMaxInt32) + 1)));
-  EXPECT_EQ(ICData::kUint32RangeBit,
-            RANGE_OF(Integer::New(kMaxUint32)));
-
-  EXPECT_EQ(ICData::kInt64RangeBit,
-            RANGE_OF(Integer::New(static_cast<int64_t>(kMaxUint32) + 1)));
-  EXPECT_EQ(ICData::kInt64RangeBit,
-            RANGE_OF(Integer::New(static_cast<int64_t>(kMinInt32) - 1)));
-  EXPECT_EQ(ICData::kInt64RangeBit, RANGE_OF(Integer::New(kMaxInt64)));
-  EXPECT_EQ(ICData::kInt64RangeBit, RANGE_OF(Integer::New(kMinInt64)));
-
-  EXPECT_EQ(-1, RANGE_OF(Bool::True().raw()));
-
-#undef RANGE_OF
-}
-
-
 ASSEMBLER_TEST_GENERATE(Semaphore, assembler) {
   __ EnterFrame();
   __ LoadImmediate(T0, 40);
diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc
index c266bf6..1902779 100644
--- a/runtime/vm/assembler_x64.cc
+++ b/runtime/vm/assembler_x64.cc
@@ -3321,6 +3321,7 @@
 }
 
 
+#ifndef PRODUCT
 void Assembler::MaybeTraceAllocation(intptr_t cid,
                                      Label* trace,
                                      bool near_jump) {
@@ -3375,6 +3376,7 @@
   intptr_t size_offset = ClassTable::SizeOffsetFor(cid, space == Heap::kNew);
   addq(Address(temp_reg, size_offset), Immediate(size_in_bytes));
 }
+#endif  // !PRODUCT
 
 
 void Assembler::TryAllocate(const Class& cls,
@@ -3673,48 +3675,6 @@
 }
 
 
-void Assembler::ComputeRange(Register result, Register value, Label* not_mint) {
-  Label done, not_smi;
-  testl(value, Immediate(kSmiTagMask));
-  j(NOT_ZERO, &not_smi, Assembler::kNearJump);
-
-  sarq(value, Immediate(32));  // Take the tag into account.
-  movq(result, Immediate(ICData::kUint32RangeBit));  // Uint32
-  cmpq(value, Immediate(1));
-  j(EQUAL, &done, Assembler::kNearJump);
-
-  movq(result, Immediate(ICData::kInt32RangeBit));
-  subq(result, value);  // 10 (positive int32), 11 (negative int32)
-  negq(value);
-  cmpq(value, Immediate(1));
-  j(BELOW_EQUAL, &done);
-
-  // On 64-bit we don't need to track sign of smis outside of the Int32 range.
-  // Just pretend they are all signed.
-  movq(result, Immediate(ICData::kSignedRangeBit));
-  jmp(&done);
-
-  Bind(&not_smi);
-  CompareClassId(value, kMintCid);
-  j(NOT_EQUAL, not_mint);
-  movq(result, Immediate(ICData::kInt64RangeBit));
-
-  Bind(&done);
-}
-
-
-void Assembler::UpdateRangeFeedback(Register value,
-                                    intptr_t index,
-                                    Register ic_data,
-                                    Register scratch,
-                                    Label* miss) {
-  ASSERT(ICData::IsValidRangeFeedbackIndex(index));
-  ComputeRange(scratch, value, miss);
-  shll(scratch, Immediate(ICData::RangeFeedbackShift(index)));
-  orl(FieldAddress(ic_data, ICData::state_bits_offset()), scratch);
-}
-
-
 Address Assembler::ElementAddressForIntIndex(bool is_external,
                                              intptr_t cid,
                                              intptr_t index_scale,
diff --git a/runtime/vm/assembler_x64.h b/runtime/vm/assembler_x64.h
index f31d37b..f4ce132 100644
--- a/runtime/vm/assembler_x64.h
+++ b/runtime/vm/assembler_x64.h
@@ -861,14 +861,11 @@
     sarq(reg, Immediate(kSmiTagSize));
   }
 
-  void ComputeRange(Register result, Register value, Label* miss);
-  void UpdateRangeFeedback(Register value,
-                           intptr_t index,
-                           Register ic_data,
-                           Register scratch,
-                           Label* miss);
+  void BranchIfNotSmi(Register reg, Label* label) {
+    testq(reg, Immediate(kSmiTagMask));
+    j(NOT_ZERO, label);
+  }
 
-  int PreferredLoopAlignment() { return 16; }
   void Align(int alignment, intptr_t offset);
   void Bind(Label* label);
   void Jump(Label* label) { jmp(label); }
diff --git a/runtime/vm/assembler_x64_test.cc b/runtime/vm/assembler_x64_test.cc
index eb8219d..681a599 100644
--- a/runtime/vm/assembler_x64_test.cc
+++ b/runtime/vm/assembler_x64_test.cc
@@ -3589,55 +3589,6 @@
   EXPECT_EQ(0, res);
 }
 
-
-ASSEMBLER_TEST_GENERATE(ComputeRange, assembler) {
-  Label miss;
-  __ movq(RDX, CallingConventions::kArg1Reg);
-  __ ComputeRange(RAX, RDX, &miss);
-  __ ret();
-
-  __ Bind(&miss);
-  __ movq(RAX, Immediate(0));
-  __ ret();
-}
-
-
-ASSEMBLER_TEST_RUN(ComputeRange, test) {
-  typedef intptr_t (*ComputeRange)(RawObject*);
-  ComputeRange range_of = reinterpret_cast<ComputeRange>(test->entry());
-
-  EXPECT_EQ(ICData::kInt32RangeBit, range_of(Smi::New(0)));
-  EXPECT_EQ(ICData::kInt32RangeBit, range_of(Smi::New(1)));
-  EXPECT_EQ(ICData::kInt32RangeBit, range_of(Smi::New(kMaxInt32)));
-  EXPECT_EQ(ICData::kInt32RangeBit | ICData::kSignedRangeBit,
-            range_of(Smi::New(-1)));
-  EXPECT_EQ(ICData::kInt32RangeBit | ICData::kSignedRangeBit,
-            range_of(Smi::New(kMinInt32)));
-
-  EXPECT_EQ(ICData::kUint32RangeBit,
-            range_of(Smi::New(static_cast<int64_t>(kMaxInt32) + 1)));
-  EXPECT_EQ(ICData::kUint32RangeBit,
-            range_of(Smi::New(kMaxUint32)));
-
-  // On 64-bit platforms we don't track the sign of the smis outside of
-  // int32 range because it is not needed to distinguish kInt32Range from
-  // kUint32Range.
-  EXPECT_EQ(ICData::kSignedRangeBit,
-            range_of(Smi::New(static_cast<int64_t>(kMinInt32) - 1)));
-  EXPECT_EQ(ICData::kSignedRangeBit,
-            range_of(Smi::New(static_cast<int64_t>(kMaxUint32) + 1)));
-  EXPECT_EQ(ICData::kSignedRangeBit, range_of(Smi::New(Smi::kMaxValue)));
-  EXPECT_EQ(ICData::kSignedRangeBit, range_of(Smi::New(Smi::kMinValue)));
-
-  EXPECT_EQ(ICData::kInt64RangeBit, range_of(Integer::New(Smi::kMaxValue + 1)));
-  EXPECT_EQ(ICData::kInt64RangeBit, range_of(Integer::New(Smi::kMinValue - 1)));
-  EXPECT_EQ(ICData::kInt64RangeBit, range_of(Integer::New(kMaxInt64)));
-  EXPECT_EQ(ICData::kInt64RangeBit, range_of(Integer::New(kMinInt64)));
-
-  EXPECT_EQ(0, range_of(Bool::True().raw()));
-}
-
-
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_X64
diff --git a/runtime/vm/atomic_fuchsia.h b/runtime/vm/atomic_fuchsia.h
index d6c0f57..67dd329 100644
--- a/runtime/vm/atomic_fuchsia.h
+++ b/runtime/vm/atomic_fuchsia.h
@@ -13,34 +13,30 @@
 #error This file should only be included on Fuchsia builds.
 #endif
 
-#include "platform/assert.h"
-
 namespace dart {
 
 inline uintptr_t AtomicOperations::FetchAndIncrement(uintptr_t* p) {
-  UNIMPLEMENTED();
-  return 0;
+  return __sync_fetch_and_add(p, 1);
 }
 
 
 inline void AtomicOperations::IncrementBy(intptr_t* p, intptr_t value) {
-  UNIMPLEMENTED();
+  __sync_fetch_and_add(p, value);
 }
 
 
 inline void AtomicOperations::IncrementInt64By(int64_t* p, int64_t value) {
-  UNIMPLEMENTED();
+  __sync_fetch_and_add(p, value);
 }
 
 
 inline uintptr_t AtomicOperations::FetchAndDecrement(uintptr_t* p) {
-  UNIMPLEMENTED();
-  return 0;
+  return __sync_fetch_and_sub(p, 1);
 }
 
 
 inline void AtomicOperations::DecrementBy(intptr_t* p, intptr_t value) {
-  UNIMPLEMENTED();
+  __sync_fetch_and_sub(p, value);
 }
 
 
@@ -48,16 +44,14 @@
 inline uword AtomicOperations::CompareAndSwapWord(uword* ptr,
                                                   uword old_value,
                                                   uword new_value) {
-  UNIMPLEMENTED();
-  return 0;
+  return __sync_val_compare_and_swap(ptr, old_value, new_value);
 }
 
 
 inline uint32_t AtomicOperations::CompareAndSwapUint32(uint32_t* ptr,
                                                        uint32_t old_value,
                                                        uint32_t new_value) {
-  UNIMPLEMENTED();
-  return 0;
+  return __sync_val_compare_and_swap(ptr, old_value, new_value);
 }
 #endif  // !defined(USING_SIMULATOR_ATOMICS)
 
diff --git a/runtime/vm/become.cc b/runtime/vm/become.cc
index 13b7439..a4d9fd1 100644
--- a/runtime/vm/become.cc
+++ b/runtime/vm/become.cc
@@ -148,6 +148,17 @@
 };
 
 
+void Become::MakeDummyObject(const Instance& instance) {
+  // Make the forward pointer point to itself.
+  // This is needed to distinguish it from a real forward object.
+  ForwardObjectTo(instance.raw(), instance.raw());
+}
+
+static bool IsDummyObject(RawObject* object) {
+  if (!object->IsForwardingCorpse()) return false;
+  return GetForwardedObject(object) == object;
+}
+
 void Become::ElementsForwardIdentity(const Array& before, const Array& after) {
   Thread* thread = Thread::Current();
   Isolate* isolate = thread->isolate();
@@ -174,7 +185,7 @@
     if (before_obj->IsVMHeapObject()) {
       FATAL("become: Cannot forward VM heap objects");
     }
-    if (before_obj->IsForwardingCorpse()) {
+    if (before_obj->IsForwardingCorpse() && !IsDummyObject(before_obj)) {
       FATAL("become: Cannot forward to multiple targets");
     }
     if (after_obj->IsForwardingCorpse()) {
diff --git a/runtime/vm/become.h b/runtime/vm/become.h
index b78524d..8ce164e 100644
--- a/runtime/vm/become.h
+++ b/runtime/vm/become.h
@@ -80,6 +80,11 @@
   // in 'after'. Every element in 'before' is guaranteed to be not reachable.
   // Useful for atomically applying behavior and schema changes.
   static void ElementsForwardIdentity(const Array& before, const Array& after);
+
+  // Convert and instance object into a dummy object,
+  // making the instance independent of its class.
+  // (used for morphic instances during reload).
+  static void MakeDummyObject(const Instance& instance);
 };
 
 }  // namespace dart
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 4bb5e93..161d0b2 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -21,6 +21,7 @@
   V(Object_noSuchMethod, 6)                                                    \
   V(Object_runtimeType, 1)                                                     \
   V(Object_instanceOf, 4)                                                      \
+  V(Object_simpleInstanceOf, 2)                                                \
   V(Object_instanceOfNum, 2)                                                   \
   V(Object_instanceOfInt, 2)                                                   \
   V(Object_instanceOfSmi, 2)                                                   \
@@ -365,6 +366,7 @@
   V(VMService_CancelStream, 1)                                                 \
   V(VMService_RequestAssets, 0)                                                \
   V(VMService_DecodeAssets, 1)                                                 \
+  V(VMService_spawnUriNotify, 2)                                               \
 
 // List of bootstrap native entry points used in the dart:mirror library.
 #define MIRRORS_BOOTSTRAP_NATIVE_LIST(V)                                       \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 6554d23..1191301 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -2521,12 +2521,15 @@
 // getter function object for each enumeration value and for the
 // values field. We also don't have to generate the code for these getters
 // from thin air (no source code is available).
-void ClassFinalizer::AllocateEnumValues(const Class &enum_cls) {
+void ClassFinalizer::AllocateEnumValues(const Class& enum_cls) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   const Field& index_field =
       Field::Handle(zone, enum_cls.LookupInstanceField(Symbols::Index()));
   ASSERT(!index_field.IsNull());
+  const Field& name_field = Field::Handle(zone,
+        enum_cls.LookupInstanceFieldAllowPrivate(Symbols::_name()));
+  ASSERT(!name_field.IsNull());
   const Field& values_field =
       Field::Handle(zone, enum_cls.LookupStaticField(Symbols::Values()));
   ASSERT(!values_field.IsNull());
@@ -2539,6 +2542,11 @@
   Instance& ordinal_value = Instance::Handle(zone);
   Instance& enum_value = Instance::Handle(zone);
 
+  const String& enum_name = String::Handle(enum_cls.ScrubbedName());
+  const String& name_prefix =
+      String::Handle(String::Concat(enum_name, Symbols::Dot()));
+
+  String& enum_ident = String::Handle();
   for (intptr_t i = 0; i < fields.Length(); i++) {
     field = Field::RawCast(fields.At(i));
     if (!field.is_static()) continue;
@@ -2547,8 +2555,18 @@
     // contain the smi value of the ordinal number, which was stored in
     // the field by the parser. Other fields contain non-smi values.
     if (!ordinal_value.IsSmi()) continue;
+    enum_ident = field.name();
+    // Construct the string returned by toString.
+    ASSERT(!enum_ident.IsNull());
+    // For the user-visible name of the enumeration value, we need to
+    // unmangle private names.
+    if (enum_ident.CharAt(0) == '_') {
+      enum_ident = String::ScrubName(enum_ident);
+    }
+    enum_ident = Symbols::FromConcat(thread, name_prefix, enum_ident);
     enum_value = Instance::New(enum_cls, Heap::kOld);
     enum_value.SetField(index_field, ordinal_value);
+    enum_value.SetField(name_field, enum_ident);
     const char* error_msg = "";
     enum_value = enum_value.CheckAndCanonicalize(thread, &error_msg);
     ASSERT(!enum_value.IsNull());
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index 4549fb8..ed2ea00 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -19,9 +19,9 @@
 
 ClassTable::ClassTable()
     : top_(kNumPredefinedCids), capacity_(0), table_(NULL),
-      old_tables_(new MallocGrowableArray<RawClass**>()),
-      class_heap_stats_table_(NULL),
-      predefined_class_heap_stats_table_(NULL) {
+      old_tables_(new MallocGrowableArray<RawClass**>()) {
+  NOT_IN_PRODUCT(class_heap_stats_table_ = NULL);
+  NOT_IN_PRODUCT(predefined_class_heap_stats_table_ = NULL);
   if (Dart::vm_isolate() == NULL) {
     capacity_ = initial_capacity_;
     table_ = reinterpret_cast<RawClass**>(
@@ -39,17 +39,22 @@
     table_[kForwardingCorpse] = vm_class_table->At(kForwardingCorpse);
     table_[kDynamicCid] = vm_class_table->At(kDynamicCid);
     table_[kVoidCid] = vm_class_table->At(kVoidCid);
+
+#ifndef PRODUCT
     class_heap_stats_table_ = reinterpret_cast<ClassHeapStats*>(
         calloc(capacity_, sizeof(ClassHeapStats)));  // NOLINT
     for (intptr_t i = 0; i < capacity_; i++) {
       class_heap_stats_table_[i].Initialize();
     }
+#endif  // !PRODUCT
   }
+#ifndef PRODUCT
   predefined_class_heap_stats_table_ = reinterpret_cast<ClassHeapStats*>(
         calloc(kNumPredefinedCids, sizeof(ClassHeapStats)));  // NOLINT
   for (intptr_t i = 0; i < kNumPredefinedCids; i++) {
     predefined_class_heap_stats_table_[i].Initialize();
   }
+#endif  // !PRODUCT
 }
 
 
@@ -57,9 +62,9 @@
     : top_(original->top_),
       capacity_(original->top_),
       table_(original->table_),
-      old_tables_(NULL),
-      class_heap_stats_table_(NULL),
-      predefined_class_heap_stats_table_(NULL) {
+      old_tables_(NULL) {
+  NOT_IN_PRODUCT(class_heap_stats_table_ = NULL);
+  NOT_IN_PRODUCT(predefined_class_heap_stats_table_ = NULL);
 }
 
 
@@ -68,12 +73,12 @@
     FreeOldTables();
     delete old_tables_;
     free(table_);
-    free(predefined_class_heap_stats_table_);
-    free(class_heap_stats_table_);
+    NOT_IN_PRODUCT(free(predefined_class_heap_stats_table_));
+    NOT_IN_PRODUCT(free(class_heap_stats_table_));
   } else {
     // This instance was a shallow copy. It doesn't own any memory.
-    ASSERT(predefined_class_heap_stats_table_ == NULL);
-    ASSERT(class_heap_stats_table_ == NULL);
+    NOT_IN_PRODUCT(ASSERT(predefined_class_heap_stats_table_ == NULL));
+    NOT_IN_PRODUCT(ASSERT(class_heap_stats_table_ == NULL));
   }
 }
 
@@ -85,6 +90,7 @@
 }
 
 
+#ifndef PRODUCT
 void ClassTable::SetTraceAllocationFor(intptr_t cid, bool trace) {
   ClassHeapStats* stats = PreliminaryStatsAt(cid);
   stats->set_trace_allocation(trace);
@@ -95,6 +101,7 @@
   ClassHeapStats* stats = PreliminaryStatsAt(cid);
   return stats->trace_allocation();
 }
+#endif  // !PRODUCT
 
 
 void ClassTable::Register(const Class& cls) {
@@ -120,17 +127,19 @@
       RawClass** new_table = reinterpret_cast<RawClass**>(
           malloc(new_capacity * sizeof(RawClass*)));  // NOLINT
       memmove(new_table, table_, capacity_ * sizeof(RawClass*));
+#ifndef PRODUCT
       ClassHeapStats* new_stats_table = reinterpret_cast<ClassHeapStats*>(
           realloc(class_heap_stats_table_,
                   new_capacity * sizeof(ClassHeapStats)));  // NOLINT
+#endif
       for (intptr_t i = capacity_; i < new_capacity; i++) {
         new_table[i] = NULL;
-        new_stats_table[i].Initialize();
+        NOT_IN_PRODUCT(new_stats_table[i].Initialize());
       }
       capacity_ = new_capacity;
       old_tables_->Add(table_);
       table_ = new_table;  // TODO(koda): This should use atomics.
-      class_heap_stats_table_ = new_stats_table;
+      NOT_IN_PRODUCT(class_heap_stats_table_ = new_stats_table);
     }
     ASSERT(top_ < capacity_);
     if (!Class::is_valid_id(top_)) {
@@ -156,17 +165,19 @@
     RawClass** new_table = reinterpret_cast<RawClass**>(
         malloc(new_capacity * sizeof(RawClass*)));  // NOLINT
     memmove(new_table, table_, capacity_ * sizeof(RawClass*));
+#ifndef PRODUCT
     ClassHeapStats* new_stats_table = reinterpret_cast<ClassHeapStats*>(
         realloc(class_heap_stats_table_,
                 new_capacity * sizeof(ClassHeapStats)));  // NOLINT
+#endif
     for (intptr_t i = capacity_; i < new_capacity; i++) {
       new_table[i] = NULL;
-      new_stats_table[i].Initialize();
+      NOT_IN_PRODUCT(new_stats_table[i].Initialize());
     }
     capacity_ = new_capacity;
     old_tables_->Add(table_);
     table_ = new_table;  // TODO(koda): This should use atomics.
-    class_heap_stats_table_ = new_stats_table;
+    NOT_IN_PRODUCT(class_heap_stats_table_ = new_stats_table);
     ASSERT(capacity_increment_ >= 1);
   }
 
@@ -252,7 +263,6 @@
     }
   }
 }
-#endif  // PRODUCT
 
 
 void ClassHeapStats::Initialize() {
@@ -264,6 +274,7 @@
   promoted_count = 0;
   promoted_size = 0;
   state_ = 0;
+  USE(align_);
 }
 
 
@@ -332,7 +343,6 @@
 }
 
 
-#ifndef PRODUCT
 void ClassHeapStats::PrintToJSONObject(const Class& cls,
                                        JSONObject* obj) const {
   if (!FLAG_support_service) {
@@ -369,7 +379,6 @@
   obj->AddProperty("promotedInstances", promoted_count);
   obj->AddProperty("promotedBytes", promoted_size);
 }
-#endif
 
 
 void ClassTable::UpdateAllocatedNew(intptr_t cid, intptr_t size) {
@@ -496,7 +505,6 @@
 }
 
 
-#ifndef PRODUCT
 void ClassTable::AllocationProfilePrintJSON(JSONStream* stream) {
   if (!FLAG_support_service) {
     return;
@@ -538,7 +546,6 @@
     }
   }
 }
-#endif
 
 
 void ClassTable::ResetAllocationAccumulators() {
@@ -566,6 +573,7 @@
   ASSERT(size >= 0);
   stats->post_gc.AddNew(size);
 }
+#endif  // !PRODUCT
 
 
 }  // namespace dart
diff --git a/runtime/vm/class_table.h b/runtime/vm/class_table.h
index 9a12fc3e..a7e38ba 100644
--- a/runtime/vm/class_table.h
+++ b/runtime/vm/class_table.h
@@ -20,6 +20,7 @@
 class ObjectPointerVisitor;
 class RawClass;
 
+#ifndef PRODUCT
 template<typename T>
 class AllocStats {
  public:
@@ -141,8 +142,9 @@
   intptr_t old_pre_new_gc_count_;
   intptr_t old_pre_new_gc_size_;
   intptr_t state_;
+  intptr_t align_;  // Make SIMARM and ARM agree on the size of ClassHeapStats.
 };
-
+#endif  // !PRODUCT
 
 class ClassTable {
  public:
@@ -194,15 +196,16 @@
   void Validate();
 
   void Print();
-#ifndef PRODUCT
-  void PrintToJSONObject(JSONObject* object);
-#endif
 
   // Used by the generated code.
   static intptr_t table_offset() {
     return OFFSET_OF(ClassTable, table_);
   }
 
+  // Used by the generated code.
+  static intptr_t ClassOffsetFor(intptr_t cid);
+
+#ifndef PRODUCT
   // Called whenever a class is allocated in the runtime.
   void UpdateAllocatedNew(intptr_t cid, intptr_t size);
   void UpdateAllocatedOld(intptr_t cid, intptr_t size);
@@ -215,9 +218,6 @@
   void UpdatePromoted();
 
   // Used by the generated code.
-  static intptr_t ClassOffsetFor(intptr_t cid);
-
-  // Used by the generated code.
   ClassHeapStats** TableAddressFor(intptr_t cid);
   static intptr_t TableOffsetFor(intptr_t cid);
 
@@ -235,6 +235,9 @@
   void AllocationProfilePrintJSON(JSONStream* stream);
   void ResetAllocationAccumulators();
 
+  void PrintToJSONObject(JSONObject* object);
+#endif  // !PRODUCT
+
   // Deallocates table copies. Do not call during concurrent access to table.
   void FreeOldTables();
 
@@ -257,14 +260,15 @@
   RawClass** table_;
   MallocGrowableArray<RawClass**>* old_tables_;
 
+#ifndef PRODUCT
   ClassHeapStats* class_heap_stats_table_;
-
   ClassHeapStats* predefined_class_heap_stats_table_;
 
   // May not have updated size for variable size classes.
   ClassHeapStats* PreliminaryStatsAt(intptr_t cid);
   void UpdateLiveOld(intptr_t cid, intptr_t size, intptr_t count = 1);
   void UpdateLiveNew(intptr_t cid, intptr_t size);
+#endif  // !PRODUCT
 
   DISALLOW_COPY_AND_ASSIGN(ClassTable);
 };
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index e938fef..6f958fd 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -78,15 +78,15 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kClassCid);
     intptr_t count = predefined_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawClass* cls = predefined_[i];
       intptr_t class_id = cls->ptr()->id_;
-      s->Write<intptr_t>(class_id);
+      s->WriteCid(class_id);
       s->AssignRef(cls);
     }
     count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawClass* cls = objects_[i];
       s->AssignRef(cls);
@@ -137,10 +137,10 @@
   void ReadAlloc(Deserializer* d) {
     predefined_start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     ClassTable* table = d->isolate()->class_table();
     for (intptr_t i = 0; i < count; i++) {
-      intptr_t class_id = d->Read<intptr_t>();
+      intptr_t class_id = d->ReadCid();
       ASSERT(table->HasValidClassAt(class_id));
       RawClass* cls = table->At(class_id);
       ASSERT(cls != NULL);
@@ -149,7 +149,7 @@
     predefined_stop_index_ = d->next_index();
 
     start_index_ = d->next_index();
-    count = d->Read<intptr_t>();
+    count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space,
                                          Class::InstanceSize()));
@@ -174,8 +174,13 @@
 
       intptr_t class_id = d->ReadCid();
       cls->ptr()->id_ = class_id;
-      cls->ptr()->instance_size_in_words_ = d->Read<int32_t>();
-      cls->ptr()->next_field_offset_in_words_ = d->Read<int32_t>();
+      if (!RawObject::IsInternalVMdefinedClassId(class_id)) {
+        cls->ptr()->instance_size_in_words_ = d->Read<int32_t>();
+        cls->ptr()->next_field_offset_in_words_ = d->Read<int32_t>();
+      } else {
+        d->Read<int32_t>();  // Skip.
+        d->Read<int32_t>();  // Skip.
+      }
       cls->ptr()->type_arguments_field_offset_in_words_ = d->Read<int32_t>();
       cls->ptr()->num_type_arguments_ = d->Read<uint16_t>();
       cls->ptr()->num_own_type_arguments_ = d->Read<uint16_t>();
@@ -261,7 +266,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kUnresolvedClassCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawUnresolvedClass* cls = objects_[i];
       s->AssignRef(cls);
@@ -270,7 +275,7 @@
 
   void WriteFill(Serializer* s) {
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawUnresolvedClass* cls = objects_[i];
       RawObject** from = cls->from();
@@ -295,7 +300,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space,
                                          UnresolvedClass::InstanceSize()));
@@ -342,11 +347,11 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kTypeArgumentsCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawTypeArguments* type_args = objects_[i];
       intptr_t length = Smi::Value(type_args->ptr()->length_);
-      s->Write<intptr_t>(length);
+      s->Write<int32_t>(length);
       s->AssignRef(type_args);
     }
   }
@@ -356,7 +361,7 @@
     for (intptr_t i = 0; i < count; i++) {
       RawTypeArguments* type_args = objects_[i];
       intptr_t length = Smi::Value(type_args->ptr()->length_);
-      s->Write<intptr_t>(length);
+      s->Write<int32_t>(length);
       s->Write<bool>(type_args->IsCanonical());
       intptr_t hash = Smi::Value(type_args->ptr()->hash_);
       s->Write<int32_t>(hash);
@@ -380,9 +385,9 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
-      intptr_t length = d->Read<intptr_t>();
+      intptr_t length = d->Read<int32_t>();
       d->AssignRef(AllocateUninitialized(old_space,
                                          TypeArguments::InstanceSize(length)));
     }
@@ -395,7 +400,7 @@
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawTypeArguments* type_args =
           reinterpret_cast<RawTypeArguments*>(d->Ref(id));
-      intptr_t length = d->Read<intptr_t>();
+      intptr_t length = d->Read<int32_t>();
       bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(type_args, kTypeArgumentsCid,
                                      TypeArguments::InstanceSize(length),
@@ -432,7 +437,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kPatchClassCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawPatchClass* cls = objects_[i];
       s->AssignRef(cls);
@@ -464,7 +469,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space,
                                          PatchClass::InstanceSize()));
@@ -514,7 +519,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kFunctionCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawFunction* func = objects_[i];
       s->AssignRef(func);
@@ -572,7 +577,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space,
                                          Function::InstanceSize()));
@@ -684,7 +689,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kClosureDataCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawClosureData* data = objects_[i];
       s->AssignRef(data);
@@ -716,7 +721,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space,
                                          ClosureData::InstanceSize()));
@@ -760,7 +765,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kRedirectionDataCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawRedirectionData* data = objects_[i];
       s->AssignRef(data);
@@ -792,7 +797,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space,
                                          RedirectionData::InstanceSize()));
@@ -864,7 +869,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kFieldCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawField* field = objects_[i];
       s->AssignRef(field);
@@ -929,7 +934,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, Field::InstanceSize()));
     }
@@ -1006,7 +1011,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kLiteralTokenCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawLiteralToken* token = objects_[i];
       s->AssignRef(token);
@@ -1039,7 +1044,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space,
                                          LiteralToken::InstanceSize()));
@@ -1085,7 +1090,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kTokenStreamCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawTokenStream* stream = objects_[i];
       s->AssignRef(stream);
@@ -1117,7 +1122,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space,
                                          TokenStream::InstanceSize()));
@@ -1161,7 +1166,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kScriptCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawScript* script = objects_[i];
       s->AssignRef(script);
@@ -1198,7 +1203,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, Script::InstanceSize()));
     }
@@ -1251,7 +1256,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kLibraryCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawLibrary* lib = objects_[i];
       s->AssignRef(lib);
@@ -1289,7 +1294,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, Library::InstanceSize()));
     }
@@ -1361,7 +1366,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kNamespaceCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawNamespace* ns = objects_[i];
       s->AssignRef(ns);
@@ -1393,7 +1398,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, Namespace::InstanceSize()));
     }
@@ -1436,7 +1441,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kCodeCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawCode* code = objects_[i];
       s->AssignRef(code);
@@ -1496,7 +1501,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, Code::InstanceSize(0)));
     }
@@ -1571,11 +1576,11 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kObjectPoolCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawObjectPool* pool = objects_[i];
       intptr_t length = pool->ptr()->length_;
-      s->Write<intptr_t>(length);
+      s->Write<int32_t>(length);
       s->AssignRef(pool);
     }
   }
@@ -1586,7 +1591,7 @@
       RawObjectPool* pool = objects_[i];
       RawTypedData* info_array = pool->ptr()->info_array_;
       intptr_t length = pool->ptr()->length_;
-      s->Write<intptr_t>(length);
+      s->Write<int32_t>(length);
       for (intptr_t j = 0; j < length; j++) {
         ObjectPool::EntryType entry_type =
             static_cast<ObjectPool::EntryType>(info_array->ptr()->data()[j]);
@@ -1638,9 +1643,9 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
-      intptr_t length = d->Read<intptr_t>();
+      intptr_t length = d->Read<int32_t>();
       d->AssignRef(AllocateUninitialized(old_space,
                                          ObjectPool::InstanceSize(length)));
     }
@@ -1651,7 +1656,7 @@
     bool is_vm_object = d->isolate() == Dart::vm_isolate();
     PageSpace* old_space = d->heap()->old_space();
     for (intptr_t id = start_index_; id < stop_index_; id += 1) {
-      intptr_t length = d->Read<intptr_t>();
+      intptr_t length = d->Read<int32_t>();
       RawTypedData* info_array = reinterpret_cast<RawTypedData*>(
           AllocateUninitialized(old_space, TypedData::InstanceSize(length)));
       Deserializer::InitializeHeader(info_array, kTypedDataUint8ArrayCid,
@@ -1728,7 +1733,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(cid_);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawObject* object = objects_[i];
       int32_t rodata_offset = s->GetRODataOffset(object);
@@ -1753,7 +1758,7 @@
   virtual ~RODataDeserializationCluster() { }
 
   void ReadAlloc(Deserializer* d) {
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       int32_t rodata_offset = d->Read<int32_t>();
       d->AssignRef(d->GetObjectAt(rodata_offset));
@@ -1795,11 +1800,11 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kExceptionHandlersCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawExceptionHandlers* handlers = objects_[i];
       intptr_t length = handlers->ptr()->num_entries_;
-      s->Write<intptr_t>(length);
+      s->Write<int32_t>(length);
       s->AssignRef(handlers);
     }
   }
@@ -1809,7 +1814,7 @@
     for (intptr_t i = 0; i < count; i++) {
       RawExceptionHandlers* handlers = objects_[i];
       intptr_t length = handlers->ptr()->num_entries_;
-      s->Write<intptr_t>(length);
+      s->Write<int32_t>(length);
       s->WriteRef(handlers->ptr()->handled_types_data_);
 
       uint8_t* data = reinterpret_cast<uint8_t*>(handlers->ptr()->data());
@@ -1832,9 +1837,9 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
-      intptr_t length = d->Read<intptr_t>();
+      intptr_t length = d->Read<int32_t>();
       d->AssignRef(AllocateUninitialized(old_space,
           ExceptionHandlers::InstanceSize(length)));
     }
@@ -1847,7 +1852,7 @@
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawExceptionHandlers* handlers =
           reinterpret_cast<RawExceptionHandlers*>(d->Ref(id));
-      intptr_t length = d->Read<intptr_t>();
+      intptr_t length = d->Read<int32_t>();
       Deserializer::InitializeHeader(handlers, kExceptionHandlersCid,
                                      ExceptionHandlers::InstanceSize(length),
                                      is_vm_object);
@@ -1882,11 +1887,11 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kContextCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawContext* context = objects_[i];
       intptr_t length = context->ptr()->num_variables_;
-      s->Write<intptr_t>(length);
+      s->Write<int32_t>(length);
       s->AssignRef(context);
     }
   }
@@ -1896,7 +1901,7 @@
     for (intptr_t i = 0; i < count; i++) {
       RawContext* context = objects_[i];
       intptr_t length = context->ptr()->num_variables_;
-      s->Write<intptr_t>(length);
+      s->Write<int32_t>(length);
       s->WriteRef(context->ptr()->parent_);
       for (intptr_t j = 0; j < length; j++) {
         s->WriteRef(context->ptr()->data()[j]);
@@ -1917,9 +1922,9 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
-      intptr_t length = d->Read<intptr_t>();
+      intptr_t length = d->Read<int32_t>();
       d->AssignRef(AllocateUninitialized(old_space,
                                          Context::InstanceSize(length)));
     }
@@ -1931,7 +1936,7 @@
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawContext* context = reinterpret_cast<RawContext*>(d->Ref(id));
-      intptr_t length = d->Read<intptr_t>();
+      intptr_t length = d->Read<int32_t>();
       Deserializer::InitializeHeader(context, kContextCid,
                                      Context::InstanceSize(length),
                                      is_vm_object);
@@ -1965,11 +1970,11 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kContextScopeCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawContextScope* scope = objects_[i];
       intptr_t length = scope->ptr()->num_variables_;
-      s->Write<intptr_t>(length);
+      s->Write<int32_t>(length);
       s->AssignRef(scope);
     }
   }
@@ -1979,7 +1984,7 @@
     for (intptr_t i = 0; i < count; i++) {
       RawContextScope* scope = objects_[i];
       intptr_t length = scope->ptr()->num_variables_;
-      s->Write<intptr_t>(length);
+      s->Write<int32_t>(length);
       s->Write<bool>(scope->ptr()->is_implicit_);
       RawObject** from = scope->from();
       RawObject** to = scope->to(length);
@@ -2002,9 +2007,9 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
-      intptr_t length = d->Read<intptr_t>();
+      intptr_t length = d->Read<int32_t>();
       d->AssignRef(AllocateUninitialized(old_space,
                                          ContextScope::InstanceSize(length)));
     }
@@ -2016,7 +2021,7 @@
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawContextScope* scope = reinterpret_cast<RawContextScope*>(d->Ref(id));
-      intptr_t length = d->Read<intptr_t>();
+      intptr_t length = d->Read<int32_t>();
       Deserializer::InitializeHeader(scope, kContextScopeCid,
                                      ContextScope::InstanceSize(length),
                                      is_vm_object);
@@ -2051,7 +2056,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kICDataCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawICData* ic = objects_[i];
       s->AssignRef(ic);
@@ -2071,7 +2076,7 @@
       s->Write<int32_t>(ic->ptr()->deopt_id_);
       s->Write<uint32_t>(ic->ptr()->state_bits_);
 #if defined(TAG_IC_DATA)
-      s->Write<intptr_t>(ic->ptr()->tag_);
+      s->Write<int32_t>(ic->ptr()->tag_);
 #endif
     }
   }
@@ -2089,7 +2094,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, ICData::InstanceSize()));
     }
@@ -2116,7 +2121,7 @@
       ic->ptr()->deopt_id_ = d->Read<int32_t>();
       ic->ptr()->state_bits_ = d->Read<int32_t>();
 #if defined(TAG_IC_DATA)
-      ic->ptr()->tag_ = d->Read<intptr_t>();
+      ic->ptr()->tag_ = d->Read<int32_t>();
 #endif
     }
   }
@@ -2165,7 +2170,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kMegamorphicCacheCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawMegamorphicCache* cache = objects_[i];
       s->AssignRef(cache);
@@ -2198,7 +2203,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space,
                                          MegamorphicCache::InstanceSize()));
@@ -2240,7 +2245,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kSubtypeTestCacheCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawSubtypeTestCache* cache = objects_[i];
       s->AssignRef(cache);
@@ -2268,7 +2273,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space,
                                          SubtypeTestCache::InstanceSize()));
@@ -2310,7 +2315,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kLanguageErrorCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawLanguageError* error = objects_[i];
       s->AssignRef(error);
@@ -2345,7 +2350,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space,
                                          LanguageError::InstanceSize()));
@@ -2393,7 +2398,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kUnhandledExceptionCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawUnhandledException* exception = objects_[i];
       s->AssignRef(exception);
@@ -2425,7 +2430,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space,
                                          UnhandledException::InstanceSize()));
@@ -2456,10 +2461,9 @@
  public:
   explicit InstanceSerializationCluster(intptr_t cid) : cid_(cid) {
     RawClass* cls = Isolate::Current()->class_table()->At(cid);
-    next_field_offset_ =
-        cls->ptr()->next_field_offset_in_words_ << kWordSizeLog2;
+    next_field_offset_in_words_ = cls->ptr()->next_field_offset_in_words_;
     instance_size_in_words_ = cls->ptr()->instance_size_in_words_;
-    ASSERT(next_field_offset_ > 0);
+    ASSERT(next_field_offset_in_words_ > 0);
     ASSERT(instance_size_in_words_ > 0);
   }
   virtual ~InstanceSerializationCluster() { }
@@ -2468,8 +2472,9 @@
     RawInstance* instance = Instance::RawCast(object);
     objects_.Add(instance);
 
+    intptr_t next_field_offset = next_field_offset_in_words_ << kWordSizeLog2;
     intptr_t offset = Instance::NextFieldOffset();
-    while (offset < next_field_offset_) {
+    while (offset < next_field_offset) {
       RawObject* raw_obj = *reinterpret_cast<RawObject**>(
           reinterpret_cast<uword>(instance->ptr()) + offset);
       s->Push(raw_obj);
@@ -2478,12 +2483,12 @@
   }
 
   void WriteAlloc(Serializer* s) {
-    s->Write<intptr_t>(cid_);
+    s->WriteCid(cid_);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
 
-    s->Write<intptr_t>(next_field_offset_);
-    s->Write<intptr_t>(instance_size_in_words_);
+    s->Write<int32_t>(next_field_offset_in_words_);
+    s->Write<int32_t>(instance_size_in_words_);
 
     for (intptr_t i = 0; i < count; i++) {
       RawInstance* instance = objects_[i];
@@ -2492,12 +2497,13 @@
   }
 
   void WriteFill(Serializer* s) {
+    intptr_t next_field_offset = next_field_offset_in_words_ << kWordSizeLog2;
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawInstance* instance = objects_[i];
       s->Write<bool>(instance->IsCanonical());
       intptr_t offset = Instance::NextFieldOffset();
-      while (offset < next_field_offset_) {
+      while (offset < next_field_offset) {
         RawObject* raw_obj = *reinterpret_cast<RawObject**>(
             reinterpret_cast<uword>(instance->ptr()) + offset);
         s->WriteRef(raw_obj);
@@ -2508,7 +2514,7 @@
 
  private:
   const intptr_t cid_;
-  intptr_t next_field_offset_;
+  intptr_t next_field_offset_in_words_;
   intptr_t instance_size_in_words_;
   GrowableArray<RawInstance*> objects_;
 };
@@ -2522,9 +2528,9 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
-    next_field_offset_  = d->Read<intptr_t>();
-    instance_size_in_words_  = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
+    next_field_offset_in_words_ = d->Read<int32_t>();
+    instance_size_in_words_ = d->Read<int32_t>();
     intptr_t instance_size =
         Object::RoundedAllocationSize(instance_size_in_words_ * kWordSize);
     for (intptr_t i = 0; i < count; i++) {
@@ -2534,6 +2540,7 @@
   }
 
   void ReadFill(Deserializer* d) {
+    intptr_t next_field_offset = next_field_offset_in_words_ << kWordSizeLog2;
     intptr_t instance_size =
         Object::RoundedAllocationSize(instance_size_in_words_ * kWordSize);
     bool is_vm_object = d->isolate() == Dart::vm_isolate();
@@ -2545,7 +2552,7 @@
                                      instance_size,
                                      is_vm_object, is_canonical);
       intptr_t offset = Instance::NextFieldOffset();
-      while (offset < next_field_offset_) {
+      while (offset < next_field_offset) {
         RawObject** p = reinterpret_cast<RawObject**>(
             reinterpret_cast<uword>(instance->ptr()) + offset);
         *p = d->ReadRef();
@@ -2563,7 +2570,7 @@
 
  private:
   const intptr_t cid_;
-  intptr_t next_field_offset_;
+  intptr_t next_field_offset_in_words_;
   intptr_t instance_size_in_words_;
 };
 
@@ -2587,7 +2594,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kLibraryPrefixCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawLibraryPrefix* prefix = objects_[i];
       s->AssignRef(prefix);
@@ -2622,7 +2629,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space,
                                          LibraryPrefix::InstanceSize()));
@@ -2680,13 +2687,13 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kTypeCid);
     intptr_t count = canonical_objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawType* type = canonical_objects_[i];
       s->AssignRef(type);
     }
     count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawType* type = objects_[i];
       s->AssignRef(type);
@@ -2732,14 +2739,14 @@
   void ReadAlloc(Deserializer* d) {
     canonical_start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, Type::InstanceSize()));
     }
     canonical_stop_index_ = d->next_index();
 
     start_index_ = d->next_index();
-    count = d->Read<intptr_t>();
+    count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, Type::InstanceSize()));
     }
@@ -2803,7 +2810,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kTypeRefCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawTypeRef* type = objects_[i];
       s->AssignRef(type);
@@ -2835,7 +2842,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, TypeRef::InstanceSize()));
     }
@@ -2879,7 +2886,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kTypeParameterCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawTypeParameter* type = objects_[i];
       s->AssignRef(type);
@@ -2895,7 +2902,7 @@
       for (RawObject** p = from; p <= to; p++) {
         s->WriteRef(*p);
       }
-      s->Write<intptr_t>(type->ptr()->parameterized_class_id_);
+      s->Write<int32_t>(type->ptr()->parameterized_class_id_);
       s->WriteTokenPosition(type->ptr()->token_pos_);
       s->Write<int16_t>(type->ptr()->index_);
       s->Write<int8_t>(type->ptr()->type_state_);
@@ -2915,7 +2922,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space,
                                          TypeParameter::InstanceSize()));
@@ -2936,7 +2943,7 @@
       for (RawObject** p = from; p <= to; p++) {
         *p = d->ReadRef();
       }
-      type->ptr()->parameterized_class_id_ = d->Read<intptr_t>();
+      type->ptr()->parameterized_class_id_ = d->Read<int32_t>();
       type->ptr()->token_pos_ = d->ReadTokenPosition();
       type->ptr()->index_ = d->Read<int16_t>();
       type->ptr()->type_state_ = d->Read<int8_t>();
@@ -2964,7 +2971,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kBoundedTypeCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawBoundedType* type = objects_[i];
       s->AssignRef(type);
@@ -2996,7 +3003,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space,
                                          BoundedType::InstanceSize()));
@@ -3040,7 +3047,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kClosureCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawClosure* closure = objects_[i];
       s->AssignRef(closure);
@@ -3073,7 +3080,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, Closure::InstanceSize()));
     }
@@ -3105,31 +3112,38 @@
   virtual ~MintSerializationCluster() { }
 
   void Trace(Serializer* s, RawObject* object) {
-    RawMint* mint = Mint::RawCast(object);
-    objects_.Add(mint);
+    if (!object->IsHeapObject()) {
+      RawSmi* smi = Smi::RawCast(object);
+      smis_.Add(smi);
+    } else {
+      RawMint* mint = Mint::RawCast(object);
+      mints_.Add(mint);
+    }
   }
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kMintCid);
-    intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
-    for (intptr_t i = 0; i < count; i++) {
-      RawMint* mint = objects_[i];
+
+    s->Write<int32_t>(smis_.length() + mints_.length());
+    for (intptr_t i = 0; i < smis_.length(); i++) {
+      RawSmi* smi = smis_[i];
+      s->Write<bool>(true);
+      s->Write<int64_t>(Smi::Value(smi));
+      s->AssignRef(smi);
+    }
+    for (intptr_t i = 0; i < mints_.length(); i++) {
+      RawMint* mint = mints_[i];
+      s->Write<bool>(mint->IsCanonical());
+      s->Write<int64_t>(mint->ptr()->value_);
       s->AssignRef(mint);
     }
   }
 
-  void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
-    for (intptr_t i = 0; i < count; i++) {
-      RawMint* mint = objects_[i];
-      s->Write<bool>(mint->IsCanonical());
-      s->Write<int64_t>(mint->ptr()->value_);
-    }
-  }
+  void WriteFill(Serializer* s) { }
 
  private:
-  GrowableArray<RawMint*> objects_;
+  GrowableArray<RawSmi*> smis_;
+  GrowableArray<RawMint*> mints_;
 };
 
 
@@ -3139,26 +3153,49 @@
   virtual ~MintDeserializationCluster() { }
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+    start_index_ = d->next_index();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(AllocateUninitialized(old_space, Mint::InstanceSize()));
+      bool is_canonical = d->Read<bool>();
+      int64_t value = d->Read<int64_t>();
+      if (Smi::IsValid(value)) {
+        d->AssignRef(Smi::New(value));
+      } else {
+        RawMint* mint = static_cast<RawMint*>(
+            AllocateUninitialized(old_space, Mint::InstanceSize()));
+        Deserializer::InitializeHeader(mint, kMintCid,
+                                       Mint::InstanceSize(),
+                                       is_vm_object, is_canonical);
+        mint->ptr()->value_ = value;
+        d->AssignRef(mint);
+      }
     }
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
-    bool is_vm_object = d->isolate() == Dart::vm_isolate();
+  void ReadFill(Deserializer* d) { }
 
-    for (intptr_t id = start_index_; id < stop_index_; id++) {
-      RawMint* mint = reinterpret_cast<RawMint*>(d->Ref(id));
-      bool is_canonical = d->Read<bool>();
-      Deserializer::InitializeHeader(mint, kMintCid,
-                                     Mint::InstanceSize(),
-                                     is_vm_object, is_canonical);
-      mint->ptr()->value_ = d->Read<int64_t>();
+  void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) {
+    NOT_IN_PRODUCT(TimelineDurationScope tds(Thread::Current(),
+        Timeline::GetIsolateStream(), "PostLoadMint"));
+
+    const GrowableObjectArray& new_constants =
+        GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
+    Object& number = Object::Handle(zone);
+    for (intptr_t i = start_index_; i < stop_index_; i++) {
+      number = refs.At(i);
+      if (number.IsMint() && number.IsCanonical()) {
+        new_constants.Add(number);
+      }
     }
+    const Array& constants_array =
+        Array::Handle(zone, Array::MakeArray(new_constants));
+    const Class& mint_cls = Class::Handle(zone,
+        Isolate::Current()->object_store()->mint_class());
+    mint_cls.set_constants(constants_array);
   }
 };
 
@@ -3182,7 +3219,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kBigintCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawBigint* bigint = objects_[i];
       s->AssignRef(bigint);
@@ -3215,7 +3252,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, Bigint::InstanceSize()));
     }
@@ -3254,7 +3291,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kDoubleCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawDouble* dbl = objects_[i];
       s->AssignRef(dbl);
@@ -3283,7 +3320,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, Double::InstanceSize()));
     }
@@ -3324,7 +3361,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kGrowableObjectArrayCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawGrowableObjectArray* array = objects_[i];
       s->AssignRef(array);
@@ -3358,7 +3395,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space,
                                          GrowableObjectArray::InstanceSize()));
@@ -3397,13 +3434,13 @@
   }
 
   void WriteAlloc(Serializer* s) {
-    s->Write<intptr_t>(cid_);
+    s->WriteCid(cid_);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawTypedData* data = objects_[i];
       intptr_t length = Smi::Value(data->ptr()->length_);
-      s->Write<intptr_t>(length);
+      s->Write<int32_t>(length);
       s->AssignRef(data);
     }
   }
@@ -3414,7 +3451,7 @@
     for (intptr_t i = 0; i < count; i++) {
       RawTypedData* data = objects_[i];
       intptr_t length = Smi::Value(data->ptr()->length_);
-      s->Write<intptr_t>(length);
+      s->Write<int32_t>(length);
       s->Write<bool>(data->IsCanonical());
       uint8_t* cdata = reinterpret_cast<uint8_t*>(data->ptr()->data());
       s->WriteBytes(cdata, length * element_size);
@@ -3435,10 +3472,10 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
     for (intptr_t i = 0; i < count; i++) {
-      intptr_t length = d->Read<intptr_t>();
+      intptr_t length = d->Read<int32_t>();
       d->AssignRef(AllocateUninitialized(old_space,
           TypedData::InstanceSize(length * element_size)));
     }
@@ -3451,7 +3488,7 @@
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawTypedData* data = reinterpret_cast<RawTypedData*>(d->Ref(id));
-      intptr_t length = d->Read<intptr_t>();
+      intptr_t length = d->Read<int32_t>();
       bool is_canonical = d->Read<bool>();
       intptr_t length_in_bytes = length * element_size;
       Deserializer::InitializeHeader(data, cid_,
@@ -3480,9 +3517,9 @@
   }
 
   void WriteAlloc(Serializer* s) {
-    s->Write<intptr_t>(cid_);
+    s->WriteCid(cid_);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawExternalTypedData* data = objects_[i];
       s->AssignRef(data);
@@ -3495,7 +3532,7 @@
     for (intptr_t i = 0; i < count; i++) {
       RawExternalTypedData* data = objects_[i];
       intptr_t length = Smi::Value(data->ptr()->length_);
-      s->Write<intptr_t>(length);
+      s->Write<int32_t>(length);
       uint8_t* cdata = reinterpret_cast<uint8_t*>(data->ptr()->data_);
       s->WriteBytes(cdata, length * element_size);
     }
@@ -3515,7 +3552,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space,
                                          ExternalTypedData::InstanceSize()));
@@ -3530,7 +3567,7 @@
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawExternalTypedData* data =
           reinterpret_cast<RawExternalTypedData*>(d->Ref(id));
-      intptr_t length = d->Read<intptr_t>();
+      intptr_t length = d->Read<int32_t>();
       Deserializer::InitializeHeader(data, cid_,
                                      ExternalTypedData::InstanceSize(),
                                      is_vm_object);
@@ -3564,7 +3601,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kStacktraceCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawStacktrace* trace = objects_[i];
       s->AssignRef(trace);
@@ -3596,7 +3633,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space,
                                          Stacktrace::InstanceSize()));
@@ -3640,7 +3677,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kRegExpCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawRegExp* regexp = objects_[i];
       s->AssignRef(regexp);
@@ -3657,7 +3694,7 @@
         s->WriteRef(*p);
       }
 
-      s->Write<intptr_t>(regexp->ptr()->num_registers_);
+      s->Write<int32_t>(regexp->ptr()->num_registers_);
       s->Write<int8_t>(regexp->ptr()->type_flags_);
     }
   }
@@ -3675,7 +3712,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space,
                                          RegExp::InstanceSize()));
@@ -3696,7 +3733,7 @@
         *p = d->ReadRef();
       }
 
-      regexp->ptr()->num_registers_ = d->Read<intptr_t>();
+      regexp->ptr()->num_registers_ = d->Read<int32_t>();
       regexp->ptr()->type_flags_ = d->Read<int8_t>();
     }
   }
@@ -3730,7 +3767,7 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kLinkedHashMapCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawLinkedHashMap* map = objects_[i];
       s->AssignRef(map);
@@ -3750,7 +3787,7 @@
       const intptr_t deleted_keys = Smi::Value(map->ptr()->deleted_keys_);
 
       // Write out the number of (not deleted) key/value pairs that will follow.
-      s->Write<intptr_t>((used_data >> 1) - deleted_keys);
+      s->Write<int32_t>((used_data >> 1) - deleted_keys);
 
       RawArray* data_array = map->ptr()->data_;
       RawObject** data_elements = data_array->ptr()->data();
@@ -3778,7 +3815,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space,
                                          LinkedHashMap::InstanceSize()));
@@ -3801,7 +3838,7 @@
           reinterpret_cast<RawTypeArguments*>(d->ReadRef());
 
       // TODO(rmacnak): Reserve ref ids and co-allocate in ReadAlloc.
-      intptr_t pairs = d->Read<intptr_t>();
+      intptr_t pairs = d->Read<int32_t>();
       intptr_t used_data = pairs << 1;
       intptr_t data_size = Utils::Maximum(
           Utils::RoundUpToPowerOfTwo(used_data),
@@ -3848,11 +3885,11 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(cid_);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawArray* array = objects_[i];
       intptr_t length = Smi::Value(array->ptr()->length_);
-      s->Write<intptr_t>(length);
+      s->Write<int32_t>(length);
       s->AssignRef(array);
     }
   }
@@ -3862,7 +3899,7 @@
     for (intptr_t i = 0; i < count; i++) {
       RawArray* array = objects_[i];
       intptr_t length = Smi::Value(array->ptr()->length_);
-      s->Write<intptr_t>(length);
+      s->Write<int32_t>(length);
       s->Write<bool>(array->IsCanonical());
       s->WriteRef(array->ptr()->type_arguments_);
       for (intptr_t j = 0; j < length; j++) {
@@ -3885,9 +3922,9 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
-      intptr_t length = d->Read<intptr_t>();
+      intptr_t length = d->Read<int32_t>();
       d->AssignRef(AllocateUninitialized(old_space,
                                          Array::InstanceSize(length)));
     }
@@ -3899,7 +3936,7 @@
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawArray* array = reinterpret_cast<RawArray*>(d->Ref(id));
-      intptr_t length = d->Read<intptr_t>();
+      intptr_t length = d->Read<int32_t>();
       bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(array, cid_,
                                      Array::InstanceSize(length),
@@ -3931,11 +3968,11 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kOneByteStringCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawOneByteString* str = objects_[i];
       intptr_t length = Smi::Value(str->ptr()->length_);
-      s->Write<intptr_t>(length);
+      s->Write<int32_t>(length);
       s->AssignRef(str);
     }
   }
@@ -3945,7 +3982,7 @@
     for (intptr_t i = 0; i < count; i++) {
       RawOneByteString* str = objects_[i];
       intptr_t length = Smi::Value(str->ptr()->length_);
-      s->Write<intptr_t>(length);
+      s->Write<int32_t>(length);
       s->Write<bool>(str->IsCanonical());
       intptr_t hash = Smi::Value(str->ptr()->hash_);
       s->Write<int32_t>(hash);
@@ -3966,9 +4003,9 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
-      intptr_t length = d->Read<intptr_t>();
+      intptr_t length = d->Read<int32_t>();
       d->AssignRef(AllocateUninitialized(old_space,
                                          OneByteString::InstanceSize(length)));
     }
@@ -3980,13 +4017,13 @@
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawOneByteString* str = reinterpret_cast<RawOneByteString*>(d->Ref(id));
-      intptr_t length = d->Read<intptr_t>();
+      intptr_t length = d->Read<int32_t>();
       bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(str, kOneByteStringCid,
                                      OneByteString::InstanceSize(length),
                                      is_vm_object, is_canonical);
       str->ptr()->length_ = Smi::New(length);
-      str->ptr()->hash_ = Smi::New(d->Read<intptr_t>());
+      str->ptr()->hash_ = Smi::New(d->Read<int32_t>());
       for (intptr_t j = 0; j < length; j++) {
         str->ptr()->data()[j] = d->Read<uint8_t>();
       }
@@ -4008,11 +4045,11 @@
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kTwoByteStringCid);
     intptr_t count = objects_.length();
-    s->Write<intptr_t>(count);
+    s->Write<int32_t>(count);
     for (intptr_t i = 0; i < count; i++) {
       RawTwoByteString* str = objects_[i];
       intptr_t length = Smi::Value(str->ptr()->length_);
-      s->Write<intptr_t>(length);
+      s->Write<int32_t>(length);
       s->AssignRef(str);
     }
   }
@@ -4022,7 +4059,7 @@
     for (intptr_t i = 0; i < count; i++) {
       RawTwoByteString* str = objects_[i];
       intptr_t length = Smi::Value(str->ptr()->length_);
-      s->Write<intptr_t>(length);
+      s->Write<int32_t>(length);
       s->Write<bool>(str->IsCanonical());
       intptr_t hash = Smi::Value(str->ptr()->hash_);
       s->Write<int32_t>(hash);
@@ -4043,9 +4080,9 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->Read<intptr_t>();
+    intptr_t count = d->Read<int32_t>();
     for (intptr_t i = 0; i < count; i++) {
-      intptr_t length = d->Read<intptr_t>();
+      intptr_t length = d->Read<int32_t>();
       d->AssignRef(AllocateUninitialized(old_space,
                                          TwoByteString::InstanceSize(length)));
     }
@@ -4058,7 +4095,7 @@
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawTwoByteString* str =
           reinterpret_cast<RawTwoByteString*>(d->Ref(id));
-      intptr_t length = d->Read<intptr_t>();
+      intptr_t length = d->Read<int32_t>();
       bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(str, kTwoByteStringCid,
                                      TwoByteString::InstanceSize(length),
@@ -4196,7 +4233,9 @@
 void Serializer::Trace(RawObject* object) {
   intptr_t cid;
   if (!object->IsHeapObject()) {
-    cid = kSmiCid;
+    // Smis are merged into the Mint cluster because Smis for the writer might
+    // become Mints for the reader and vice versa.
+    cid = kMintCid;
   } else {
     cid = object->GetClassId();
   }
@@ -4227,7 +4266,7 @@
 
 
 #if defined(DEBUG)
-static const intptr_t kSectionMarker = 0xABAB;
+static const int32_t kSectionMarker = 0xABAB;
 #endif
 
 void Serializer::Serialize() {
@@ -4244,6 +4283,11 @@
   }
 
   intptr_t num_objects = num_base_objects_ + num_written_objects_;
+#if defined(ARCH_IS_64_BIT)
+  if (!Utils::IsInt(32, num_objects)) {
+    FATAL("Ref overflow");
+  }
+#endif
 
   Write<int32_t>(num_objects);
   Write<int32_t>(num_clusters);
@@ -4253,7 +4297,7 @@
     if (cluster != NULL) {
       cluster->WriteAlloc(this);
 #if defined(DEBUG)
-      Write<intptr_t>(next_ref_index_);
+      Write<int32_t>(next_ref_index_);
 #endif
     }
   }
@@ -4266,7 +4310,7 @@
     if (cluster != NULL) {
       cluster->WriteFill(this);
 #if defined(DEBUG)
-      Write<intptr_t>(kSectionMarker);
+      Write<int32_t>(kSectionMarker);
 #endif
     }
   }
@@ -4336,7 +4380,7 @@
   }
 
 #if defined(DEBUG)
-  Write<intptr_t>(kSectionMarker);
+  Write<int32_t>(kSectionMarker);
 #endif
 
   // Note we are not clearing the object id table. The full ref table
@@ -4379,7 +4423,7 @@
   }
 
 #if defined(DEBUG)
-  Write<intptr_t>(kSectionMarker);
+  Write<int32_t>(kSectionMarker);
 #endif
 
   heap_->ResetObjectIdTable();
@@ -4599,7 +4643,7 @@
       clusters_[i] = ReadCluster();
       clusters_[i]->ReadAlloc(this);
 #if defined(DEBUG)
-      intptr_t serializers_next_ref_index_ = Read<intptr_t>();
+      intptr_t serializers_next_ref_index_ = Read<int32_t>();
       ASSERT(serializers_next_ref_index_ == next_ref_index_);
 #endif
     }
@@ -4614,7 +4658,7 @@
     for (intptr_t i = 0; i < num_clusters_; i++) {
       clusters_[i]->ReadFill(this);
 #if defined(DEBUG)
-      intptr_t section_marker = Read<intptr_t>();
+      int32_t section_marker = Read<int32_t>();
       ASSERT(section_marker == kSectionMarker);
 #endif
     }
@@ -4698,7 +4742,7 @@
     }
 
 #if defined(DEBUG)
-    intptr_t section_marker = Read<intptr_t>();
+    int32_t section_marker = Read<int32_t>();
     ASSERT(section_marker == kSectionMarker);
 #endif
 
@@ -4739,7 +4783,7 @@
     }
 
 #if defined(DEBUG)
-    intptr_t section_marker = Read<intptr_t>();
+    int32_t section_marker = Read<int32_t>();
     ASSERT(section_marker == kSectionMarker);
 #endif
 
@@ -4766,27 +4810,27 @@
 }
 
 
-// An object visitor which will iterate over all the script objects in the heap
-// and either count them or collect them into an array. This is used during
-// full snapshot generation of the VM isolate to write out all script
-// objects and their accompanying token streams.
-class ScriptVisitor : public ObjectVisitor {
+// An object visitor which will iterate over all the token stream objects in the
+// heap and either count them or collect them into an array. This is used during
+// full snapshot generation of the VM isolate to write out all token streams so
+// they will be shared across all isolates.
+class SnapshotTokenStreamVisitor : public ObjectVisitor {
  public:
-  explicit ScriptVisitor(Thread* thread) :
+  explicit SnapshotTokenStreamVisitor(Thread* thread) :
       objHandle_(Object::Handle(thread->zone())),
       count_(0),
-      scripts_(NULL) {}
+      token_streams_(NULL) {}
 
-  ScriptVisitor(Thread* thread, const Array* scripts) :
+  SnapshotTokenStreamVisitor(Thread* thread, const Array* token_streams) :
       objHandle_(Object::Handle(thread->zone())),
       count_(0),
-      scripts_(scripts) {}
+      token_streams_(token_streams) {}
 
   void VisitObject(RawObject* obj) {
-    if (obj->IsScript()) {
-      if (scripts_ != NULL) {
+    if (obj->IsTokenStream()) {
+      if (token_streams_ != NULL) {
         objHandle_ = obj;
-        scripts_->SetAt(count_, objHandle_);
+        token_streams_->SetAt(count_, objHandle_);
       }
       count_ += 1;
     }
@@ -4797,7 +4841,7 @@
  private:
   Object& objHandle_;
   intptr_t count_;
-  const Array* scripts_;
+  const Array* token_streams_;
 };
 
 
@@ -4814,7 +4858,7 @@
       vm_isolate_snapshot_size_(0),
       isolate_snapshot_size_(0),
       instructions_writer_(instructions_writer),
-      scripts_(Array::Handle(zone())),
+      token_streams_(Array::Handle(zone())),
       saved_symbol_table_(Array::Handle(zone())),
       new_vm_symbol_table_(Array::Handle(zone())) {
   ASSERT(isolate_snapshot_buffer_ != NULL);
@@ -4837,16 +4881,16 @@
     NOT_IN_PRODUCT(TimelineDurationScope tds(thread(),
         Timeline::GetIsolateStream(), "PrepareNewVMIsolate"));
 
-    // Collect all the script objects and their accompanying token stream
-    // objects into an array so that we can write it out as part of the VM
-    // isolate snapshot. We first count the number of script objects, allocate
-    // an array and then fill it up with the script objects.
-    ScriptVisitor scripts_counter(thread());
-    heap()->IterateOldObjects(&scripts_counter);
-    Dart::vm_isolate()->heap()->IterateOldObjects(&scripts_counter);
-    intptr_t count = scripts_counter.count();
-    scripts_ = Array::New(count, Heap::kOld);
-    ScriptVisitor script_visitor(thread(), &scripts_);
+    // Collect all the token stream objects into an array so that we can write
+    // it out as part of the VM isolate snapshot. We first count the number of
+    // token streams, allocate an array and then fill it up with the token
+    // streams.
+    SnapshotTokenStreamVisitor token_streams_counter(thread());
+    heap()->IterateOldObjects(&token_streams_counter);
+    Dart::vm_isolate()->heap()->IterateOldObjects(&token_streams_counter);
+    intptr_t count = token_streams_counter.count();
+    token_streams_ = Array::New(count, Heap::kOld);
+    SnapshotTokenStreamVisitor script_visitor(thread(), &token_streams_);
     heap()->IterateOldObjects(&script_visitor);
     Dart::vm_isolate()->heap()->IterateOldObjects(&script_visitor);
     ASSERT(script_visitor.count() == count);
@@ -4873,7 +4917,7 @@
     saved_symbol_table_ = Array::null();
   }
   new_vm_symbol_table_ = Array::null();
-  scripts_ = Array::null();
+  token_streams_ = Array::null();
 }
 
 
@@ -4894,11 +4938,11 @@
   /*
    * Now Write out the following
    * - the symbol table
-   * - all the scripts and token streams for these scripts
+   * - all the token streams
    * - the stub code (precompiled snapshots only)
    **/
   intptr_t num_objects = serializer.WriteVMSnapshot(new_vm_symbol_table_,
-                                                    scripts_);
+                                                    token_streams_);
   serializer.FillHeader(serializer.kind());
 
   vm_isolate_snapshot_size_ = serializer.bytes_written();
diff --git a/runtime/vm/clustered_snapshot.h b/runtime/vm/clustered_snapshot.h
index b2bdd0c..aae4e82 100644
--- a/runtime/vm/clustered_snapshot.h
+++ b/runtime/vm/clustered_snapshot.h
@@ -12,6 +12,7 @@
 #include "vm/exceptions.h"
 #include "vm/globals.h"
 #include "vm/growable_array.h"
+#include "vm/hash_map.h"
 #include "vm/heap.h"
 #include "vm/isolate.h"
 #include "vm/object.h"
@@ -83,15 +84,34 @@
 };
 
 
-enum {
-  kRefTagSize = 1,
-  kRefTagShift = 1,
-  kRefTagMask = 1,
-  kSmiRefTag = 0x0,
-  kHeapRefTag = 0x1,
+class SmiObjectIdPair {
+ public:
+  SmiObjectIdPair() : smi_(NULL), id_(0) { }
+  RawSmi* smi_;
+  intptr_t id_;
+
+  bool operator==(const SmiObjectIdPair& other) const {
+    return (smi_ == other.smi_) && (id_ == other.id_);
+  }
 };
 
 
+class SmiObjectIdPairTrait {
+ public:
+  typedef RawSmi* Key;
+  typedef intptr_t Value;
+  typedef SmiObjectIdPair Pair;
+
+  static Key KeyOf(Pair kv) { return kv.smi_; }
+  static Value ValueOf(Pair kv) { return kv.id_; }
+  static inline intptr_t Hashcode(Key key) { return Smi::Value(key); }
+  static inline bool IsKeyEqual(Pair kv, Key key) { return kv.smi_ == key; }
+};
+
+
+typedef DirectChainedHashMap<SmiObjectIdPairTrait> SmiObjectIdMap;
+
+
 class Serializer : public StackResource {
  public:
   Serializer(Thread* thread,
@@ -114,13 +134,36 @@
 
   void AssignRef(RawObject* object) {
     ASSERT(next_ref_index_ != 0);
-    heap_->SetObjectId(object, next_ref_index_);
-    ASSERT(heap_->GetObjectId(object) == next_ref_index_);
+    if (object->IsHeapObject()) {
+      heap_->SetObjectId(object, next_ref_index_);
+      ASSERT(heap_->GetObjectId(object) == next_ref_index_);
+    } else {
+      RawSmi* smi = Smi::RawCast(object);
+      SmiObjectIdPair* existing_pair = smi_ids_.Lookup(smi);
+      if (existing_pair != NULL) {
+        ASSERT(existing_pair->id_ == 1);
+        existing_pair->id_ = next_ref_index_;
+      } else {
+        SmiObjectIdPair new_pair;
+        new_pair.smi_ = smi;
+        new_pair.id_ = next_ref_index_;
+        smi_ids_.Insert(new_pair);
+      }
+    }
     next_ref_index_++;
   }
 
   void Push(RawObject* object) {
     if (!object->IsHeapObject()) {
+      RawSmi* smi = Smi::RawCast(object);
+      if (smi_ids_.Lookup(smi) == NULL) {
+        SmiObjectIdPair pair;
+        pair.smi_ = smi;
+        pair.id_ = 1;
+        smi_ids_.Insert(pair);
+        stack_.Add(object);
+        num_written_objects_++;
+      }
       return;
     }
 
@@ -180,9 +223,12 @@
 
   void WriteRef(RawObject* object) {
     if (!object->IsHeapObject()) {
-      ASSERT(static_cast<intptr_t>(kSmiRefTag) ==
-             static_cast<intptr_t>(kSmiTag));
-      Write<intptr_t>(reinterpret_cast<intptr_t>(object));
+      RawSmi* smi = Smi::RawCast(object);
+      intptr_t id = smi_ids_.Lookup(smi)->id_;
+      if (id == 0) {
+        FATAL("Missing ref");
+      }
+      Write<int32_t>(id);
       return;
     }
 
@@ -200,7 +246,7 @@
       }
       FATAL("Missing ref");
     }
-    Write<intptr_t>((id << kRefTagShift) | kHeapRefTag);
+    Write<int32_t>(id);
   }
 
   void WriteTokenPosition(TokenPosition pos) {
@@ -234,6 +280,7 @@
   intptr_t num_base_objects_;
   intptr_t num_written_objects_;
   intptr_t next_ref_index_;
+  SmiObjectIdMap smi_ids_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(Serializer);
 };
@@ -300,13 +347,8 @@
   }
 
   RawObject* ReadRef() {
-    intptr_t index = Read<intptr_t>();
-    if ((index & kRefTagMask) == kSmiRefTag) {
-      ASSERT(static_cast<intptr_t>(kSmiRefTag) ==
-             static_cast<intptr_t>(kSmiTag));
-      return reinterpret_cast<RawSmi*>(index);
-    }
-    return Ref(index >> kRefTagShift);
+    int32_t index = Read<int32_t>();
+    return Ref(index);
   }
 
   TokenPosition ReadTokenPosition() {
@@ -400,7 +442,7 @@
   intptr_t isolate_snapshot_size_;
   ForwardList* forward_list_;
   InstructionsWriter* instructions_writer_;
-  Array& scripts_;
+  Array& token_streams_;
   Array& saved_symbol_table_;
   Array& new_vm_symbol_table_;
 
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 4b572a7..ea33dae 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -91,6 +91,35 @@
 }
 
 
+DEFINE_RUNTIME_ENTRY(RangeError, 2) {
+  const Instance& length = Instance::CheckedHandle(arguments.ArgAt(0));
+  const Instance& index = Instance::CheckedHandle(arguments.ArgAt(1));
+  if (!length.IsInteger()) {
+    // Throw: new ArgumentError.value(length, "length", "is not an integer");
+    const Array& args = Array::Handle(Array::New(3));
+    args.SetAt(0, length);
+    args.SetAt(1, Symbols::Length());
+    args.SetAt(2, String::Handle(String::New("is not an integer")));
+    Exceptions::ThrowByType(Exceptions::kArgumentValue, args);
+  }
+  if (!index.IsInteger()) {
+    // Throw: new ArgumentError.value(index, "index", "is not an integer");
+    const Array& args = Array::Handle(Array::New(3));
+    args.SetAt(0, index);
+    args.SetAt(1, Symbols::Index());
+    args.SetAt(2, String::Handle(String::New("is not an integer")));
+    Exceptions::ThrowByType(Exceptions::kArgumentValue, args);
+  }
+  // Throw: new RangeError.range(index, 0, length, "length");
+  const Array& args = Array::Handle(Array::New(4));
+  args.SetAt(0, index);
+  args.SetAt(1, Integer::Handle(Integer::New(0)));
+  args.SetAt(2, length);
+  args.SetAt(3, Symbols::Length());
+  Exceptions::ThrowByType(Exceptions::kRange, args);
+}
+
+
 // Allocation of a fixed length array of given element type.
 // This runtime entry is never called for allocating a List of a generic type,
 // because a prior run time call instantiates the element type if necessary.
@@ -782,6 +811,25 @@
   return result.raw();
 }
 
+
+// Perform the subtype and return constant function based on the result.
+static RawFunction* ComputeTypeCheckTarget(const Instance& receiver,
+                                           const AbstractType& type,
+                                           const ArgumentsDescriptor& desc) {
+  const TypeArguments& checked_type_arguments = TypeArguments::Handle();
+  Error& error = Error::Handle();
+  bool result = receiver.IsInstanceOf(type, checked_type_arguments, &error);
+  ASSERT(error.IsNull());
+  ObjectStore* store = Isolate::Current()->object_store();
+  const Function& target
+      = Function::Handle(result
+                         ? store->simple_instance_of_true_function()
+                         : store->simple_instance_of_false_function());
+  ASSERT(!target.IsNull());
+  return target.raw();;
+}
+
+
 static RawFunction* InlineCacheMissHandler(
     const GrowableArray<const Instance*>& args,
     const ICData& ic_data) {
@@ -790,8 +838,17 @@
       arguments_descriptor(Array::Handle(ic_data.arguments_descriptor()));
   String& function_name = String::Handle(ic_data.target_name());
   ASSERT(function_name.IsSymbol());
+
   Function& target_function = Function::Handle(
       Resolver::ResolveDynamic(receiver, function_name, arguments_descriptor));
+
+  ObjectStore* store = Isolate::Current()->object_store();
+  if (target_function.raw() == store->simple_instance_of_function()) {
+    // Replace the target function with constant function.
+    const AbstractType& type = AbstractType::Cast(*args[1]);
+    target_function
+        = ComputeTypeCheckTarget(receiver, type, arguments_descriptor);
+  }
   if (target_function.IsNull()) {
     if (FLAG_trace_ic) {
       OS::PrintErr("InlineCacheMissHandler NULL function for %s receiver: %s\n",
@@ -1242,9 +1299,11 @@
   bool do_deopt = false;
   bool do_stacktrace = false;
   bool do_reload = false;
+  const intptr_t isolate_reload_every =
+      isolate->reload_every_n_stack_overflow_checks();
   if ((FLAG_deoptimize_every > 0) ||
       (FLAG_stacktrace_every > 0) ||
-      (FLAG_reload_every > 0)) {
+      (isolate_reload_every > 0)) {
     // TODO(turnidge): To make --deoptimize_every and
     // --stacktrace-every faster we could move this increment/test to
     // the generated code.
@@ -1257,14 +1316,14 @@
         (count % FLAG_stacktrace_every) == 0) {
       do_stacktrace = true;
     }
-    if ((FLAG_reload_every > 0) &&
-        (count % FLAG_reload_every) == 0) {
+    if ((isolate_reload_every > 0) &&
+        (count % isolate_reload_every) == 0) {
       do_reload = isolate->CanReload();
     }
   }
   if ((FLAG_deoptimize_filter != NULL) ||
       (FLAG_stacktrace_filter != NULL) ||
-      FLAG_reload_every_optimized) {
+       FLAG_reload_every_optimized) {
     DartFrameIterator iterator;
     StackFrame* frame = iterator.NextFrame();
     ASSERT(frame != NULL);
@@ -1297,10 +1356,16 @@
     DeoptimizeFunctionsOnStack();
   }
   if (do_reload) {
-    if (FLAG_reload_every_back_off) {
-      FLAG_reload_every *= 2;
+#ifndef PRODUCT
+    // Maybe adjust the rate of future reloads.
+    isolate->MaybeIncreaseReloadEveryNStackOverflowChecks();
+    // Issue a reload.
+    isolate->ReloadSources();
+    const Error& error = Error::Handle(isolate->sticky_reload_error());
+    if (!error.IsNull()) {
+      FATAL1("*** Isolate reload failed: %s\n", error.ToErrorCString());
     }
-    NOT_IN_PRODUCT(isolate->ReloadSources();)
+#endif
   }
   if (FLAG_support_debugger && do_stacktrace) {
     String& var_name = String::Handle();
@@ -1317,6 +1382,10 @@
     intptr_t num_frames = stack->Length();
     for (intptr_t i = 0; i < num_frames; i++) {
       ActivationFrame* frame = stack->FrameAt(i);
+#ifndef DART_PRECOMPILED_RUNTIME
+      // Ensure that we have unoptimized code.
+      frame->function().EnsureHasCompiledUnoptimizedCode();
+#endif
       // Variable locations and number are unknown when precompiling.
       const int num_vars =
          FLAG_precompiled_runtime ? 0 : frame->NumLocalVariables();
@@ -1341,8 +1410,16 @@
     ASSERT(frame != NULL);
     const Code& code = Code::ZoneHandle(frame->LookupDartCode());
     ASSERT(!code.IsNull());
+    ASSERT(!code.is_optimized());
     const Function& function = Function::Handle(code.function());
     ASSERT(!function.IsNull());
+
+    // If the code of the frame does not match the function's unoptimized code,
+    // we bail out since the code was reset by an isolate reload.
+    if (code.raw() != function.unoptimized_code()) {
+      return;
+    }
+
     // Since the code is referenced from the frame and the ZoneHandle,
     // it cannot have been removed from the function.
     ASSERT(function.HasCode());
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index cc3b691..1bc179c 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -1167,8 +1167,10 @@
         done = true;
       }
 
-      // Clear the error if it was not a real error, but just a bailout.
-      if (error.IsLanguageError() &&
+      // If is is not a background compilation, clear the error if it was not a
+      // real error, but just a bailout. If we're it a background compilation
+      // this will be dealt with in the caller.
+      if (!Compiler::IsBackgroundCompilation() && error.IsLanguageError() &&
           (LanguageError::Cast(error).kind() == Report::kBailout)) {
         thread()->clear_sticky_error();
       }
@@ -1277,6 +1279,21 @@
             THR_Print("Aborted background compilation: %s\n",
                 function.ToFullyQualifiedCString());
           }
+          {
+            // If it was a bailout, then disable optimization.
+            Error& error = Error::Handle();
+            // We got an error during compilation.
+            error = thread->sticky_error();
+            thread->clear_sticky_error();
+            if (error.IsLanguageError() &&
+                LanguageError::Cast(error).kind() == Report::kBailout) {
+              if (FLAG_trace_compiler) {
+                THR_Print("--> disabling optimizations for '%s'\n",
+                          function.ToFullyQualifiedCString());
+              }
+              function.SetIsOptimizable(false);
+            }
+          }
           return Error::null();
         }
         // Optimizer bailed out. Disable optimizations and never try again.
@@ -1295,6 +1312,7 @@
         // We got an error during compilation.
         error = thread->sticky_error();
         thread->clear_sticky_error();
+        // The non-optimizing compiler should not bail out.
         ASSERT(error.IsLanguageError() &&
                LanguageError::Cast(error).kind() != Report::kBailout);
         return error.raw();
@@ -1870,8 +1888,9 @@
             function = Function::null();
           } else {
             qelem = function_queue()->Remove();
-            if (FLAG_stress_test_background_compilation) {
-              const Function& old = Function::Handle(qelem->Function());
+            const Function& old = Function::Handle(qelem->Function());
+            if ((!old.HasOptimizedCode() && old.IsOptimizable()) ||
+                 FLAG_stress_test_background_compilation) {
               if (Compiler::CanOptimizeFunction(thread, old)) {
                 QueueElement* repeat_qelem = new QueueElement(old);
                 function_queue()->Add(repeat_qelem);
diff --git a/runtime/vm/constant_propagator.cc b/runtime/vm/constant_propagator.cc
index 6b97f7d..1f5290d 100644
--- a/runtime/vm/constant_propagator.cc
+++ b/runtime/vm/constant_propagator.cc
@@ -253,6 +253,10 @@
 void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) { }
 
 
+void ConstantPropagator::VisitGenericCheckBound(GenericCheckBoundInstr* instr) {
+}
+
+
 void ConstantPropagator::VisitCheckEitherNonSmi(
     CheckEitherNonSmiInstr* instr) { }
 
diff --git a/runtime/vm/constants_dbc.h b/runtime/vm/constants_dbc.h
index 5d901b8..e84ae57 100644
--- a/runtime/vm/constants_dbc.h
+++ b/runtime/vm/constants_dbc.h
@@ -148,6 +148,11 @@
 //    Invoke function in SP[0] with arguments SP[-(1+ArgC)], ..., SP[-1] and
 //    argument descriptor PP[D].
 //
+//  - IndirectStaticCall ArgC, D
+//
+//    Invoke the function given by the ICData in SP[0] with arguments
+//    SP[-(1+ArgC)], ..., SP[-1] and argument descriptor PP[D].
+//
 //  - InstanceCall<N> ArgC, D; InstanceCall<N>Opt ArgC, D
 //
 //    Lookup and invoke method with N checked arguments using ICData in PP[D]
@@ -183,11 +188,29 @@
 //    the immediately following instruction is skipped. These instructions
 //    expect their operands to be Smis, but don't check that they are.
 //
+//  - ShrImm rA, rB, rC
+//
+//    FP[rA] <- FP[rB] >> rC. Shifts the Smi in FP[rB] right by rC. rC is
+//    assumed to be a legal positive number by which righ-shifting is possible.
+//
+//  - Min, Max rA, rB, rC
+//
+//    FP[rA] <- {min, max}(FP[rB], FP[rC]). Assumes that FP[rB], and FP[rC] are
+//    Smis.
+//
 //  - Neg rA , rD
 //
 //    FP[rA] <- -FP[rD]. Assumes FP[rD] is a Smi. If there is no overflow the
 //    immediately following instruction is skipped.
 //
+//  - DMin, DMax, DAdd, DSub, DMul, DDiv, DPow, DMod rA, rB, rC
+//
+//    Arithmetic operaions on unboxed doubles. FP[rA] <- FP[rB] op FP[rC].
+//
+//  - DNeg, DCos, DSin, DSqrt rA, rD
+//
+//    FP[rA] <- op(FP[rD]). Assumes FP[rD] is an unboxed double.
+//
 //  - BitOr, BitAnd, BitXor rA, rB, rC
 //
 //    FP[rA] <- FP[rB] op FP[rC]. These instructions expect their operands to be
@@ -197,6 +220,30 @@
 //
 //    FP[rA] <- ~FP[rD]. As above, assumes FP[rD] is a Smi.
 //
+//  - WriteIntoDouble rA, rD
+//
+//    Box the double in FP[rD] with the result in FP[rA].
+//
+//  - UnboxDouble rA, rD
+//
+//    Unbox the double in FP[rD] into FP[rA]. Assumes FP[rD] is a double.
+//
+//  - CheckedUnboxDouble rA, rD
+//
+//    Unboxes FP[rD] into FP[rA] and skips the following instruction unless
+//    FP[rD] is not a double or a Smi. When FP[rD] is a Smi, converts it to a
+//    double.
+//
+//  - SmiToDouble rA, rD
+//
+//    Convert the Smi in FP[rD] to an unboxed double in FP[rA].
+//
+//  - DoubleToSmi rA, rD
+//
+//    If the unboxed double in FP[rD] can be converted to a Smi in FP[rA], then
+//    this instruction does so, and skips the following instruction. Otherwise,
+//    the following instruction is not skipped.
+//
 //  - StoreStaticT`OS D
 //
 //    Stores TOS into the static field PP[D].
@@ -228,6 +275,13 @@
 //    Cond is Eq or Ne. Skips the next instruction unless the given condition
 //    holds.
 //
+//  - If<Cond> rA, rD
+//
+//    Cond is Le, Lt, Ge, Gt, unsigned variants ULe, ULt, UGe, UGt, and
+//    unboxed double variants DEq, DNe, DLe, DLt, DGe, DGt.
+//    Skips the next instruction unless FP[rA] <Cond> FP[rD]. Assumes that
+//    FP[rA] and FP[rD] are Smis or unboxed doubles as inidcated by <Cond>.
+//
 //  - CreateArrayTOS
 //
 //    Allocate array of length SP[0] with type arguments SP[-1].
@@ -247,8 +301,23 @@
 //
 //  - StoreIndexed rA, rB, rC
 //
-//    Store rC into array rA at index rB. No typechecking is done.
-//    rA is assumed to be a RawArray, rB to be a smi.
+//    Store FP[rC] into array FP[rA] at index FP[rB]. No typechecking is done.
+//    FP[rA] is assumed to be a RawArray, FP[rB] to be a smi.
+//
+//  - StoreFloat64Indexed rA, rB, rC
+//
+//    Store the unboxed double in FP[rC] into the typed data array at FP[rA]
+//    at index FP[rB].
+//
+//  - LoadIndexed rA, rB, rC
+//
+//    Loads from array FP[rB] at index FP[rC] into FP[rA]. No typechecking is
+//    done. FP[rB] is assumed to be a RawArray, and to contain a Smi at FP[rC].
+//
+//  - Load{Float64, OneByteString, TwoByteString}Indexed rA, rB, rC
+//
+//    Loads from typed data array FP[rB] at index FP[rC] into an unboxed double,
+//    or tagged Smi in FP[rA] as indicated by the type in the name.
 //
 //  - StoreField rA, B, rC
 //
@@ -376,13 +445,24 @@
 //    If FP[rA] & FP[rD] != 0, then skip the next instruction. FP[rA] and FP[rD]
 //    must be Smis.
 //
+//  - TestCids rA, D
+//
+//    The next D instructions must be Nops whose D field encodes a class id. If
+//    the class id of FP[rA] matches, jump to PC + N + 1 if the matching Nop's
+//    A != 0 or PC + N + 2 if the matching Nop's A = 0. If no match is found,
+//    jump to PC + N.
+//
 //  - CheckSmi rA
 //
 //    If FP[rA] is a Smi, then skip the next instruction.
 //
+//  - CheckEitherNonSmi rA, rD
+//
+//    If either FP[rA] or FP[rD] is not a Smi, then skip the next instruction.
+//
 //  - CheckClassId rA, D
 //
-//    If the object at FP[rA]'s class id matches the class id D, then skip the
+//    If the class id in FP[rA] matches the class id D, then skip the
 //    following instruction.
 //
 //  - CheckDenseSwitch rA, D
@@ -455,12 +535,12 @@
 //     tgt jump target relative to the PC of the current instruction
 //
 // TODO(vegorov) jump targets should be encoded relative to PC of the next
-//               instruction because PC is incremeted immediately after fetch
+//               instruction because PC is incremented immediately after fetch
 //               and before decoding.
 //
 #define BYTECODES_LIST(V)                              \
   V(Trap,                            0, ___, ___, ___) \
-  V(Nop,                             D, lit, ___, ___) \
+  V(Nop,                           A_D, num, lit, ___) \
   V(Compile,                         0, ___, ___, ___) \
   V(HotCheck,                      A_D, num, num, ___) \
   V(Intrinsic,                       A, num, ___, ___) \
@@ -479,6 +559,7 @@
   V(PushConstant,                    D, lit, ___, ___) \
   V(StoreLocal,                      X, xeg, ___, ___) \
   V(PopLocal,                        X, xeg, ___, ___) \
+  V(IndirectStaticCall,            A_D, num, num, ___) \
   V(StaticCall,                    A_D, num, num, ___) \
   V(InstanceCall1,                 A_D, num, num, ___) \
   V(InstanceCall2,                 A_D, num, num, ___) \
@@ -503,11 +584,31 @@
   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(ShrImm,                      A_B_C, reg, reg, num) \
   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(Min,                         A_B_C, reg, reg, reg) \
+  V(Max,                         A_B_C, reg, reg, reg) \
+  V(WriteIntoDouble,               A_D, reg, reg, ___) \
+  V(UnboxDouble,                   A_D, reg, reg, ___) \
+  V(CheckedUnboxDouble,            A_D, reg, reg, ___) \
+  V(SmiToDouble,                   A_D, reg, reg, ___) \
+  V(DoubleToSmi,                   A_D, reg, reg, ___) \
+  V(DAdd,                        A_B_C, reg, reg, reg) \
+  V(DSub,                        A_B_C, reg, reg, reg) \
+  V(DMul,                        A_B_C, reg, reg, reg) \
+  V(DDiv,                        A_B_C, reg, reg, reg) \
+  V(DNeg,                          A_D, reg, reg, ___) \
+  V(DSqrt,                         A_D, reg, reg, ___) \
+  V(DMin,                        A_B_C, reg, reg, reg) \
+  V(DMax,                        A_B_C, reg, reg, reg) \
+  V(DCos,                          A_D, reg, reg, ___) \
+  V(DSin,                          A_D, reg, reg, ___) \
+  V(DPow,                        A_B_C, reg, reg, reg) \
+  V(DMod,                        A_B_C, reg, reg, reg) \
   V(StoreStaticTOS,                  D, lit, ___, ___) \
   V(PushStatic,                      D, lit, ___, ___) \
   V(InitStaticTOS,                   0, ___, ___, ___) \
@@ -517,6 +618,20 @@
   V(IfEqStrictNumTOS,                0, ___, ___, ___) \
   V(IfNeStrict,                    A_D, reg, reg, ___) \
   V(IfEqStrict,                    A_D, reg, reg, ___) \
+  V(IfLe,                          A_D, reg, reg, ___) \
+  V(IfLt,                          A_D, reg, reg, ___) \
+  V(IfGe,                          A_D, reg, reg, ___) \
+  V(IfGt,                          A_D, reg, reg, ___) \
+  V(IfULe,                         A_D, reg, reg, ___) \
+  V(IfULt,                         A_D, reg, reg, ___) \
+  V(IfUGe,                         A_D, reg, reg, ___) \
+  V(IfUGt,                         A_D, reg, reg, ___) \
+  V(IfDNe,                         A_D, reg, reg, ___) \
+  V(IfDEq,                         A_D, reg, reg, ___) \
+  V(IfDLe,                         A_D, reg, reg, ___) \
+  V(IfDLt,                         A_D, reg, reg, ___) \
+  V(IfDGe,                         A_D, reg, reg, ___) \
+  V(IfDGt,                         A_D, reg, reg, ___) \
   V(IfNeStrictNum,                 A_D, reg, reg, ___) \
   V(IfEqStrictNum,                 A_D, reg, reg, ___) \
   V(IfEqNull,                        A, reg, ___, ___) \
@@ -526,6 +641,11 @@
   V(AllocateT,                       0, ___, ___, ___) \
   V(StoreIndexedTOS,                 0, ___, ___, ___) \
   V(StoreIndexed,                A_B_C, reg, reg, reg) \
+  V(StoreFloat64Indexed,         A_B_C, reg, reg, reg) \
+  V(LoadIndexed,                 A_B_C, reg, reg, reg) \
+  V(LoadFloat64Indexed,          A_B_C, reg, reg, reg) \
+  V(LoadOneByteStringIndexed,    A_B_C, reg, reg, reg) \
+  V(LoadTwoByteStringIndexed,    A_B_C, reg, reg, reg) \
   V(StoreField,                  A_B_C, reg, num, reg) \
   V(StoreFieldTOS,                   D, num, ___, ___) \
   V(LoadField,                   A_B_C, reg, reg, num) \
@@ -547,7 +667,9 @@
   V(AssertAssignable,                D, num, lit, ___) \
   V(AssertBoolean,                   A, num, ___, ___) \
   V(TestSmi,                       A_D, reg, reg, ___) \
+  V(TestCids,                      A_D, reg, num, ___) \
   V(CheckSmi,                        A, reg, ___, ___) \
+  V(CheckEitherNonSmi,             A_D, reg, reg, ___) \
   V(CheckClassId,                  A_D, reg, num, ___) \
   V(CheckDenseSwitch,              A_D, reg, num, ___) \
   V(CheckCids,                   A_B_C, reg, num, ___) \
@@ -619,6 +741,7 @@
   DART_FORCE_INLINE static bool IsCallOpcode(Instr instr) {
     switch (DecodeOpcode(instr)) {
       case Bytecode::kStaticCall:
+      case Bytecode::kIndirectStaticCall:
       case Bytecode::kInstanceCall1:
       case Bytecode::kInstanceCall2:
       case Bytecode::kInstanceCall1Opt:
@@ -650,7 +773,7 @@
 
 const int16_t FPREG = 0;
 const int16_t SPREG = 1;
-const intptr_t kNumberOfCpuRegisters = 20;
+const intptr_t kNumberOfCpuRegisters = 32;
 const intptr_t kDartAvailableCpuRegs = -1;
 const intptr_t kNoRegister = -1;
 const intptr_t kReservedCpuRegisters = 0;
diff --git a/runtime/vm/cpuinfo_fuchsia.cc b/runtime/vm/cpuinfo_fuchsia.cc
index 04fe196..ad9e990 100644
--- a/runtime/vm/cpuinfo_fuchsia.cc
+++ b/runtime/vm/cpuinfo_fuchsia.cc
@@ -8,8 +8,7 @@
 #include "vm/cpuinfo.h"
 
 #include "platform/assert.h"
-
-// TODO(zra): Use "vm/cpuid.h"
+#include "vm/cpuid.h"
 
 namespace dart {
 
@@ -17,30 +16,55 @@
 const char* CpuInfo::fields_[kCpuInfoMax] = {0};
 
 void CpuInfo::InitOnce() {
-  UNIMPLEMENTED();
+  // TODO(zra): Add support for HOST_ARCH_ARM64
+#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
+  method_ = kCpuInfoCpuId;
+
+  // Initialize the CpuId information.
+  CpuId::InitOnce();
+
+  fields_[kCpuInfoProcessor] = "Processor";
+  fields_[kCpuInfoModel] = "Hardware";
+  fields_[kCpuInfoHardware] = "Hardware";
+  fields_[kCpuInfoFeatures] = "Features";
+#endif
 }
 
 
 void CpuInfo::Cleanup() {
-  UNIMPLEMENTED();
+  if (method_ == kCpuInfoCpuId) {
+    CpuId::Cleanup();
+  }
 }
 
 
 bool CpuInfo::FieldContains(CpuInfoIndices idx, const char* search_string) {
-  UNIMPLEMENTED();
-  return false;
+  if (method_ == kCpuInfoCpuId) {
+    return strstr(CpuId::field(idx), search_string);
+  } else {
+    return false;
+  }
 }
 
 
 const char* CpuInfo::ExtractField(CpuInfoIndices idx) {
-  UNIMPLEMENTED();
-  return "<undefined>";
+  if (method_ == kCpuInfoCpuId) {
+    return CpuId::field(idx);
+  } else {
+    return strdup("");
+  }
 }
 
 
 bool CpuInfo::HasField(const char* field) {
-  UNIMPLEMENTED();
-  return false;
+  if (method_ == kCpuInfoCpuId) {
+    return (strcmp(field, fields_[kCpuInfoProcessor]) == 0) ||
+           (strcmp(field, fields_[kCpuInfoModel]) == 0) ||
+           (strcmp(field, fields_[kCpuInfoHardware]) == 0) ||
+           (strcmp(field, fields_[kCpuInfoFeatures]) == 0);
+  } else {
+    return false;
+  }
 }
 
 }  // namespace dart
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 62c7226..0bd8730 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -41,7 +41,6 @@
 DECLARE_FLAG(bool, trace_time_all);
 DEFINE_FLAG(bool, keep_code, false,
             "Keep deoptimized code for profiling.");
-DEFINE_FLAG(bool, shutdown, true, "Do a clean shutdown of the VM");
 DEFINE_FLAG(bool, trace_shutdown, false, "Trace VM shutdown on stderr");
 
 Isolate* Dart::vm_isolate_ = NULL;
@@ -96,6 +95,7 @@
   CHECK_OFFSET(Isolate::heap_offset(), 8);
   CHECK_OFFSET(Thread::stack_limit_offset(), 4);
   CHECK_OFFSET(Thread::object_null_offset(), 36);
+  NOT_IN_PRODUCT(CHECK_OFFSET(sizeof(ClassHeapStats), 120));
 #endif
 #if defined(TARGET_ARCH_MIPS)
   // These offsets are embedded in precompiled instructions. We need simmips
@@ -104,6 +104,7 @@
   CHECK_OFFSET(Isolate::heap_offset(), 8);
   CHECK_OFFSET(Thread::stack_limit_offset(), 4);
   CHECK_OFFSET(Thread::object_null_offset(), 36);
+  NOT_IN_PRODUCT(CHECK_OFFSET(sizeof(ClassHeapStats), 120));
 #endif
 #if defined(TARGET_ARCH_ARM64)
   // These offsets are embedded in precompiled instructions. We need simarm64
@@ -112,6 +113,7 @@
   CHECK_OFFSET(Isolate::heap_offset(), 16);
   CHECK_OFFSET(Thread::stack_limit_offset(), 8);
   CHECK_OFFSET(Thread::object_null_offset(), 72);
+  NOT_IN_PRODUCT(CHECK_OFFSET(sizeof(ClassHeapStats), 208));
 #endif
 #undef CHECK_OFFSET
 }
@@ -375,105 +377,89 @@
     Thread::ExitIsolate();
   }
 
-  if (FLAG_shutdown) {
-    // Disable the creation of new isolates.
+  // Disable the creation of new isolates.
+  if (FLAG_trace_shutdown) {
+    OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Disabling isolate creation\n",
+                 timestamp());
+  }
+  Isolate::DisableIsolateCreation();
+
+  // Send the OOB Kill message to all remaining application isolates.
+  if (FLAG_trace_shutdown) {
+    OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Killing all app isolates\n",
+                 timestamp());
+  }
+  Isolate::KillAllIsolates(Isolate::kInternalKillMsg);
+
+  // Wait for all isolates, but the service and the vm isolate to shut down.
+  // Only do that if there is a service isolate running.
+  if (ServiceIsolate::IsRunning()) {
     if (FLAG_trace_shutdown) {
-      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Disabling isolate creation\n",
+      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down app isolates\n",
                    timestamp());
     }
-    Isolate::DisableIsolateCreation();
+    WaitForApplicationIsolateShutdown();
+  }
 
-    // Send the OOB Kill message to all remaining application isolates.
-    if (FLAG_trace_shutdown) {
-      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Killing all app isolates\n",
-                   timestamp());
-    }
-    Isolate::KillAllIsolates(Isolate::kInternalKillMsg);
+  // Shutdown the service isolate.
+  if (FLAG_trace_shutdown) {
+    OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down service isolate\n",
+                 timestamp());
+  }
+  ServiceIsolate::Shutdown();
 
-    // Wait for all isolates, but the service and the vm isolate to shut down.
-    // Only do that if there is a service isolate running.
-    if (ServiceIsolate::IsRunning()) {
-      if (FLAG_trace_shutdown) {
-        OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down app isolates\n",
-                     timestamp());
-      }
-      WaitForApplicationIsolateShutdown();
-    }
+  // Wait for the remaining isolate (service isolate) to shutdown
+  // before shutting down the thread pool.
+  if (FLAG_trace_shutdown) {
+    OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Waiting for isolate shutdown\n",
+                 timestamp());
+  }
+  WaitForIsolateShutdown();
 
-    // Shutdown the service isolate.
-    if (FLAG_trace_shutdown) {
-      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down service isolate\n",
-                   timestamp());
-    }
-    ServiceIsolate::Shutdown();
+  // Shutdown the thread pool. On return, all thread pool threads have exited.
+  if (FLAG_trace_shutdown) {
+    OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Deleting thread pool\n",
+                 timestamp());
+  }
+  delete thread_pool_;
+  thread_pool_ = NULL;
 
-    // Wait for the remaining isolate (service isolate) to shutdown
-    // before shutting down the thread pool.
-    if (FLAG_trace_shutdown) {
-      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Waiting for isolate shutdown\n",
-                   timestamp());
-    }
-    WaitForIsolateShutdown();
+  // Disable creation of any new OSThread structures which means no more new
+  // threads can do an EnterIsolate. This must come after isolate shutdown
+  // because new threads may need to be spawned to shutdown the isolates.
+  // This must come after deletion of the thread pool to avoid a race in which
+  // a thread spawned by the thread pool does not exit through the thread
+  // pool, messing up its bookkeeping.
+  if (FLAG_trace_shutdown) {
+    OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Disabling OS Thread creation\n",
+                 timestamp());
+  }
+  OSThread::DisableOSThreadCreation();
 
-    // Shutdown the thread pool. On return, all thread pool threads have exited.
-    if (FLAG_trace_shutdown) {
-      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Deleting thread pool\n",
-                   timestamp());
-    }
-    delete thread_pool_;
-    thread_pool_ = NULL;
+  // Set the VM isolate as current isolate.
+  if (FLAG_trace_shutdown) {
+    OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Cleaning up vm isolate\n",
+                 timestamp());
+  }
+  bool result = Thread::EnterIsolate(vm_isolate_);
+  ASSERT(result);
 
-    // Disable creation of any new OSThread structures which means no more new
-    // threads can do an EnterIsolate. This must come after isolate shutdown
-    // because new threads may need to be spawned to shutdown the isolates.
-    // This must come after deletion of the thread pool to avoid a race in which
-    // a thread spawned by the thread pool does not exit through the thread
-    // pool, messing up its bookkeeping.
-    if (FLAG_trace_shutdown) {
-      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Disabling OS Thread creation\n",
-                   timestamp());
-    }
-    OSThread::DisableOSThreadCreation();
+  ShutdownIsolate();
+  vm_isolate_ = NULL;
+  ASSERT(Isolate::IsolateListLength() == 0);
 
-    // Set the VM isolate as current isolate.
-    if (FLAG_trace_shutdown) {
-      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Cleaning up vm isolate\n",
-                   timestamp());
-    }
-    bool result = Thread::EnterIsolate(vm_isolate_);
-    ASSERT(result);
+  TargetCPUFeatures::Cleanup();
+  StoreBuffer::ShutDown();
 
-    ShutdownIsolate();
-    vm_isolate_ = NULL;
-    ASSERT(Isolate::IsolateListLength() == 0);
-
-    TargetCPUFeatures::Cleanup();
-    StoreBuffer::ShutDown();
-
-    // Delete the current thread's TLS and set it's TLS to null.
-    // If it is the last thread then the destructor would call
-    // OSThread::Cleanup.
-    OSThread* os_thread = OSThread::Current();
-    OSThread::SetCurrent(NULL);
-    delete os_thread;
-    if (FLAG_trace_shutdown) {
-      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Deleted os_thread\n",
-                   timestamp());
-    }
-  } else {
-    // Shutdown the service isolate.
-    if (FLAG_trace_shutdown) {
-      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down service isolate\n",
-                   timestamp());
-    }
-    ServiceIsolate::Shutdown();
-
-    // Disable thread creation.
-    if (FLAG_trace_shutdown) {
-      OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Disabling OS Thread creation\n",
-                   timestamp());
-    }
-    OSThread::DisableOSThreadCreation();
+  // Delete the current thread's TLS and set it's TLS to null.
+  // If it is the last thread then the destructor would call
+  // OSThread::Cleanup.
+  OSThread* os_thread = OSThread::Current();
+  OSThread::SetCurrent(NULL);
+  delete os_thread;
+  if (FLAG_trace_shutdown) {
+    OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Deleted os_thread\n",
+                 timestamp());
   }
 
   if (FLAG_trace_shutdown) {
@@ -674,12 +660,6 @@
 #elif defined(TARGET_ARCH_DBC64)
     buffer.AddString(" dbc64");
 #endif
-  } else if (Snapshot::IsFull(kind)) {
-#if defined(ARCH_IS_32BIT)
-  buffer.AddString(" 32");
-#else
-  buffer.AddString(" 64");
-#endif
   }
 
   return buffer.Steal();
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index c9942da..34a8d33 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1325,10 +1325,9 @@
 
 DART_EXPORT void* Dart_IsolateData(Dart_Isolate isolate) {
   if (isolate == NULL) {
-    FATAL1("%s expects argument 'isolate' to be non-null.",  CURRENT_FUNC);
+    FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);
   }
   // TODO(16615): Validate isolate parameter.
-  NoSafepointScope no_safepoint_scope;
   Isolate* iso = reinterpret_cast<Isolate*>(isolate);
   return iso->init_callback_data();
 }
@@ -5808,6 +5807,71 @@
 }
 
 
+DART_EXPORT int64_t Dart_TimelineGetMicros() {
+  return OS::GetCurrentMonotonicMicros();
+}
+
+
+#if defined(PRODUCT)
+DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback(
+    const char* name,
+    Dart_ServiceRequestCallback callback,
+    void* user_data) {
+  return;
+}
+
+
+DART_EXPORT void Dart_RegisterRootServiceRequestCallback(
+    const char* name,
+    Dart_ServiceRequestCallback callback,
+    void* user_data) {
+  return;
+}
+
+
+DART_EXPORT Dart_Handle Dart_SetServiceStreamCallbacks(
+    Dart_ServiceStreamListenCallback listen_callback,
+    Dart_ServiceStreamCancelCallback cancel_callback) {
+  return Api::Success();
+}
+
+
+DART_EXPORT Dart_Handle Dart_ServiceSendDataEvent(const char* stream_id,
+                                                  const char* event_kind,
+                                                  const uint8_t* bytes,
+                                                  intptr_t bytes_length) {
+  return Api::Success();
+}
+
+
+DART_EXPORT void Dart_GlobalTimelineSetRecordedStreams(int64_t stream_mask) {
+  return;
+}
+
+
+DART_EXPORT void Dart_SetEmbedderTimelineCallbacks(
+    Dart_EmbedderTimelineStartRecording start_recording,
+    Dart_EmbedderTimelineStopRecording stop_recording) {
+  return;
+}
+
+
+DART_EXPORT bool Dart_GlobalTimelineGetTrace(Dart_StreamConsumer consumer,
+                                             void* user_data) {
+  return false;
+}
+
+
+DART_EXPORT void Dart_TimelineEvent(const char* label,
+                                    int64_t timestamp0,
+                                    int64_t timestamp1_or_async_id,
+                                    Dart_Timeline_Event_Type type,
+                                    intptr_t argument_count,
+                                    const char** argument_names,
+                                    const char** argument_values) {
+  return;
+}
+#else  // defined(PRODUCT)
 DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback(
     const char* name,
     Dart_ServiceRequestCallback callback,
@@ -5871,9 +5935,6 @@
                                                   const char* event_kind,
                                                   const uint8_t* bytes,
                                                   intptr_t bytes_length) {
-#if defined(PRODUCT)
-  return Api::Success();
-#else  // defined(PRODUCT)
   DARTSCOPE(Thread::Current());
   Isolate* I = T->isolate();
   if (stream_id == NULL) {
@@ -5892,12 +5953,6 @@
   Service::SendEmbedderEvent(I, stream_id, event_kind,
                              bytes, bytes_length);
   return Api::Success();
-#endif  // defined(PRODUCT)
-}
-
-
-DART_EXPORT int64_t Dart_TimelineGetMicros() {
-  return OS::GetCurrentMonotonicMicros();
 }
 
 
@@ -6125,6 +6180,7 @@
   }
   event->Complete();
 }
+#endif  // defined(PRODUCT)
 
 
 DART_EXPORT void Dart_SetThreadName(const char* name) {
diff --git a/runtime/vm/dart_api_message.cc b/runtime/vm/dart_api_message.cc
index 2d4e759..ed04af0 100644
--- a/runtime/vm/dart_api_message.cc
+++ b/runtime/vm/dart_api_message.cc
@@ -642,8 +642,6 @@
     }
     case kOneByteStringCid: {
       intptr_t len = ReadSmiValue();
-      intptr_t hash = ReadSmiValue();
-      USE(hash);
       uint8_t *latin1 =
           reinterpret_cast<uint8_t*>(allocator(len * sizeof(uint8_t)));
       intptr_t utf8_len = 0;
@@ -663,8 +661,6 @@
     }
     case kTwoByteStringCid: {
       intptr_t len = ReadSmiValue();
-      intptr_t hash = ReadSmiValue();
-      USE(hash);
       uint16_t *utf16 = reinterpret_cast<uint16_t*>(
           allocator(len * sizeof(uint16_t)));
       intptr_t utf8_len = 0;
@@ -1203,9 +1199,8 @@
       WriteIndexedObject(type == Utf8::kLatin1 ? kOneByteStringCid
                                                : kTwoByteStringCid);
       WriteTags(0);
-      // Write string length, hash and content
+      // Write string length and content.
       WriteSmi(len);
-      WriteSmi(0);  // TODO(sgjesse): Hash - not written.
       if (type == Utf8::kLatin1) {
         uint8_t* latin1_str =
             reinterpret_cast<uint8_t*>(::malloc(len * sizeof(uint8_t)));
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 64476a9..a52cf4a 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -827,7 +827,7 @@
   if (deopt_frame_.IsNull()) {
     return GetVariableValue(LocalVarAddress(fp(), slot_index));
   } else {
-    return deopt_frame_.At(deopt_frame_offset_ + slot_index);
+    return deopt_frame_.At(LocalVarIndex(deopt_frame_offset_, slot_index));
   }
 }
 
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index f31a897..ae38a71 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -147,6 +147,7 @@
   delete[] deferred_objects_;
   deferred_objects_ = NULL;
   deferred_objects_count_ = 0;
+#ifndef PRODUCT
   if (FLAG_support_timeline && (deopt_start_micros_ != 0)) {
     TimelineStream* compiler_stream = Timeline::GetCompilerStream();
     ASSERT(compiler_stream != NULL);
@@ -172,6 +173,7 @@
       }
     }
   }
+#endif  // !PRODUCT
 }
 
 
@@ -1045,6 +1047,10 @@
   Location::Kind stack_slot_kind) {
   if (loc.IsFpuRegister()) {
     return FpuRegisterSource(FpuRegisterSource::kRegister, loc.fpu_reg());
+#if defined(TARGET_ARCH_DBC)
+  } else if (loc.IsRegister()) {
+    return FpuRegisterSource(FpuRegisterSource::kRegister, loc.reg());
+#endif
   } else {
     ASSERT((stack_slot_kind == Location::kQuadStackSlot) ||
            (stack_slot_kind == Location::kDoubleStackSlot));
diff --git a/runtime/vm/deopt_instructions.h b/runtime/vm/deopt_instructions.h
index 79a2c50..09e01b4 100644
--- a/runtime/vm/deopt_instructions.h
+++ b/runtime/vm/deopt_instructions.h
@@ -86,8 +86,14 @@
     ASSERT(FlowGraphCompiler::SupportsUnboxedDoubles());
     ASSERT(fpu_registers_ != NULL);
     ASSERT(reg >= 0);
+#if !defined(TARGET_ARCH_DBC)
     ASSERT(reg < kNumberOfFpuRegisters);
     return *reinterpret_cast<double*>(&fpu_registers_[reg]);
+#else
+    // On DBC registers and stack slots are the same.
+    const intptr_t stack_index = num_args_ + kDartFrameFixedSize + reg;
+    return *reinterpret_cast<double*>(GetSourceFrameAddressAt(stack_index));
+#endif
   }
 
   simd128_value_t FpuRegisterValueAsSimd128(FpuRegister reg) const {
diff --git a/runtime/vm/disassembler.cc b/runtime/vm/disassembler.cc
index eef90c3..a735289 100644
--- a/runtime/vm/disassembler.cc
+++ b/runtime/vm/disassembler.cc
@@ -26,6 +26,7 @@
                                              intptr_t hex_size,
                                              char* human_buffer,
                                              intptr_t human_size,
+                                             Object* object,
                                              uword pc) {
   static const int kHexColumnWidth = 23;
   uint8_t* pc_ptr = reinterpret_cast<uint8_t*>(pc);
@@ -37,6 +38,9 @@
     }
   }
   THR_Print("%s", human_buffer);
+  if (object != NULL) {
+    THR_Print("   %s", object->ToCString());
+  }
   THR_Print("\n");
 }
 
@@ -54,6 +58,7 @@
                                                  intptr_t hex_size,
                                                  char* human_buffer,
                                                  intptr_t human_size,
+                                                 Object* object,
                                                  uword pc) {
   // Instructions are represented as four consecutive values in a JSON array.
   // The first is the address of the instruction, the second is the hex string,
@@ -63,9 +68,8 @@
   jsarr_.AddValue(hex_buffer);
   jsarr_.AddValue(human_buffer);
 
-  Object& object = Object::Handle();
-  if (DecodeLoadObjectFromPoolOrThread(pc, code, &object)) {
-    jsarr_.AddValue(object);
+  if (object != NULL) {
+    jsarr_.AddValue(*object);
   } else {
     jsarr_.AddValueNull();  // Not a reference to null.
   }
@@ -97,33 +101,6 @@
 }
 
 
-class FindAddrVisitor : public FindObjectVisitor {
- public:
-  explicit FindAddrVisitor(uword addr) : addr_(addr) { }
-  virtual ~FindAddrVisitor() { }
-
-  virtual uword filter_addr() const { return addr_; }
-
-  // Check if object matches find condition.
-  virtual bool FindObject(RawObject* obj) const {
-    return obj == reinterpret_cast<RawObject*>(addr_);
-  }
-
- private:
-  const uword addr_;
-
-  DISALLOW_COPY_AND_ASSIGN(FindAddrVisitor);
-};
-
-
-bool Disassembler::CanFindOldObject(uword addr) {
-  FindAddrVisitor visitor(addr);
-  NoSafepointScope no_safepoint;
-  return Dart::vm_isolate()->heap()->FindOldObject(&visitor) != Object::null()
-      || Isolate::Current()->heap()->FindOldObject(&visitor) != Object::null();
-}
-
-
 void Disassembler::Disassemble(uword start,
                                uword end,
                                DisassemblyFormatter* formatter,
@@ -168,16 +145,18 @@
       }
     }
     int instruction_length;
+    Object* object;
     DecodeInstruction(hex_buffer,
                       sizeof(hex_buffer),
                       human_buffer,
                       sizeof(human_buffer),
-                      &instruction_length, pc);
+                      &instruction_length, code, &object, pc);
     formatter->ConsumeInstruction(code,
                                   hex_buffer,
                                   sizeof(hex_buffer),
                                   human_buffer,
                                   sizeof(human_buffer),
+                                  object,
                                   pc);
     pc += instruction_length;
   }
@@ -250,37 +229,39 @@
   }
   THR_Print("}\n");
 
-  THR_Print("Variable Descriptors for function '%s' {\n",
-            function_fullname);
-  const LocalVarDescriptors& var_descriptors =
-      LocalVarDescriptors::Handle(code.GetLocalVarDescriptors());
-  intptr_t var_desc_length =
-      var_descriptors.IsNull() ? 0 : var_descriptors.Length();
-  String& var_name = String::Handle();
-  for (intptr_t i = 0; i < var_desc_length; i++) {
-    var_name = var_descriptors.GetName(i);
-    RawLocalVarDescriptors::VarInfo var_info;
-    var_descriptors.GetInfo(i, &var_info);
-    const int8_t kind = var_info.kind();
-    if (kind == RawLocalVarDescriptors::kSavedCurrentContext) {
-      THR_Print("  saved current CTX reg offset %d\n", var_info.index());
-    } else {
-      if (kind == RawLocalVarDescriptors::kContextLevel) {
-        THR_Print("  context level %d scope %d", var_info.index(),
-            var_info.scope_id);
-      } else if (kind == RawLocalVarDescriptors::kStackVar) {
-        THR_Print("  stack var '%s' offset %d",
-          var_name.ToCString(), var_info.index());
+  if (FLAG_print_variable_descriptors) {
+    THR_Print("Variable Descriptors for function '%s' {\n",
+              function_fullname);
+    const LocalVarDescriptors& var_descriptors =
+        LocalVarDescriptors::Handle(code.GetLocalVarDescriptors());
+    intptr_t var_desc_length =
+        var_descriptors.IsNull() ? 0 : var_descriptors.Length();
+    String& var_name = String::Handle();
+    for (intptr_t i = 0; i < var_desc_length; i++) {
+      var_name = var_descriptors.GetName(i);
+      RawLocalVarDescriptors::VarInfo var_info;
+      var_descriptors.GetInfo(i, &var_info);
+      const int8_t kind = var_info.kind();
+      if (kind == RawLocalVarDescriptors::kSavedCurrentContext) {
+        THR_Print("  saved current CTX reg offset %d\n", var_info.index());
       } else {
-        ASSERT(kind == RawLocalVarDescriptors::kContextVar);
-        THR_Print("  context var '%s' level %d offset %d",
-            var_name.ToCString(), var_info.scope_id, var_info.index());
+        if (kind == RawLocalVarDescriptors::kContextLevel) {
+          THR_Print("  context level %d scope %d", var_info.index(),
+              var_info.scope_id);
+        } else if (kind == RawLocalVarDescriptors::kStackVar) {
+          THR_Print("  stack var '%s' offset %d",
+            var_name.ToCString(), var_info.index());
+        } else {
+          ASSERT(kind == RawLocalVarDescriptors::kContextVar);
+          THR_Print("  context var '%s' level %d offset %d",
+              var_name.ToCString(), var_info.scope_id, var_info.index());
+        }
+        THR_Print(" (valid %s-%s)\n", var_info.begin_pos.ToCString(),
+                                      var_info.end_pos.ToCString());
       }
-      THR_Print(" (valid %s-%s)\n", var_info.begin_pos.ToCString(),
-                                    var_info.end_pos.ToCString());
     }
+    THR_Print("}\n");
   }
-  THR_Print("}\n");
 
   THR_Print("Exception Handlers for function '%s' {\n", function_fullname);
   const ExceptionHandlers& handlers =
diff --git a/runtime/vm/disassembler.h b/runtime/vm/disassembler.h
index fc3649a..7adb12a 100644
--- a/runtime/vm/disassembler.h
+++ b/runtime/vm/disassembler.h
@@ -29,6 +29,7 @@
                                   intptr_t hex_size,
                                   char* human_buffer,
                                   intptr_t human_size,
+                                  Object* object,
                                   uword pc) = 0;
 
   // Print a formatted message.
@@ -48,6 +49,7 @@
                                   intptr_t hex_size,
                                   char* human_buffer,
                                   intptr_t human_size,
+                                  Object* object,
                                   uword pc);
 
   virtual void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
@@ -70,6 +72,7 @@
                                   intptr_t hex_size,
                                   char* human_buffer,
                                   intptr_t human_size,
+                                  Object* object,
                                   uword pc);
 
   virtual void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
@@ -112,29 +115,14 @@
     Disassemble(start, end, &stdout_formatter);
   }
 
-  // Disassemble instructions in a memory region.
-  static void DisassembleMemoryRegion(const MemoryRegion& instructions,
-                                      DisassemblyFormatter* formatter) {
-    uword start = instructions.start();
-    uword end = instructions.end();
-    Disassemble(start, end, formatter);
-  }
-
-  static void DisassembleMemoryRegion(const MemoryRegion& instructions) {
-    uword start = instructions.start();
-    uword end = instructions.end();
-    Disassemble(start, end);
-  }
-
   // Decodes one instruction.
   // Writes a hexadecimal representation into the hex_buffer and a
   // human-readable representation into the human_buffer.
   // Writes the length of the decoded instruction in bytes in out_instr_len.
   static void DecodeInstruction(char* hex_buffer, intptr_t hex_size,
                                 char* human_buffer, intptr_t human_size,
-                                int* out_instr_len, uword pc);
-
-  static bool CanFindOldObject(uword addr);
+                                int* out_instr_len, const Code& code,
+                                Object** object, uword pc);
 
   static void DisassembleCode(const Function& function, bool optimized);
   static void DisassembleCodeUnoptimized(
diff --git a/runtime/vm/disassembler_arm.cc b/runtime/vm/disassembler_arm.cc
index 2b0c103..67c0afb 100644
--- a/runtime/vm/disassembler_arm.cc
+++ b/runtime/vm/disassembler_arm.cc
@@ -6,9 +6,9 @@
 
 #include "vm/globals.h"  // Needed here to get TARGET_ARCH_ARM.
 #if defined(TARGET_ARCH_ARM)
-
 #include "platform/assert.h"
 #include "vm/cpu.h"
+#include "vm/instructions.h"
 
 namespace dart {
 
@@ -1534,7 +1534,8 @@
 
 void Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size,
                                      char* human_buffer, intptr_t human_size,
-                                     int* out_instr_size, uword pc) {
+                                     int* out_instr_size, const Code& code,
+                                     Object** object, uword pc) {
   ARMDecoder decoder(human_buffer, human_size);
   decoder.InstructionDecode(pc);
   int32_t instruction_bits = Instr::At(pc)->InstructionBits();
@@ -1542,6 +1543,14 @@
   if (out_instr_size) {
     *out_instr_size = Instr::kInstrSize;
   }
+
+  *object = NULL;
+  if (!code.IsNull()) {
+    *object = &Object::Handle();
+    if (!DecodeLoadObjectFromPoolOrThread(pc, code, *object)) {
+      *object = NULL;
+    }
+  }
 }
 
 #endif  // !PRODUCT
diff --git a/runtime/vm/disassembler_arm64.cc b/runtime/vm/disassembler_arm64.cc
index a238641..dd7d00c 100644
--- a/runtime/vm/disassembler_arm64.cc
+++ b/runtime/vm/disassembler_arm64.cc
@@ -7,6 +7,7 @@
 #include "vm/globals.h"  // Needed here to get TARGET_ARCH_ARM64.
 #if defined(TARGET_ARCH_ARM64)
 #include "platform/assert.h"
+#include "vm/instructions.h"
 
 namespace dart {
 
@@ -1488,7 +1489,8 @@
 
 void Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size,
                                      char* human_buffer, intptr_t human_size,
-                                     int* out_instr_size, uword pc) {
+                                     int* out_instr_size, const Code& code,
+                                     Object** object, uword pc) {
   ARM64Decoder decoder(human_buffer, human_size);
   decoder.InstructionDecode(pc);
   int32_t instruction_bits = Instr::At(pc)->InstructionBits();
@@ -1496,6 +1498,14 @@
   if (out_instr_size) {
     *out_instr_size = Instr::kInstrSize;
   }
+
+  *object = NULL;
+  if (!code.IsNull()) {
+    *object = &Object::Handle();
+    if (!DecodeLoadObjectFromPoolOrThread(pc, code, *object)) {
+      *object = NULL;
+    }
+  }
 }
 
 #endif  // !PRODUCT
diff --git a/runtime/vm/disassembler_dbc.cc b/runtime/vm/disassembler_dbc.cc
index 5c8b3a0..a2095a0 100644
--- a/runtime/vm/disassembler_dbc.cc
+++ b/runtime/vm/disassembler_dbc.cc
@@ -10,6 +10,7 @@
 #include "platform/assert.h"
 #include "vm/constants_dbc.h"
 #include "vm/cpu.h"
+#include "vm/instructions.h"
 
 namespace dart {
 
@@ -214,6 +215,8 @@
                                      char* human_buffer,
                                      intptr_t human_size,
                                      int* out_instr_size,
+                                     const Code& code,
+                                     Object** object,
                                      uword pc) {
   const uint32_t instr = *reinterpret_cast<uint32_t*>(pc);
   const uint8_t opcode = instr & 0xFF;
@@ -229,6 +232,14 @@
   if (out_instr_size) {
     *out_instr_size = sizeof(uint32_t);
   }
+
+  *object = NULL;
+  if (!code.IsNull()) {
+    *object = &Object::Handle();
+    if (!DecodeLoadObjectFromPoolOrThread(pc, code, *object)) {
+      *object = NULL;
+    }
+  }
 }
 
 
diff --git a/runtime/vm/disassembler_ia32.cc b/runtime/vm/disassembler_ia32.cc
index 31e4fdba..8f3d7f6 100644
--- a/runtime/vm/disassembler_ia32.cc
+++ b/runtime/vm/disassembler_ia32.cc
@@ -465,69 +465,17 @@
 }
 
 
-static const char* ObjectToCStringNoGC(const Object& obj) {
-  if (obj.IsSmi() ||
-      obj.IsMint() ||
-      obj.IsDouble() ||
-      obj.IsString() ||
-      obj.IsNull() ||
-      obj.IsBool() ||
-      obj.IsClass() ||
-      obj.IsFunction() ||
-      obj.IsICData() ||
-      obj.IsField() ||
-      obj.IsCode()) {
-    return obj.ToCString();
-  }
-
-  const Class& clazz = Class::Handle(obj.clazz());
-  const char* full_class_name = clazz.ToCString();
-  return OS::SCreate(Thread::Current()->zone(),
-      "instance of %s", full_class_name);
-}
-
-
 void X86Decoder::PrintAddress(uword addr) {
   char addr_buffer[32];
   OS::SNPrint(addr_buffer, sizeof(addr_buffer), "%#" Px "", addr);
   Print(addr_buffer);
-  // Try to print as heap object or stub name
-  if (((addr & kSmiTagMask) == kHeapObjectTag) &&
-      reinterpret_cast<RawObject*>(addr)->IsWellFormed() &&
-      reinterpret_cast<RawObject*>(addr)->IsOldObject() &&
-      !Isolate::Current()->heap()->CodeContains(addr) &&
-      !Dart::vm_isolate()->heap()->CodeContains(addr) &&
-      Disassembler::CanFindOldObject(addr)) {
-    NoSafepointScope no_safepoint;
-    const Object& obj = Object::Handle(reinterpret_cast<RawObject*>(addr));
-    if (obj.IsArray()) {
-      const Array& arr = Array::Cast(obj);
-      intptr_t len = arr.Length();
-      if (len > 5) len = 5;  // Print a max of 5 elements.
-      Print("  Array[");
-      int i = 0;
-      Object& element = Object::Handle();
-      while (i < len) {
-        element = arr.At(i);
-        if (i > 0) Print(", ");
-        Print(ObjectToCStringNoGC(element));
-        i++;
-      }
-      if (i < arr.Length()) Print(", ...");
-      Print("]");
-      return;
-    }
-    Print("  '");
-    Print(ObjectToCStringNoGC(obj));
-    Print("'");
-  } else {
-    // 'addr' is not an object, but probably a code address.
-    const char* name_of_stub = StubCode::NameOfStub(addr);
-    if (name_of_stub != NULL) {
-      Print("  [stub: ");
-      Print(name_of_stub);
-      Print("]");
-    }
+
+  // Try to print as  stub name.
+  const char* name_of_stub = StubCode::NameOfStub(addr);
+  if (name_of_stub != NULL) {
+    Print("  [stub: ");
+    Print(name_of_stub);
+    Print("]");
   }
 }
 
@@ -1845,7 +1793,8 @@
 
 void Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size,
                                      char* human_buffer, intptr_t human_size,
-                                     int* out_instr_len, uword pc) {
+                                     int* out_instr_len, const Code& code,
+                                     Object** object, uword pc) {
   ASSERT(hex_size > 0);
   ASSERT(human_size > 0);
   X86Decoder decoder(human_buffer, human_size);
@@ -1862,6 +1811,18 @@
   if (out_instr_len) {
     *out_instr_len = instruction_length;
   }
+
+  *object = NULL;
+  if (!code.IsNull() && code.is_alive()) {
+    intptr_t offsets_length = code.pointer_offsets_length();
+    for (intptr_t i = 0; i < offsets_length; i++) {
+      uword addr = code.GetPointerOffsetAt(i) + code.EntryPoint();
+      if ((pc <= addr) && (addr < (pc + instruction_length))) {
+        *object = &Object::Handle(*reinterpret_cast<RawObject**>(addr));
+        break;
+      }
+    }
+  }
 }
 
 #endif  // !PRODUCT
diff --git a/runtime/vm/disassembler_mips.cc b/runtime/vm/disassembler_mips.cc
index 22fe462..78831a7 100644
--- a/runtime/vm/disassembler_mips.cc
+++ b/runtime/vm/disassembler_mips.cc
@@ -7,6 +7,7 @@
 #include "vm/globals.h"  // Needed here to get TARGET_ARCH_MIPS.
 #if defined(TARGET_ARCH_MIPS)
 #include "platform/assert.h"
+#include "vm/instructions.h"
 
 namespace dart {
 
@@ -778,7 +779,8 @@
 
 void Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size,
                                      char* human_buffer, intptr_t human_size,
-                                     int* out_instr_len, uword pc) {
+                                     int* out_instr_len, const Code& code,
+                                     Object** object, uword pc) {
   MIPSDecoder decoder(human_buffer, human_size);
   Instr* instr = Instr::At(pc);
   decoder.InstructionDecode(instr);
@@ -786,6 +788,14 @@
   if (out_instr_len) {
     *out_instr_len = Instr::kInstrSize;
   }
+
+  *object = NULL;
+  if (!code.IsNull()) {
+    *object = &Object::Handle();
+    if (!DecodeLoadObjectFromPoolOrThread(pc, code, *object)) {
+      *object = NULL;
+    }
+  }
 }
 
 #endif  // !PRODUCT
diff --git a/runtime/vm/disassembler_x64.cc b/runtime/vm/disassembler_x64.cc
index 60118f1..f389415 100644
--- a/runtime/vm/disassembler_x64.cc
+++ b/runtime/vm/disassembler_x64.cc
@@ -9,6 +9,7 @@
 #include "platform/utils.h"
 #include "vm/allocation.h"
 #include "vm/heap.h"
+#include "vm/instructions.h"
 #include "vm/os.h"
 #include "vm/stack_frame.h"
 #include "vm/stub_code.h"
@@ -785,65 +786,9 @@
 }
 
 
-static const char* ObjectToCStringNoGC(const Object& obj) {
-  if (obj.IsSmi() ||
-      obj.IsMint() ||
-      obj.IsDouble() ||
-      obj.IsString() ||
-      obj.IsNull() ||
-      obj.IsBool() ||
-      obj.IsClass() ||
-      obj.IsFunction() ||
-      obj.IsICData() ||
-      obj.IsField() ||
-      obj.IsCode()) {
-    return obj.ToCString();
-  }
-
-  const Class& clazz = Class::Handle(obj.clazz());
-  const char* full_class_name = clazz.ToCString();
-  return OS::SCreate(Thread::Current()->zone(),
-      "instance of %s", full_class_name);
-}
-
-
 void DisassemblerX64::PrintAddress(uint8_t* addr_byte_ptr) {
   uword addr = reinterpret_cast<uword>(addr_byte_ptr);
   Print("%#" Px "", addr);
-  // Try to print as heap object or stub name
-  if (((addr & kSmiTagMask) == kHeapObjectTag) &&
-      reinterpret_cast<RawObject*>(addr)->IsWellFormed() &&
-      reinterpret_cast<RawObject*>(addr)->IsOldObject() &&
-      !Dart::vm_isolate()->heap()->CodeContains(addr) &&
-      !Isolate::Current()->heap()->CodeContains(addr) &&
-      Disassembler::CanFindOldObject(addr)) {
-    NoSafepointScope no_safepoint;
-    const Object& obj = Object::Handle(reinterpret_cast<RawObject*>(addr));
-    if (obj.IsArray()) {
-      const Array& arr = Array::Cast(obj);
-      intptr_t len = arr.Length();
-      if (len > 5) len = 5;  // Print a max of 5 elements.
-      Print("  Array[");
-      int i = 0;
-      Object& element = Object::Handle();
-      while (i < len) {
-        element = arr.At(i);
-        if (i > 0) Print(", ");
-        Print("%s", ObjectToCStringNoGC(element));
-        i++;
-      }
-      if (i < arr.Length()) Print(", ...");
-      Print("]");
-      return;
-    }
-    Print("  '%s'", ObjectToCStringNoGC(obj));
-  } else {
-    // 'addr' is not an object, but probably a code address.
-    const char* name_of_stub = StubCode::NameOfStub(addr);
-    if (name_of_stub != NULL) {
-      Print("  [stub: %s]", name_of_stub);
-    }
-  }
 }
 
 
@@ -1935,7 +1880,8 @@
 
 void Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size,
                                      char* human_buffer, intptr_t human_size,
-                                     int* out_instr_len, uword pc) {
+                                     int* out_instr_len, const Code& code,
+                                     Object** object, uword pc) {
   ASSERT(hex_size > 0);
   ASSERT(human_size > 0);
   DisassemblerX64 decoder(human_buffer, human_size);
@@ -1952,6 +1898,14 @@
   if (out_instr_len) {
     *out_instr_len = instruction_length;
   }
+
+  *object = NULL;
+  if (!code.IsNull()) {
+    *object = &Object::Handle();
+    if (!DecodeLoadObjectFromPoolOrThread(pc, code, *object)) {
+      *object = NULL;
+    }
+  }
 }
 
 #endif  // !PRODUCT
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index c22e43c..7daddd9 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -12,6 +12,12 @@
 #define USING_DBC false
 #endif
 
+#if defined(TARGET_OS_FUCHSIA)
+#define USING_FUCHSIA true
+#else
+#define USING_FUCHSIA false
+#endif
+
 // Don't use USING_MULTICORE outside of this file.
 #if defined(ARCH_IS_MULTI_CORE)
 #define USING_MULTICORE true
@@ -35,8 +41,6 @@
 //   D(name, type, default_value, comment)
 //   C(name, precompiled_value, product_value, type, default_value, comment)
 #define FLAG_LIST(P, R, D, C)                                                  \
-P(always_megamorphic_calls, bool, false,                                       \
-  "Instance call always as megamorphic.")                                      \
 P(background_compilation, bool, USING_MULTICORE,                               \
   "Run optimizing compilation in background")                                  \
 R(background_compilation_stop_alot, false, bool, false,                        \
@@ -90,8 +94,6 @@
   "Ratio of getter/setter usage used for double field unboxing heuristics")    \
 P(guess_icdata_cid, bool, true,                                                \
   "Artificially create type feedback for arithmetic etc. operations")          \
-P(ic_range_profiling, bool, !USING_DBC,                                        \
-  "Generate special IC stubs collecting range information ")                   \
 P(interpret_irregexp, bool, USING_DBC,                                         \
   "Use irregexp bytecode interpreter")                                         \
 P(lazy_dispatchers, bool, true,                                                \
@@ -108,7 +110,7 @@
 P(max_polymorphic_checks, int, 4,                                              \
   "Maximum number of polymorphic check, otherwise it is megamorphic.")         \
 P(max_equality_polymorphic_checks, int, 32,                                    \
-    "Maximum number of polymorphic checks in equality operator,")              \
+  "Maximum number of polymorphic checks in equality operator,")                \
 P(merge_sin_cos, bool, false,                                                  \
   "Merge sin/cos into sincos")                                                 \
 P(new_gen_ext_limit, int, 64,                                                  \
@@ -138,7 +140,9 @@
   "Print live ranges after allocation.")                                       \
 C(print_stop_message, false, false, bool, false,                               \
   "Print stop message.")                                                       \
-R(profiler, false, bool, !USING_DBC,                                           \
+D(print_variable_descriptors, bool, false,                                     \
+  "Print variable descriptors in disassembly.")                                \
+R(profiler, false, bool, !USING_DBC && !USING_FUCHSIA,                         \
   "Enable the profiler.")                                                      \
 P(reorder_basic_blocks, bool, true,                                            \
   "Reorder basic blocks")                                                      \
@@ -146,13 +150,13 @@
   "Support the AST printer.")                                                  \
 R(support_compiler_stats, false, bool, true,                                   \
   "Support compiler stats.")                                                   \
-R(support_debugger, false, bool, true,                                         \
+C(support_debugger, false, false, bool, true,                                  \
   "Support the debugger.")                                                     \
 R(support_disassembler, false, bool, true,                                     \
   "Support the disassembler.")                                                 \
 R(support_il_printer, false, bool, true,                                       \
   "Support the IL printer.")                                                   \
-R(support_reload, false, bool, true,                                           \
+C(support_reload, false, false, bool, true,                                    \
   "Support isolate reload.")                                                   \
 R(support_service, false, bool, true,                                          \
   "Support the service protocol.")                                             \
@@ -184,8 +188,6 @@
   "Use field guards and track field types")                                    \
 C(use_osr, false, true, bool, true,                                            \
   "Use OSR")                                                                   \
-R(verbose_dev, false, bool, false,                                             \
-  "Enables verbose messages during development.")                              \
 P(verbose_gc, bool, false,                                                     \
   "Enables verbose GC.")                                                       \
 P(verbose_gc_hdr, int, 40,                                                     \
diff --git a/runtime/vm/flags.cc b/runtime/vm/flags.cc
index cb76c91..8c5a9d8 100644
--- a/runtime/vm/flags.cc
+++ b/runtime/vm/flags.cc
@@ -487,6 +487,7 @@
 }
 
 
+#ifndef PRODUCT
 void Flags::PrintFlagToJSONArray(JSONArray* jsarr, const Flag* flag) {
   if (!FLAG_support_service) {
     return;
@@ -542,5 +543,6 @@
     PrintFlagToJSONArray(&jsarr, flags_[i]);
   }
 }
+#endif  // !PRODUCT
 
 }  // namespace dart
diff --git a/runtime/vm/flags.h b/runtime/vm/flags.h
index 81f594e..b30299c 100644
--- a/runtime/vm/flags.h
+++ b/runtime/vm/flags.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2012, 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.
 
@@ -67,7 +67,9 @@
 
   static bool Initialized() { return initialized_; }
 
+#ifndef PRODUCT
   static void PrintJSON(JSONStream* js);
+#endif  // !PRODUCT
 
   static bool SetFlag(const char* name,
                       const char* value,
@@ -90,7 +92,9 @@
 
   static void PrintFlags();
 
+#ifndef PRODUCT
   static void PrintFlagToJSONArray(JSONArray* jsarr, const Flag* flag);
+#endif  // !PRODUCT
 
   // Testing needs direct access to private methods.
   friend void Dart_TestParseFlags();
diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc
index 009e500..558e6f7 100644
--- a/runtime/vm/flow_graph_allocator.cc
+++ b/runtime/vm/flow_graph_allocator.cc
@@ -749,15 +749,22 @@
 
 
 static Location::Kind RegisterKindForResult(Instruction* instr) {
-  if ((instr->representation() == kUnboxedDouble) ||
-      (instr->representation() == kUnboxedFloat32x4) ||
-      (instr->representation() == kUnboxedInt32x4) ||
-      (instr->representation() == kUnboxedFloat64x2) ||
-      (instr->representation() == kPairOfUnboxedDouble)) {
+  const Representation rep = instr->representation();
+#if !defined(TARGET_ARCH_DBC)
+  if ((rep == kUnboxedDouble) || (rep == kUnboxedFloat32x4) ||
+      (rep == kUnboxedInt32x4) || (rep == kUnboxedFloat64x2) ||
+      (rep == kPairOfUnboxedDouble)) {
     return Location::kFpuRegister;
   } else {
     return Location::kRegister;
   }
+#else
+  // DBC supports only unboxed doubles and does not have distinguished FPU
+  // registers.
+  ASSERT((rep != kUnboxedFloat32x4) && (rep != kUnboxedInt32x4) &&
+         (rep != kUnboxedFloat64x2) && (rep != kPairOfUnboxedDouble));
+  return Location::kRegister;
+#endif
 }
 
 
@@ -3055,6 +3062,11 @@
                        unallocated_xmm_,
                        fpu_regs_,
                        blocked_fpu_registers_);
+#if defined(TARGET_ARCH_DBC)
+  // For DBC all registers should have been allocated in the first pass.
+  ASSERT(unallocated_.is_empty());
+#endif
+
   AllocateUnallocatedRanges();
 #if defined(TARGET_ARCH_DBC)
   const intptr_t last_used_fpu_register = last_used_register_;
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index aeea819..0bcf854 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -899,10 +899,13 @@
           context, Context::parent_offset(), Type::ZoneHandle(Z, Type::null()),
           token_pos));
     }
-    return new(Z) LoadFieldInstr(context,
-                                 Context::variable_offset(local.index()),
-                                 local.type(),
-                                 token_pos);
+    LoadFieldInstr* load = new(Z) LoadFieldInstr(
+        context,
+        Context::variable_offset(local.index()),
+        local.type(),
+        token_pos);
+    load->set_is_immutable(local.is_final());
+    return load;
   } else {
     return new(Z) LoadLocalInstr(local, token_pos);
   }
@@ -1543,6 +1546,22 @@
   return Bind(BuildAssertAssignable(token_pos, value, dst_type, dst_name));
 }
 
+static bool simpleInstanceOfType(const AbstractType& type) {
+  // Bail if the type is still uninstantiated at compile time.
+  if (!type.IsInstantiated()) return false;
+
+  // Bail if the type is a function or a Dart Function type.
+  if (type.IsFunctionType() || type.IsDartFunctionType()) return false;
+
+  ASSERT(type.HasResolvedTypeClass());
+  const Class& type_class = Class::Handle(type.type_class());
+  // Bail if the type has any type parameters.
+  if (type_class.IsGeneric()) return false;
+
+  // Finally a simple class for instance of checking.
+  return true;
+}
+
 
 void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) {
   ASSERT(Token::IsTypeTestOperator(node->kind()));
@@ -1599,7 +1618,32 @@
     return;
   }
 
+  // We now know type is a real class (!num, !int, !smi, !string)
+  // and the type check could NOT be removed at compile time.
   PushArgumentInstr* push_left = PushArgument(for_left_value.value());
+  if (simpleInstanceOfType(type)) {
+    ASSERT(!node->right()->AsTypeNode()->type().IsNull());
+    ZoneGrowableArray<PushArgumentInstr*>* arguments =
+        new(Z) ZoneGrowableArray<PushArgumentInstr*>(2);
+    arguments->Add(push_left);
+    Value* type_const = Bind(new(Z) ConstantInstr(type));
+    arguments->Add(PushArgument(type_const));
+    const intptr_t kNumArgsChecked = 2;
+    Definition* result = new(Z) InstanceCallInstr(
+        node->token_pos(),
+        Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()),
+        node->kind(),
+        arguments,
+        Object::null_array(),  // No argument names.
+        kNumArgsChecked,
+        owner()->ic_data_array());
+    if (negate_result) {
+      result = new(Z) BooleanNegateInstr(Bind(result));
+    }
+    ReturnDefinition(result);
+    return;
+  }
+
   PushArgumentInstr* push_type_args = NULL;
   if (type.IsInstantiated()) {
     push_type_args = PushArgument(BuildNullValue(node->token_pos()));
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 13159ba..b98a3fc 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -43,7 +43,6 @@
 DEFINE_FLAG(bool, source_lines, false, "Emit source line as assembly comment.");
 DEFINE_FLAG(bool, trace_inlining_intervals, false,
     "Inlining interval diagnostics");
-DEFINE_FLAG(bool, use_megamorphic_stub, true, "Out of line megamorphic lookup");
 
 DECLARE_FLAG(bool, code_comments);
 DECLARE_FLAG(charp, deoptimize_filter);
@@ -85,9 +84,7 @@
     FLAG_inlining_constant_arguments_min_size_threshold = 30;
 
     FLAG_background_compilation = false;
-    FLAG_always_megamorphic_calls = true;
     FLAG_fields_may_be_reset = true;
-    FLAG_ic_range_profiling = false;
     FLAG_interpret_irregexp = true;
     FLAG_lazy_dispatchers = false;
     FLAG_link_natives_lazily = true;
@@ -356,7 +353,7 @@
 bool FlowGraphCompiler::ForceSlowPathForStackOverflow() const {
   if ((FLAG_stacktrace_every > 0) ||
       (FLAG_deoptimize_every > 0) ||
-      (FLAG_reload_every > 0)) {
+      (isolate()->reload_every_n_stack_overflow_checks() > 0)) {
     return true;
   }
   if (FLAG_stacktrace_filter != NULL &&
@@ -1198,12 +1195,6 @@
                                deopt_id, token_pos, locs);
     return;
   }
-  if (FLAG_always_megamorphic_calls) {
-    EmitMegamorphicInstanceCall(ic_data_in, argument_count,
-                                deopt_id, token_pos, locs,
-                                CatchClauseNode::kInvalidTryIndex);
-    return;
-  }
   ASSERT(!ic_data.IsNull());
   if (is_optimizing() && (ic_data_in.NumberOfUsedChecks() == 0)) {
     // Emit IC call that will count and thus may need reoptimization at
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index 0a30dc9..7541f1b 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -199,7 +199,6 @@
   Label* exit_label() { return &exit_label_; }
 
   void GenerateCode(FlowGraphCompiler* compiler) {
-    ASSERT(exit_label_.IsBound());
     EmitNativeCode(compiler);
     ASSERT(entry_label_.IsBound());
   }
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 4162943..8d8626c 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -27,7 +27,6 @@
 DEFINE_FLAG(bool, unbox_mints, true, "Optimize 64-bit integer arithmetic.");
 DEFINE_FLAG(bool, unbox_doubles, true, "Optimize double arithmetic.");
 DECLARE_FLAG(bool, enable_simd_inline);
-DECLARE_FLAG(bool, use_megamorphic_stub);
 
 
 void MegamorphicSlowPath::EmitNativeCode(FlowGraphCompiler* compiler) {
@@ -1056,13 +1055,8 @@
   // No such checking code is generated if only fixed parameters are declared,
   // unless we are in debug mode or unless we are compiling a closure.
   if (num_copied_params == 0) {
-#ifdef DEBUG
-    ASSERT(!parsed_function().function().HasOptionalParameters());
-    const bool check_arguments = !flow_graph().IsCompiledForOsr();
-#else
     const bool check_arguments =
         function.IsClosureFunction() && !flow_graph().IsCompiledForOsr();
-#endif
     if (check_arguments) {
       __ Comment("Check argument count");
       // Check that exactly num_fixed arguments are passed in.
@@ -1075,14 +1069,10 @@
       __ cmp(R0, Operand(R1));
       __ b(&correct_num_arguments, EQ);
       __ Bind(&wrong_num_arguments);
-      if (function.IsClosureFunction()) {
-        ASSERT(assembler()->constant_pool_allowed());
-        __ LeaveDartFrame(kKeepCalleePP);  // Arguments are still on the stack.
-        __ Branch(*StubCode::CallClosureNoSuchMethod_entry());
-        // The noSuchMethod call may return to the caller, but not here.
-      } else {
-        __ Stop("Wrong number of arguments");
-      }
+      ASSERT(assembler()->constant_pool_allowed());
+      __ LeaveDartFrame(kKeepCalleePP);  // Arguments are still on the stack.
+      __ Branch(*StubCode::CallClosureNoSuchMethod_entry());
+      // The noSuchMethod call may return to the caller, but not here.
       __ Bind(&correct_num_arguments);
     }
   } else if (!flow_graph().IsCompiledForOsr()) {
@@ -1342,11 +1332,8 @@
     __ Comment("Slow case: megamorphic call");
   }
   __ LoadObject(R9, cache);
-  if (FLAG_use_megamorphic_stub) {
-    __ BranchLink(*StubCode::MegamorphicLookup_entry());
-  } else {
-    StubCode::EmitMegamorphicLookup(assembler());
-  }
+  __ ldr(LR, Address(THR, Thread::megamorphic_lookup_entry_point_offset()));
+  __ blx(LR);
   __ blx(R1);
 
   __ Bind(&done);
@@ -1432,7 +1419,12 @@
     intptr_t deopt_id,
     TokenPosition token_pos,
     LocationSummary* locs) {
-  __ LoadObject(R4, arguments_descriptor);
+  ASSERT(!function.IsClosureFunction());
+  if (function.HasOptionalParameters()) {
+    __ LoadObject(R4, arguments_descriptor);
+  } else {
+    __ LoadImmediate(R4, 0);  // GC safe smi zero because of stub.
+  }
   // Do not use the code from the function, but let the code be patched so that
   // we can record the outgoing edges to other code.
   GenerateStaticDartCall(deopt_id,
diff --git a/runtime/vm/flow_graph_compiler_arm64.cc b/runtime/vm/flow_graph_compiler_arm64.cc
index d0c066e..178482a 100644
--- a/runtime/vm/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/flow_graph_compiler_arm64.cc
@@ -25,7 +25,6 @@
 
 DEFINE_FLAG(bool, trap_on_deoptimization, false, "Trap on deoptimization.");
 DECLARE_FLAG(bool, enable_simd_inline);
-DECLARE_FLAG(bool, use_megamorphic_stub);
 
 
 void MegamorphicSlowPath::EmitNativeCode(FlowGraphCompiler* compiler) {
@@ -1051,13 +1050,8 @@
   // No such checking code is generated if only fixed parameters are declared,
   // unless we are in debug mode or unless we are compiling a closure.
   if (num_copied_params == 0) {
-#ifdef DEBUG
-    ASSERT(!parsed_function().function().HasOptionalParameters());
-    const bool check_arguments = !flow_graph().IsCompiledForOsr();
-#else
     const bool check_arguments =
         function.IsClosureFunction() && !flow_graph().IsCompiledForOsr();
-#endif
     if (check_arguments) {
       __ Comment("Check argument count");
       // Check that exactly num_fixed arguments are passed in.
@@ -1070,13 +1064,9 @@
       __ CompareRegisters(R0, R1);
       __ b(&correct_num_arguments, EQ);
       __ Bind(&wrong_num_arguments);
-      if (function.IsClosureFunction()) {
-        __ LeaveDartFrame(kKeepCalleePP);  // Arguments are still on the stack.
-        __ BranchPatchable(*StubCode::CallClosureNoSuchMethod_entry());
-        // The noSuchMethod call may return to the caller, but not here.
-      } else {
-        __ Stop("Wrong number of arguments");
-      }
+      __ LeaveDartFrame(kKeepCalleePP);  // Arguments are still on the stack.
+      __ BranchPatchable(*StubCode::CallClosureNoSuchMethod_entry());
+      // The noSuchMethod call may return to the caller, but not here.
       __ Bind(&correct_num_arguments);
     }
   } else if (!flow_graph().IsCompiledForOsr()) {
@@ -1324,11 +1314,8 @@
   }
 
   __ LoadObject(R5, cache);
-  if (FLAG_use_megamorphic_stub) {
-    __ BranchLink(*StubCode::MegamorphicLookup_entry());
-  } else  {
-    StubCode::EmitMegamorphicLookup(assembler());
-  }
+  __ ldr(LR, Address(THR, Thread::megamorphic_lookup_entry_point_offset()));
+  __ blr(LR);
   __ blr(R1);
 
   __ Bind(&done);
@@ -1413,7 +1400,12 @@
     intptr_t deopt_id,
     TokenPosition token_pos,
     LocationSummary* locs) {
-  __ LoadObject(R4, arguments_descriptor);
+  ASSERT(!function.IsClosureFunction());
+  if (function.HasOptionalParameters()) {
+    __ LoadObject(R4, arguments_descriptor);
+  } else {
+    __ LoadImmediate(R4, 0);  // GC safe smi zero because of stub.
+  }
   // Do not use the code from the function, but let the code be patched so that
   // we can record the outgoing edges to other code.
   GenerateStaticDartCall(deopt_id,
diff --git a/runtime/vm/flow_graph_compiler_dbc.cc b/runtime/vm/flow_graph_compiler_dbc.cc
index 8fb0b4c..fc1534d 100644
--- a/runtime/vm/flow_graph_compiler_dbc.cc
+++ b/runtime/vm/flow_graph_compiler_dbc.cc
@@ -27,7 +27,6 @@
 DEFINE_FLAG(bool, unbox_mints, true, "Optimize 64-bit integer arithmetic.");
 DEFINE_FLAG(bool, unbox_doubles, true, "Optimize double arithmetic.");
 DECLARE_FLAG(bool, enable_simd_inline);
-DECLARE_FLAG(bool, use_megamorphic_stub);
 DECLARE_FLAG(charp, optimization_filter);
 
 void MegamorphicSlowPath::EmitNativeCode(FlowGraphCompiler* compiler) {
@@ -45,7 +44,12 @@
 
 
 bool FlowGraphCompiler::SupportsUnboxedDoubles() {
+#if defined(ARCH_IS_64_BIT)
+  return true;
+#else
+  // We use 64-bit wide stack slots to unbox doubles.
   return false;
+#endif
 }
 
 
@@ -423,7 +427,18 @@
   } else if (source.IsRegister() && destination.IsRegister()) {
     __ Move(destination.reg(), source.reg());
   } else if (source.IsConstant() && destination.IsRegister()) {
-    __ LoadConstant(destination.reg(), source.constant());
+    if (source.constant_instruction()->representation() == kUnboxedDouble) {
+      const Register result = destination.reg();
+      const Object& constant = source.constant();
+      if (Utils::DoublesBitEqual(Double::Cast(constant).value(), 0.0)) {
+        __ BitXor(result, result, result);
+      } else {
+        __ LoadConstant(result, constant);
+        __ UnboxDouble(result, result);
+      }
+    } else {
+      __ LoadConstant(destination.reg(), source.constant());
+    }
   } else {
     compiler_->Bailout("Unsupported move");
     UNREACHABLE();
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 4a036e2..4fc5628 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -29,7 +29,6 @@
 DEFINE_FLAG(bool, unbox_mints, true, "Optimize 64-bit integer arithmetic.");
 
 DECLARE_FLAG(bool, enable_simd_inline);
-DECLARE_FLAG(bool, use_megamorphic_stub);
 
 
 void MegamorphicSlowPath::EmitNativeCode(FlowGraphCompiler* compiler) {
@@ -1055,13 +1054,8 @@
   // No such checking code is generated if only fixed parameters are declared,
   // unless we are in debug mode or unless we are compiling a closure.
   if (num_copied_params == 0) {
-#ifdef DEBUG
-    ASSERT(!parsed_function().function().HasOptionalParameters());
-    const bool check_arguments = !flow_graph().IsCompiledForOsr();
-#else
     const bool check_arguments =
         function.IsClosureFunction() && !flow_graph().IsCompiledForOsr();
-#endif
     if (check_arguments) {
       __ Comment("Check argument count");
       // Check that exactly num_fixed arguments are passed in.
@@ -1075,13 +1069,9 @@
       __ j(EQUAL, &correct_num_arguments, Assembler::kNearJump);
 
       __ Bind(&wrong_num_arguments);
-      if (function.IsClosureFunction()) {
-        __ LeaveFrame();  // The arguments are still on the stack.
-        __ Jmp(*StubCode::CallClosureNoSuchMethod_entry());
-        // The noSuchMethod call may return to the caller, but not here.
-      } else {
-        __ Stop("Wrong number of arguments");
-      }
+      __ LeaveFrame();  // The arguments are still on the stack.
+      __ Jmp(*StubCode::CallClosureNoSuchMethod_entry());
+      // The noSuchMethod call may return to the caller, but not here.
       __ Bind(&correct_num_arguments);
     }
   } else if (!flow_graph().IsCompiledForOsr()) {
@@ -1319,11 +1309,7 @@
     __ Comment("Slow case: megamorphic call");
   }
   __ LoadObject(ECX, cache);
-  if (FLAG_use_megamorphic_stub) {
-    __ Call(*StubCode::MegamorphicLookup_entry());
-  } else  {
-    StubCode::EmitMegamorphicLookup(assembler());
-  }
+  __ call(Address(THR, Thread::megamorphic_lookup_entry_point_offset()));
   __ call(EBX);
 
   __ Bind(&done);
@@ -1362,7 +1348,11 @@
     intptr_t deopt_id,
     TokenPosition token_pos,
     LocationSummary* locs) {
-  __ LoadObject(EDX, arguments_descriptor);
+  if (function.HasOptionalParameters()) {
+    __ LoadObject(EDX, arguments_descriptor);
+  } else {
+    __ xorl(EDX, EDX);  // GC safe smi zero because of stub.
+  }
   // Do not use the code from the function, but let the code be patched so that
   // we can record the outgoing edges to other code.
   GenerateDartCall(deopt_id,
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index 2376554..a6f3f14 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -23,7 +23,6 @@
 namespace dart {
 
 DEFINE_FLAG(bool, trap_on_deoptimization, false, "Trap on deoptimization.");
-DECLARE_FLAG(bool, use_megamorphic_stub);
 
 
 void MegamorphicSlowPath::EmitNativeCode(FlowGraphCompiler* compiler) {
@@ -1073,13 +1072,8 @@
   // No such checking code is generated if only fixed parameters are declared,
   // unless we are in debug mode or unless we are compiling a closure.
   if (num_copied_params == 0) {
-#ifdef DEBUG
-    ASSERT(!parsed_function().function().HasOptionalParameters());
-    const bool check_arguments = !flow_graph().IsCompiledForOsr();
-#else
     const bool check_arguments =
         function.IsClosureFunction() && !flow_graph().IsCompiledForOsr();
-#endif
     if (check_arguments) {
       __ Comment("Check argument count");
       // Check that exactly num_fixed arguments are passed in.
@@ -1092,13 +1086,9 @@
                              ArgumentsDescriptor::positional_count_offset()));
       __ beq(T0, T1, &correct_num_arguments);
       __ Bind(&wrong_num_arguments);
-      if (function.IsClosureFunction()) {
-        __ LeaveDartFrame(kKeepCalleePP);  // Arguments are still on the stack.
-        __ Branch(*StubCode::CallClosureNoSuchMethod_entry());
-        // The noSuchMethod call may return to the caller, but not here.
-      } else {
-        __ Stop("Wrong number of arguments");
-      }
+      __ LeaveDartFrame(kKeepCalleePP);  // Arguments are still on the stack.
+      __ Branch(*StubCode::CallClosureNoSuchMethod_entry());
+      // The noSuchMethod call may return to the caller, but not here.
       __ Bind(&correct_num_arguments);
     }
   } else if (!flow_graph().IsCompiledForOsr()) {
@@ -1349,11 +1339,8 @@
     __ Comment("Slow case: megamorphic call");
   }
   __ LoadObject(S5, cache);
-  if (FLAG_use_megamorphic_stub) {
-    __ BranchLink(*StubCode::MegamorphicLookup_entry());
-  } else  {
-    StubCode::EmitMegamorphicLookup(assembler());
-  }
+  __ lw(T9, Address(THR, Thread::megamorphic_lookup_entry_point_offset()));
+  __ jalr(T9);
   __ jalr(T1);
 
   __ Bind(&done);
@@ -1439,7 +1426,12 @@
     TokenPosition token_pos,
     LocationSummary* locs) {
   __ Comment("StaticCall");
-  __ LoadObject(S4, arguments_descriptor);
+  ASSERT(!function.IsClosureFunction());
+  if (function.HasOptionalParameters()) {
+    __ LoadObject(S4, arguments_descriptor);
+  } else {
+    __ LoadImmediate(S4, 0);  // GC safe smi zero because of stub.
+  }
   // Do not use the code from the function, but let the code be patched so that
   // we can record the outgoing edges to other code.
   GenerateStaticDartCall(deopt_id,
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index 5cc5c93..4c60d20 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -25,7 +25,7 @@
 DEFINE_FLAG(bool, trap_on_deoptimization, false, "Trap on deoptimization.");
 DEFINE_FLAG(bool, unbox_mints, true, "Optimize 64-bit integer arithmetic.");
 DECLARE_FLAG(bool, enable_simd_inline);
-DECLARE_FLAG(bool, use_megamorphic_stub);
+
 
 void MegamorphicSlowPath::EmitNativeCode(FlowGraphCompiler* compiler) {
   Assembler* assembler = compiler->assembler();
@@ -1057,13 +1057,8 @@
   // No such checking code is generated if only fixed parameters are declared,
   // unless we are in debug mode or unless we are compiling a closure.
   if (num_copied_params == 0) {
-#ifdef DEBUG
-    ASSERT(!parsed_function().function().HasOptionalParameters());
-    const bool check_arguments = !flow_graph().IsCompiledForOsr();
-#else
     const bool check_arguments =
         function.IsClosureFunction() && !flow_graph().IsCompiledForOsr();
-#endif
     if (check_arguments) {
       __ Comment("Check argument count");
       // Check that exactly num_fixed arguments are passed in.
@@ -1077,13 +1072,9 @@
       __ j(EQUAL, &correct_num_arguments, Assembler::kNearJump);
 
       __ Bind(&wrong_num_arguments);
-      if (function.IsClosureFunction()) {
-        __ LeaveDartFrame(kKeepCalleePP);  // Leave arguments on the stack.
-        __ Jmp(*StubCode::CallClosureNoSuchMethod_entry());
-        // The noSuchMethod call may return to the caller, but not here.
-      } else {
-        __ Stop("Wrong number of arguments");
-      }
+      __ LeaveDartFrame(kKeepCalleePP);  // Leave arguments on the stack.
+      __ Jmp(*StubCode::CallClosureNoSuchMethod_entry());
+      // The noSuchMethod call may return to the caller, but not here.
       __ Bind(&correct_num_arguments);
     }
   } else if (!flow_graph().IsCompiledForOsr()) {
@@ -1348,11 +1339,7 @@
     __ Comment("Slow case: megamorphic call");
   }
   __ LoadObject(RBX, cache);
-  if (FLAG_use_megamorphic_stub) {
-    __ Call(*StubCode::MegamorphicLookup_entry());
-  } else  {
-    StubCode::EmitMegamorphicLookup(assembler());
-  }
+  __ call(Address(THR, Thread::megamorphic_lookup_entry_point_offset()));
   __ call(RCX);
 
   __ Bind(&done);
@@ -1419,7 +1406,12 @@
     intptr_t deopt_id,
     TokenPosition token_pos,
     LocationSummary* locs) {
-  __ LoadObject(R10, arguments_descriptor);
+  ASSERT(!function.IsClosureFunction());
+  if (function.HasOptionalParameters()) {
+    __ LoadObject(R10, arguments_descriptor);
+  } else {
+    __ xorq(R10, R10);  // GC safe smi zero because of stub.
+  }
   // Do not use the code from the function, but let the code be patched so that
   // we can record the outgoing edges to other code.
   GenerateStaticDartCall(deopt_id,
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index f93b1d1..a8e27c0 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -634,7 +634,9 @@
 
     // Don't inline any intrinsified functions in precompiled mode
     // to reduce code size and make sure we use the intrinsic code.
-    if (FLAG_precompiled_mode && function.is_intrinsic()) {
+    if (FLAG_precompiled_mode &&
+        function.is_intrinsic() &&
+        !inliner_->AlwaysInline(function)) {
       TRACE_INLINING(THR_Print("     Bailout: intrinisic\n"));
       PRINT_INLINING_TREE("intrinsic",
           &call_data->caller, &function, call_data->call);
@@ -2045,15 +2047,6 @@
                                        Definition** array,
                                        Definition* index,
                                        Instruction** cursor) {
-  // Insert index smi check.
-  *cursor = flow_graph->AppendTo(
-      *cursor,
-      new(Z) CheckSmiInstr(new(Z) Value(index),
-                           call->deopt_id(),
-                           call->token_pos()),
-      call->env(),
-      FlowGraph::kEffect);
-
   // Insert array length load and bounds check.
   LoadFieldInstr* length =
       new(Z) LoadFieldInstr(
@@ -2460,6 +2453,29 @@
 }
 
 
+static bool InlineSmiBitAndFromSmi(FlowGraph* flow_graph,
+                                   Instruction* call,
+                                   TargetEntryInstr** entry,
+                                   Definition** last) {
+  Definition* left = call->ArgumentAt(0);
+  Definition* right = call->ArgumentAt(1);
+
+  *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
+                                   call->GetBlock()->try_index());
+  (*entry)->InheritDeoptTarget(Z, call);
+  // Right arguments is known to be smi: other._bitAndFromSmi(this);
+  BinarySmiOpInstr* smi_op =
+      new(Z) BinarySmiOpInstr(Token::kBIT_AND,
+                              new(Z) Value(left),
+                              new(Z) Value(right),
+                              call->deopt_id());
+  flow_graph->AppendTo(*entry, smi_op, call->env(), FlowGraph::kValue);
+  *last = smi_op;
+
+  return true;
+}
+
+
 static bool InlineGrowableArraySetter(FlowGraph* flow_graph,
                                       intptr_t offset,
                                       StoreBarrierType store_barrier_type,
@@ -2495,15 +2511,6 @@
     Definition** array,
     Definition* byte_index,
     Instruction** cursor) {
-  // Insert byte_index smi check.
-  *cursor = flow_graph->AppendTo(*cursor,
-                                 new(Z) CheckSmiInstr(
-                                     new(Z) Value(byte_index),
-                                     call->deopt_id(),
-                                     call->token_pos()),
-                                 call->env(),
-                                 FlowGraph::kEffect);
-
   LoadFieldInstr* length =
       new(Z) LoadFieldInstr(
           new(Z) Value(*array),
@@ -2804,15 +2811,6 @@
     Definition* str,
     Definition* index,
     Instruction* cursor) {
-
-  cursor = flow_graph->AppendTo(cursor,
-                                new(Z) CheckSmiInstr(
-                                    new(Z) Value(index),
-                                    call->deopt_id(),
-                                    call->token_pos()),
-                                call->env(),
-                                FlowGraph::kEffect);
-
   // Load the length of the string.
   // Treat length loads as mutable (i.e. affected by side effects) to avoid
   // hoisting them since we can't hoist the preceding class-check. This
@@ -3227,6 +3225,8 @@
       return InlineGrowableArraySetter(
           flow_graph, GrowableObjectArray::length_offset(), kNoStoreBarrier,
           call, entry, last);
+    case MethodRecognizer::kSmi_bitAndFromSmi:
+      return InlineSmiBitAndFromSmi(flow_graph, call, entry, last);
     default:
       return false;
   }
diff --git a/runtime/vm/flow_graph_range_analysis.cc b/runtime/vm/flow_graph_range_analysis.cc
index 70a9dc5..1e7afbd 100644
--- a/runtime/vm/flow_graph_range_analysis.cc
+++ b/runtime/vm/flow_graph_range_analysis.cc
@@ -693,6 +693,7 @@
     }
 
     if (!range.Equals(defn->range())) {
+#ifndef PRODUCT
       if (FLAG_support_il_printer && FLAG_trace_range_analysis) {
         THR_Print("%c [%" Pd "] %s:  %s => %s\n",
                   OpPrefix(op),
@@ -701,6 +702,7 @@
                   Range::ToCString(defn->range()),
                   Range::ToCString(&range));
       }
+#endif  // !PRODUCT
       defn->set_range(range);
       return true;
     }
@@ -1022,12 +1024,14 @@
     // range give up on generalization for simplicity.
     GrowableArray<Definition*> non_positive_symbols;
     if (!FindNonPositiveSymbols(&non_positive_symbols, upper_bound)) {
+#ifndef PRODUCT
       if (FLAG_support_il_printer && FLAG_trace_range_analysis) {
         THR_Print("Failed to generalize %s index to %s"
                   " (can't ensure positivity)\n",
                   check->ToCString(),
                   IndexBoundToCString(upper_bound));
       }
+#endif  // !PRODUCT
       return;
     }
 
@@ -1056,21 +1060,25 @@
     if (!RangeUtils::IsPositive(lower_bound->range())) {
       // Can't prove that lower bound is positive even with additional checks
       // against potentially non-positive symbols. Give up.
+#ifndef PRODUCT
       if (FLAG_support_il_printer && FLAG_trace_range_analysis) {
         THR_Print("Failed to generalize %s index to %s"
                   " (lower bound is not positive)\n",
                   check->ToCString(),
                   IndexBoundToCString(upper_bound));
       }
+#endif  // !PRODUCT
       return;
     }
 
+#ifndef PRODUCT
     if (FLAG_support_il_printer && FLAG_trace_range_analysis) {
       THR_Print("For %s computed index bounds [%s, %s]\n",
                 check->ToCString(),
                 IndexBoundToCString(lower_bound),
                 IndexBoundToCString(upper_bound));
     }
+#endif  // !PRODUCT
 
     // At this point we know that 0 <= index < UpperBound(index) under
     // certain preconditions. Start by emitting this preconditions.
@@ -1493,6 +1501,7 @@
     return defn;
   }
 
+#ifndef PRODUCT
   static void PrettyPrintIndexBoundRecursively(BufferFormatter* f,
                                                Definition* index_bound) {
     BinarySmiOpInstr* binary_op = index_bound->AsBinarySmiOp();
@@ -1518,6 +1527,7 @@
     PrettyPrintIndexBoundRecursively(&f, index_bound);
     return Thread::Current()->zone()->MakeCopyOfString(buffer);
   }
+#endif  // !PRODUCT
 
   RangeAnalysis* range_analysis_;
   FlowGraph* flow_graph_;
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index 2ee8ed1..2162cfe 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -237,6 +237,13 @@
 }
 
 
+void FlowGraphTypePropagator::VisitCheckArrayBound(
+    CheckArrayBoundInstr* check) {
+  // Array bounds checks also test index for smi.
+  SetCid(check->index()->definition(), kSmiCid);
+}
+
+
 void FlowGraphTypePropagator::VisitCheckClass(CheckClassInstr* check) {
   if ((check->unary_checks().NumberOfChecks() != 1) ||
       !check->Dependencies().IsNone()) {
diff --git a/runtime/vm/flow_graph_type_propagator.h b/runtime/vm/flow_graph_type_propagator.h
index 3c10917..7a5e87e 100644
--- a/runtime/vm/flow_graph_type_propagator.h
+++ b/runtime/vm/flow_graph_type_propagator.h
@@ -27,6 +27,7 @@
 
   virtual void VisitJoinEntry(JoinEntryInstr* instr);
   virtual void VisitCheckSmi(CheckSmiInstr* instr);
+  virtual void VisitCheckArrayBound(CheckArrayBoundInstr* instr);
   virtual void VisitCheckClass(CheckClassInstr* instr);
   virtual void VisitCheckClassId(CheckClassIdInstr* instr);
   virtual void VisitGuardFieldClass(GuardFieldClassInstr* instr);
diff --git a/runtime/vm/gc_marker.cc b/runtime/vm/gc_marker.cc
index ae0e205..319716e 100644
--- a/runtime/vm/gc_marker.cc
+++ b/runtime/vm/gc_marker.cc
@@ -534,6 +534,7 @@
 
 
 void GCMarker::ProcessObjectIdTable(Isolate* isolate) {
+#ifndef PRODUCT
   if (!FLAG_support_service) {
     return;
   }
@@ -541,6 +542,7 @@
   ObjectIdRing* ring = isolate->object_id_ring();
   ASSERT(ring != NULL);
   ring->VisitPointers(&visitor);
+#endif  // !PRODUCT
 }
 
 
@@ -666,6 +668,7 @@
 
 template<class MarkingVisitorType>
 void GCMarker::FinalizeResultsFrom(MarkingVisitorType* visitor) {
+#ifndef PRODUCT
   {
     MutexLocker ml(&stats_mutex_);
     marked_bytes_ += visitor->marked_bytes();
@@ -680,6 +683,7 @@
       }
     }
   }
+#endif  // !PRODUCT
   visitor->Finalize();
 }
 
diff --git a/runtime/vm/gc_sweeper.cc b/runtime/vm/gc_sweeper.cc
index 5b7949b..e37f1db 100644
--- a/runtime/vm/gc_sweeper.cc
+++ b/runtime/vm/gc_sweeper.cc
@@ -152,7 +152,7 @@
     {
       MonitorLocker ml(old_space_->tasks_lock());
       old_space_->set_tasks(old_space_->tasks() - 1);
-      ml.Notify();
+      ml.NotifyAll();
     }
   }
 
diff --git a/runtime/vm/heap.cc b/runtime/vm/heap.cc
index 21a4b46..83bacb1 100644
--- a/runtime/vm/heap.cc
+++ b/runtime/vm/heap.cc
@@ -236,7 +236,7 @@
 #endif
   ASSERT(old_space_->tasks() == 1);
   old_space_->set_tasks(0);
-  ml.Notify();
+  ml.NotifyAll();
 }
 
 
@@ -350,6 +350,7 @@
 }
 
 
+#ifndef PRODUCT
 void Heap::UpdateClassHeapStatsBeforeGC(Heap::Space space) {
   ClassTable* class_table = isolate()->class_table();
   if (space == kNew) {
@@ -358,6 +359,7 @@
     class_table->ResetCountersOld();
   }
 }
+#endif
 
 
 void Heap::CollectNewSpaceGarbage(Thread* thread,
@@ -369,9 +371,9 @@
     RecordBeforeGC(kNew, reason);
     VMTagScope tagScope(thread, VMTag::kGCNewSpaceTagId);
     TIMELINE_FUNCTION_GC_DURATION(thread, "CollectNewGeneration");
-    UpdateClassHeapStatsBeforeGC(kNew);
+    NOT_IN_PRODUCT(UpdateClassHeapStatsBeforeGC(kNew));
     new_space_.Scavenge(invoke_api_callbacks);
-    isolate()->class_table()->UpdatePromoted();
+    NOT_IN_PRODUCT(isolate()->class_table()->UpdatePromoted());
     RecordAfterGC(kNew);
     PrintStats();
     NOT_IN_PRODUCT(PrintStatsToTimeline(&tds));
@@ -393,7 +395,7 @@
     RecordBeforeGC(kOld, reason);
     VMTagScope tagScope(thread, VMTag::kGCOldSpaceTagId);
     TIMELINE_FUNCTION_GC_DURATION(thread, "CollectOldGeneration");
-    UpdateClassHeapStatsBeforeGC(kOld);
+    NOT_IN_PRODUCT(UpdateClassHeapStatsBeforeGC(kOld));
     old_space_.MarkSweep(invoke_api_callbacks);
     RecordAfterGC(kOld);
     PrintStats();
@@ -729,11 +731,13 @@
   stats_.after_.old_ = old_space_.GetCurrentUsage();
   ASSERT((space == kNew && gc_new_space_in_progress_) ||
          (space == kOld && gc_old_space_in_progress_));
+#ifndef PRODUCT
   if (FLAG_support_service && Service::gc_stream.enabled()) {
     ServiceEvent event(Isolate::Current(), ServiceEvent::kGC);
     event.set_gc_stats(&stats_);
     Service::HandleEvent(&event);
   }
+#endif  // !PRODUCT
 }
 
 
diff --git a/runtime/vm/heap_test.cc b/runtime/vm/heap_test.cc
index 1d55a13..7454cf4 100644
--- a/runtime/vm/heap_test.cc
+++ b/runtime/vm/heap_test.cc
@@ -74,6 +74,7 @@
 }
 
 
+#ifndef PRODUCT
 class ClassHeapStatsTestHelper {
  public:
   static ClassHeapStats* GetHeapStatsForCid(ClassTable* class_table,
@@ -231,6 +232,7 @@
   EXPECT_GT(expected_size + kTolerance, after - before);
   Dart_ExitScope();
 }
+#endif  // !PRODUCT
 
 
 class FindOnly : public FindObjectVisitor {
diff --git a/runtime/vm/il_printer.cc b/runtime/vm/il_printer.cc
index 5104545..d8d18f3 100644
--- a/runtime/vm/il_printer.cc
+++ b/runtime/vm/il_printer.cc
@@ -197,16 +197,6 @@
                               const ICData& ic_data,
                               intptr_t num_checks_to_print) {
   f->Print(" IC[");
-  if (ic_data.HasRangeFeedback()) {
-    f->Print("{%s",
-        ICData::RangeFeedbackToString(ic_data.DecodeRangeFeedbackAt(0)));
-    if (ic_data.NumArgsTested() == 2) {
-      f->Print(" x %s",
-          ICData::RangeFeedbackToString(ic_data.DecodeRangeFeedbackAt(1)));
-    }
-    f->Print("->%s} ",
-        ICData::RangeFeedbackToString(ic_data.DecodeRangeFeedbackAt(2)));
-  }
   f->Print("%" Pd ": ", ic_data.NumberOfChecks());
   Function& target = Function::Handle();
   if ((num_checks_to_print == FlowGraphPrinter::kPrintAll) ||
diff --git a/runtime/vm/instructions_dbc.cc b/runtime/vm/instructions_dbc.cc
index 4dc73be..d648d511 100644
--- a/runtime/vm/instructions_dbc.cc
+++ b/runtime/vm/instructions_dbc.cc
@@ -20,6 +20,7 @@
     case Bytecode::kLoadConstant:
     case Bytecode::kPushConstant:
     case Bytecode::kStaticCall:
+    case Bytecode::kIndirectStaticCall:
     case Bytecode::kInstanceCall1:
     case Bytecode::kInstanceCall2:
     case Bytecode::kInstanceCall1Opt:
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 689d535..d1f8f92 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -3177,18 +3177,6 @@
       ASSERT(ArgumentCount() == 2);
       compiler->EmitInstanceCall(*stub_entry, *call_ic_data, ArgumentCount(),
                                  deopt_id(), token_pos(), locs());
-    } else if (FLAG_ic_range_profiling &&
-               (Token::IsBinaryArithmeticOperator(token_kind()) ||
-                Token::IsUnaryArithmeticOperator(token_kind()))) {
-      ASSERT(Token::IsUnaryArithmeticOperator(token_kind()) ==
-                 (ArgumentCount() == 1));
-      ASSERT(Token::IsBinaryArithmeticOperator(token_kind()) ==
-                 (ArgumentCount() == 2));
-      const StubEntry* stub_entry = (ArgumentCount() == 1)
-          ? StubCode::UnaryRangeCollectingInlineCache_entry()
-          : StubCode::BinaryRangeCollectingInlineCache_entry();
-      compiler->EmitInstanceCall(*stub_entry, *call_ic_data, ArgumentCount(),
-                                 deopt_id(), token_pos(), locs());
     } else {
       compiler->GenerateInstanceCall(deopt_id(),
                                      token_pos(),
@@ -3198,14 +3186,17 @@
     }
   }
 #else
-  ICData* ic_data = &ICData::ZoneHandle(call_ic_data->Original());
+  ICData* original_ic_data = &ICData::ZoneHandle(call_ic_data->Original());
 
   // Emit smi fast path instruction. If fast-path succeeds it skips the next
-  // instruction otherwise it falls through.
-  TryFastPathSmiOp(compiler, ic_data, function_name());
+  // instruction otherwise it falls through. Only attempt in unoptimized code
+  // because TryFastPathSmiOp will update original_ic_data.
+  if (!compiler->is_optimizing()) {
+    TryFastPathSmiOp(compiler, original_ic_data, function_name());
+  }
 
-  const intptr_t call_ic_data_kidx = __ AddConstant(*call_ic_data);
-  switch (ic_data->NumArgsTested()) {
+  const intptr_t call_ic_data_kidx = __ AddConstant(*original_ic_data);
+  switch (original_ic_data->NumArgsTested()) {
     case 1:
       if (compiler->is_optimizing()) {
         __ InstanceCall1Opt(ArgumentCount(), call_ic_data_kidx);
@@ -3292,7 +3283,6 @@
 
 
 void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-#if !defined(TARGET_ARCH_DBC)
   const ICData* call_ic_data = NULL;
   if (!FLAG_propagate_ic_data || !compiler->is_optimizing() ||
       (ic_data() == NULL)) {
@@ -3318,6 +3308,8 @@
   } else {
     call_ic_data = &ICData::ZoneHandle(ic_data()->raw());
   }
+
+#if !defined(TARGET_ARCH_DBC)
   compiler->GenerateStaticCall(deopt_id(),
                                token_pos(),
                                function(),
@@ -3333,17 +3325,20 @@
         Array::Handle(ic_data()->arguments_descriptor());
   const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor);
 
-  __ PushConstant(function());
-  __ StaticCall(ArgumentCount(), argdesc_kidx);
-  RawPcDescriptors::Kind kind = (compiler->is_optimizing())
-                              ? RawPcDescriptors::kOther
-                              : RawPcDescriptors::kUnoptStaticCall;
-  compiler->AddCurrentDescriptor(kind, deopt_id(), token_pos());
-
-  compiler->RecordAfterCall(this);
-
   if (compiler->is_optimizing()) {
+    __ PushConstant(function());
+    __ StaticCall(ArgumentCount(), argdesc_kidx);
+    compiler->AddCurrentDescriptor(RawPcDescriptors::kOther,
+        deopt_id(), token_pos());
+    compiler->RecordAfterCall(this);
     __ PopLocal(locs()->out(0).reg());
+  } else {
+    const intptr_t ic_data_kidx = __ AddConstant(*call_ic_data);
+    __ PushConstant(ic_data_kidx);
+    __ IndirectStaticCall(ArgumentCount(), argdesc_kidx);
+    compiler->AddCurrentDescriptor(RawPcDescriptors::kUnoptStaticCall,
+        deopt_id(), token_pos());
+    compiler->RecordAfterCall(this);
   }
 #endif  // !defined(TARGET_ARCH_DBC)
 }
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 7307344..bfcb8a7 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -512,6 +512,7 @@
   M(ShiftMintOp)                                                               \
   M(UnaryMintOp)                                                               \
   M(CheckArrayBound)                                                           \
+  M(GenericCheckBound)                                                         \
   M(Constraint)                                                                \
   M(StringToCharCode)                                                          \
   M(OneByteStringFromCharCode)                                                 \
@@ -7928,6 +7929,35 @@
 };
 
 
+class GenericCheckBoundInstr : public TemplateInstruction<2, Throws, NoCSE> {
+ public:
+  GenericCheckBoundInstr(Value* length, Value* index, intptr_t deopt_id)
+      : TemplateInstruction(deopt_id) {
+    SetInputAt(kLengthPos, length);
+    SetInputAt(kIndexPos, index);
+  }
+
+  Value* length() const { return inputs_[kLengthPos]; }
+  Value* index() const { return inputs_[kIndexPos]; }
+
+  virtual EffectSet Effects() const { return EffectSet::None(); }
+  virtual EffectSet Dependencies() const { return EffectSet::None(); }
+
+  DECLARE_INSTRUCTION(GenericCheckBound)
+
+  virtual bool CanDeoptimize() const { return true; }
+
+  // Give a name to the location/input indices.
+  enum {
+    kLengthPos = 0,
+    kIndexPos = 1
+  };
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(GenericCheckBoundInstr);
+};
+
+
 class UnboxedIntConverterInstr : public TemplateDefinition<1, NoThrow> {
  public:
   UnboxedIntConverterInstr(Representation from,
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 1750418..aac4891 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -6111,8 +6111,7 @@
   Label* deopt = compiler->AddDeoptStub(deopt_id(),
                                         ICData::kDeoptCheckSmi,
                                         licm_hoisted_ ? ICData::kHoisted : 0);
-  __ tst(value, Operand(kSmiTagMask));
-  __ b(deopt, NE);
+  __ BranchIfNotSmi(value, deopt);
 }
 
 
@@ -6135,6 +6134,66 @@
 }
 
 
+LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone,
+                                                             bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs = new(zone) LocationSummary(
+      zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
+  locs->set_in(kLengthPos, Location::RequiresRegister());
+  locs->set_in(kIndexPos, Location::RequiresRegister());
+  return locs;
+}
+
+
+class RangeErrorSlowPath : public SlowPathCode {
+ public:
+  RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index)
+      : instruction_(instruction), try_index_(try_index) { }
+
+  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    if (Assembler::EmittingComments()) {
+      __ Comment("slow path check bound operation");
+    }
+    __ Bind(entry_label());
+    LocationSummary* locs = instruction_->locs();
+    __ Push(locs->in(0).reg());
+    __ Push(locs->in(1).reg());
+    __ CallRuntime(kRangeErrorRuntimeEntry, 2);
+    compiler->pc_descriptors_list()->AddDescriptor(
+        RawPcDescriptors::kOther,
+        compiler->assembler()->CodeSize(),
+        instruction_->deopt_id(),
+        instruction_->token_pos(),
+        try_index_);
+    compiler->RecordSafepoint(locs, 2);
+    __ bkpt(0);
+  }
+
+ private:
+  GenericCheckBoundInstr* instruction_;
+  intptr_t try_index_;
+};
+
+
+void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  RangeErrorSlowPath* slow_path =
+      new RangeErrorSlowPath(this, compiler->CurrentTryIndex());
+  compiler->AddSlowPathCode(slow_path);
+
+  Location length_loc = locs()->in(kLengthPos);
+  Location index_loc = locs()->in(kIndexPos);
+  Register length = length_loc.reg();
+  Register index = index_loc.reg();
+  const intptr_t index_cid = this->index()->Type()->ToCid();
+  if (index_cid != kSmiCid) {
+    __ BranchIfNotSmi(index, slow_path->entry_label());
+  }
+  __ cmp(index, Operand(length));
+  __ b(slow_path->entry_label(), CS);
+}
+
+
 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone,
                                                            bool opt) const {
   const intptr_t kNumInputs = 2;
@@ -6168,6 +6227,7 @@
     return;
   }
 
+  const intptr_t index_cid = index()->Type()->ToCid();
   if (index_loc.IsConstant()) {
     const Register length = length_loc.reg();
     const Smi& index = Smi::Cast(index_loc.constant());
@@ -6176,6 +6236,9 @@
   } else if (length_loc.IsConstant()) {
     const Smi& length = Smi::Cast(length_loc.constant());
     const Register index = index_loc.reg();
+    if (index_cid != kSmiCid) {
+      __ BranchIfNotSmi(index, deopt);
+    }
     if (length.Value() == Smi::kMaxValue) {
       __ tst(index, Operand(index));
       __ b(deopt, MI);
@@ -6186,6 +6249,9 @@
   } else {
     const Register length = length_loc.reg();
     const Register index = index_loc.reg();
+    if (index_cid != kSmiCid) {
+      __ BranchIfNotSmi(index, deopt);
+    }
     __ cmp(index, Operand(length));
     __ b(deopt, CS);
   }
diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc
index 642bc9e..c4f0fdc 100644
--- a/runtime/vm/intermediate_language_arm64.cc
+++ b/runtime/vm/intermediate_language_arm64.cc
@@ -5254,8 +5254,68 @@
   Label* deopt = compiler->AddDeoptStub(deopt_id(),
                                         ICData::kDeoptCheckSmi,
                                         licm_hoisted_ ? ICData::kHoisted : 0);
-  __ tsti(value, Immediate(kSmiTagMask));
-  __ b(deopt, NE);
+  __ BranchIfNotSmi(value, deopt);
+}
+
+
+
+LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone,
+                                                             bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs = new(zone) LocationSummary(
+      zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
+  locs->set_in(kLengthPos, Location::RequiresRegister());
+  locs->set_in(kIndexPos, Location::RequiresRegister());
+  return locs;
+}
+
+
+class RangeErrorSlowPath : public SlowPathCode {
+ public:
+  RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index)
+      : instruction_(instruction), try_index_(try_index) { }
+
+  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    if (Assembler::EmittingComments()) {
+      __ Comment("slow path check bound operation");
+    }
+    __ Bind(entry_label());
+    LocationSummary* locs = instruction_->locs();
+    __ Push(locs->in(0).reg());
+    __ Push(locs->in(1).reg());
+    __ CallRuntime(kRangeErrorRuntimeEntry, 2);
+    compiler->pc_descriptors_list()->AddDescriptor(
+        RawPcDescriptors::kOther,
+        compiler->assembler()->CodeSize(),
+        instruction_->deopt_id(),
+        instruction_->token_pos(),
+        try_index_);
+    compiler->RecordSafepoint(locs, 2);
+    __ brk(0);
+  }
+
+ private:
+  GenericCheckBoundInstr* instruction_;
+  intptr_t try_index_;
+};
+
+
+void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  RangeErrorSlowPath* slow_path =
+      new RangeErrorSlowPath(this, compiler->CurrentTryIndex());
+  compiler->AddSlowPathCode(slow_path);
+
+  Location length_loc = locs()->in(kLengthPos);
+  Location index_loc = locs()->in(kIndexPos);
+  Register length = length_loc.reg();
+  Register index = index_loc.reg();
+  const intptr_t index_cid = this->index()->Type()->ToCid();
+  if (index_cid != kSmiCid) {
+    __ BranchIfNotSmi(index, slow_path->entry_label());
+  }
+  __ cmp(index, Operand(length));
+  __ b(slow_path->entry_label(), CS);
 }
 
 
@@ -5282,6 +5342,7 @@
   Location length_loc = locs()->in(kLengthPos);
   Location index_loc = locs()->in(kIndexPos);
 
+  const intptr_t index_cid = index()->Type()->ToCid();
   if (length_loc.IsConstant() && index_loc.IsConstant()) {
     // TODO(srdjan): remove this code once failures are fixed.
     if ((Smi::Cast(length_loc.constant()).Value() >
@@ -5307,6 +5368,9 @@
   } else if (length_loc.IsConstant()) {
     const Smi& length = Smi::Cast(length_loc.constant());
     const Register index = index_loc.reg();
+    if (index_cid != kSmiCid) {
+      __ BranchIfNotSmi(index, deopt);
+    }
     if (length.Value() == Smi::kMaxValue) {
       __ tst(index, Operand(index));
       __ b(deopt, MI);
@@ -5317,6 +5381,9 @@
   } else {
     const Register length = length_loc.reg();
     const Register index = index_loc.reg();
+    if (index_cid != kSmiCid) {
+      __ BranchIfNotSmi(index, deopt);
+    }
     __ CompareRegisters(index, length);
     __ b(deopt, CS);
   }
diff --git a/runtime/vm/intermediate_language_dbc.cc b/runtime/vm/intermediate_language_dbc.cc
index 8c954b6..0dda8e1 100644
--- a/runtime/vm/intermediate_language_dbc.cc
+++ b/runtime/vm/intermediate_language_dbc.cc
@@ -30,36 +30,43 @@
 
 // List of instructions that are still unimplemented by DBC backend.
 #define FOR_EACH_UNIMPLEMENTED_INSTRUCTION(M)                                  \
-  M(IndirectGoto)                                                              \
   M(LoadCodeUnits)                                                             \
   M(LoadUntagged)                                                              \
   M(AllocateUninitializedContext)                                              \
   M(BinaryInt32Op)                                                             \
-  M(UnaryDoubleOp)                                                             \
-  M(SmiToDouble)                                                               \
   M(Int32ToDouble)                                                             \
-  M(MintToDouble)                                                              \
   M(DoubleToInteger)                                                           \
-  M(DoubleToSmi)                                                               \
   M(DoubleToDouble)                                                            \
   M(DoubleToFloat)                                                             \
   M(FloatToDouble)                                                             \
-  M(UnboxedConstant)                                                           \
-  M(BinaryDoubleOp)                                                            \
-  M(MathUnary)                                                                 \
-  M(MathMinMax)                                                                \
-  M(Box)                                                                       \
-  M(Unbox)                                                                     \
   M(BoxInt64)                                                                  \
-  M(CaseInsensitiveCompareUC16)                                                \
-  M(BinaryMintOp)                                                              \
-  M(ShiftMintOp)                                                               \
-  M(UnaryMintOp)                                                               \
-  M(InvokeMathCFunction)                                                       \
   M(MergedMath)                                                                \
   M(GuardFieldClass)                                                           \
   M(GuardFieldLength)                                                          \
   M(IfThenElse)                                                                \
+  M(ExtractNthOutput)                                                          \
+  M(BinaryUint32Op)                                                            \
+  M(ShiftUint32Op)                                                             \
+  M(UnaryUint32Op)                                                             \
+  M(UnboxedIntConverter)                                                       \
+  M(BoxInteger32)                                                              \
+  M(UnboxInteger32)                                                            \
+
+// List of instructions that are not used by DBC.
+// Things we aren't planning to implement for DBC:
+// - Unboxed SIMD,
+// - Unboxed Mint,
+// - Optimized RegExps,
+// - Precompilation.
+#define FOR_EACH_UNREACHABLE_INSTRUCTION(M)                                    \
+  M(CaseInsensitiveCompareUC16)                                                \
+  M(GenericCheckBound)                                                         \
+  M(GrowRegExpStack)                                                           \
+  M(IndirectGoto)                                                              \
+  M(MintToDouble)                                                              \
+  M(BinaryMintOp)                                                              \
+  M(ShiftMintOp)                                                               \
+  M(UnaryMintOp)                                                               \
   M(BinaryFloat32x4Op)                                                         \
   M(Simd32x4Shuffle)                                                           \
   M(Simd32x4ShuffleMix)                                                        \
@@ -82,7 +89,6 @@
   M(Int32x4SetFlag)                                                            \
   M(Int32x4ToFloat32x4)                                                        \
   M(BinaryInt32x4Op)                                                           \
-  M(TestCids)                                                                  \
   M(BinaryFloat64x2Op)                                                         \
   M(Float64x2Zero)                                                             \
   M(Float64x2Constructor)                                                      \
@@ -92,19 +98,7 @@
   M(Simd64x2Shuffle)                                                           \
   M(Float64x2ZeroArg)                                                          \
   M(Float64x2OneArg)                                                           \
-  M(ExtractNthOutput)                                                          \
-  M(BinaryUint32Op)                                                            \
-  M(ShiftUint32Op)                                                             \
-  M(UnaryUint32Op)                                                             \
-  M(UnboxedIntConverter)                                                       \
-  M(GrowRegExpStack)                                                           \
-  M(BoxInteger32)                                                              \
-  M(UnboxInteger32)                                                            \
   M(CheckedSmiOp)                                                              \
-  M(CheckArrayBound)                                                           \
-  M(RelationalOp)                                                              \
-  M(EqualityCompare)                                                           \
-  M(LoadIndexed)
 
 // Location summaries actually are not used by the unoptimizing DBC compiler
 // because we don't allocate any registers.
@@ -112,14 +106,17 @@
     Zone* zone,
     intptr_t num_inputs,
     Location output = Location::NoLocation(),
-    LocationSummary::ContainsCall contains_call = LocationSummary::kNoCall) {
-  const intptr_t kNumTemps = 0;
+    LocationSummary::ContainsCall contains_call = LocationSummary::kNoCall,
+    intptr_t num_temps = 0) {
   LocationSummary* locs = new(zone) LocationSummary(
-      zone, num_inputs, kNumTemps, contains_call);
+      zone, num_inputs, num_temps, contains_call);
   for (intptr_t i = 0; i < num_inputs; i++) {
     locs->set_in(i, (contains_call == LocationSummary::kNoCall) ?
         Location::RequiresRegister() : Location::RegisterLocation(i));
   }
+  for (intptr_t i = 0; i < num_temps; i++) {
+    locs->set_temp(i, Location::RequiresRegister());
+  }
   if (!output.IsInvalid()) {
     // For instructions that call we default to returning result in R0.
     locs->set_out(0, output);
@@ -145,11 +142,23 @@
     return NULL;                                                               \
   }                                                                            \
 
+#define DEFINE_UNREACHABLE_MAKE_LOCATION_SUMMARY(Name)                         \
+  LocationSummary* Name##Instr::MakeLocationSummary(Zone* zone, bool opt)      \
+      const {                                                                  \
+    UNREACHABLE();                                                             \
+    return NULL;                                                               \
+  }                                                                            \
+
 #define DEFINE_UNIMPLEMENTED_EMIT_NATIVE_CODE(Name)                            \
   void Name##Instr::EmitNativeCode(FlowGraphCompiler* compiler) {              \
     UNIMPLEMENTED();                                                           \
   }
 
+#define DEFINE_UNREACHABLE_EMIT_NATIVE_CODE(Name)                              \
+  void Name##Instr::EmitNativeCode(FlowGraphCompiler* compiler) {              \
+    UNREACHABLE();                                                             \
+  }
+
 #define DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(Name)                            \
   void Name##Instr::EmitBranchCode(FlowGraphCompiler*, BranchInstr*) {         \
     UNIMPLEMENTED();                                                           \
@@ -168,9 +177,13 @@
 
 #undef DEFINE_UNIMPLEMENTED
 
-DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(TestCids)
-DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(RelationalOp)
-DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(EqualityCompare)
+#define DEFINE_UNREACHABLE(Name)                                               \
+  DEFINE_UNREACHABLE_MAKE_LOCATION_SUMMARY(Name)                               \
+  DEFINE_UNREACHABLE_EMIT_NATIVE_CODE(Name)                                    \
+
+FOR_EACH_UNREACHABLE_INSTRUCTION(DEFINE_UNREACHABLE)
+
+#undef DEFINE_UNREACHABLE
 
 
 EMIT_NATIVE_CODE(InstanceOf, 2, Location::SameAsFirstInput(),
@@ -228,6 +241,24 @@
 
 
 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(ic_data().NumArgsTested() == 1);
+  if (!with_checks()) {
+    ASSERT(ic_data().HasOneTarget());
+    const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0));
+    const Array& arguments_descriptor =
+        Array::Handle(ArgumentsDescriptor::New(
+            instance_call()->ArgumentCount(),
+            instance_call()->argument_names()));
+    const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor);
+
+    __ PushConstant(target);
+    __ StaticCall(instance_call()->ArgumentCount(), argdesc_kidx);
+    compiler->AddCurrentDescriptor(RawPcDescriptors::kOther,
+        deopt_id(), instance_call()->token_pos());
+    compiler->RecordAfterCall(this);
+    __ PopLocal(locs()->out(0).reg());
+    return;
+  }
   Unsupported(compiler);
   UNREACHABLE();
 }
@@ -294,6 +325,25 @@
 }
 
 
+EMIT_NATIVE_CODE(UnboxedConstant, 0, Location::RequiresRegister()) {
+  // The register allocator drops constant definitions that have no uses.
+  if (locs()->out(0).IsInvalid()) {
+    return;
+  }
+  if (representation_ != kUnboxedDouble) {
+    Unsupported(compiler);
+    UNREACHABLE();
+  }
+  const Register result = locs()->out(0).reg();
+  if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) {
+    __ BitXor(result, result, result);
+  } else {
+    __ LoadConstant(result, value());
+    __ UnboxDouble(result, result);
+  }
+}
+
+
 EMIT_NATIVE_CODE(Return, 1) {
   if (compiler->is_optimizing()) {
     __ Return(locs()->in(0).reg());
@@ -367,7 +417,6 @@
       compiler->assembler()->AddConstant(arguments_descriptor);
   __ StaticCall(argument_count, argdesc_kidx);
   compiler->RecordAfterCall(this);
-
   if (compiler->is_optimizing()) {
     __ PopLocal(locs()->out(0).reg());
   }
@@ -378,14 +427,25 @@
                                   Condition true_condition,
                                   BranchLabels labels) {
   if (true_condition == NEXT_IS_TRUE) {
+    // NEXT_IS_TRUE indicates that the preceeding test expects the true case
+    // to be in the subsequent instruction, which it skips if the test fails.
     __ Jump(labels.true_label);
     if (labels.fall_through != labels.false_label) {
+      // The preceeding Jump instruction will be skipped if the test fails.
+      // If we aren't falling through to the false case, then we have to do
+      // a Jump to it here.
       __ Jump(labels.false_label);
     }
   } else {
     ASSERT(true_condition == NEXT_IS_FALSE);
+    // NEXT_IS_FALSE indicates that the preceeing test has been flipped and
+    // expects the false case to be in the subsequent instruction, which it
+    // skips if the test succeeds.
     __ Jump(labels.false_label);
     if (labels.fall_through != labels.true_label) {
+      // The preceeding Jump instruction will be skipped if the test succeeds.
+      // If we aren't falling through to the true case, then we have to do
+      // a Jump to it here.
       __ Jump(labels.true_label);
     }
   }
@@ -544,6 +604,62 @@
 }
 
 
+Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+                                           BranchLabels labels) {
+  ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT));
+  const Register value = locs()->in(0).reg();
+  const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0;
+
+  const ZoneGrowableArray<intptr_t>& data = cid_results();
+  const intptr_t num_cases = data.length() / 2;
+  ASSERT(num_cases <= 255);
+  __ TestCids(value, num_cases);
+
+  bool result = false;
+  for (intptr_t i = 0; i < data.length(); i += 2) {
+    const intptr_t test_cid = data[i];
+    result = data[i + 1] == true_result;
+    __ Nop(result ? 1 : 0, compiler->ToEmbeddableCid(test_cid, this));
+  }
+
+  // No match found, deoptimize or false.
+  if (CanDeoptimize()) {
+    compiler->EmitDeopt(deopt_id(),
+                        ICData::kDeoptTestCids,
+                        licm_hoisted_ ? ICData::kHoisted : 0);
+  } else {
+    Label* target = result ? labels.false_label : labels.true_label;
+    __ Jump(target);
+  }
+
+  return NEXT_IS_TRUE;
+}
+
+
+void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler,
+                                   BranchInstr* branch) {
+  BranchLabels labels = compiler->CreateBranchLabels(branch);
+  Condition true_condition = EmitComparisonCode(compiler, labels);
+  EmitBranchOnCondition(compiler, true_condition, labels);
+}
+
+
+EMIT_NATIVE_CODE(TestCids, 1, Location::RequiresRegister(),
+                 LocationSummary::kNoCall) {
+  Register result_reg = locs()->out(0).reg();
+  Label is_true, is_false, done;
+  BranchLabels labels = { &is_true, &is_false, &is_false };
+  EmitComparisonCode(compiler, labels);
+  __ Jump(&is_true);
+  __ Bind(&is_false);
+  __ LoadConstant(result_reg, Bool::False());
+  __ Jump(&done);
+  __ Bind(&is_true);
+  __ LoadConstant(result_reg, Bool::True());
+  __ Bind(&done);
+}
+
+
 EMIT_NATIVE_CODE(CreateArray,
                  2, Location::RequiresRegister(),
                  LocationSummary::kCall) {
@@ -559,15 +675,38 @@
 }
 
 
-EMIT_NATIVE_CODE(StoreIndexed, 3) {
+EMIT_NATIVE_CODE(StoreIndexed, 3, Location::NoLocation(),
+                 LocationSummary::kNoCall, 1) {
   if (compiler->is_optimizing()) {
-    if (class_id() != kArrayCid) {
+    if (IsExternal()) {
       Unsupported(compiler);
       UNREACHABLE();
     }
-    __ StoreIndexed(locs()->in(kArrayPos).reg(),
-                    locs()->in(kIndexPos).reg(),
-                    locs()->in(kValuePos).reg());
+    const Register array = locs()->in(kArrayPos).reg();
+    const Register index = locs()->in(kIndexPos).reg();
+    const Register value = locs()->in(kValuePos).reg();
+    const Register temp = locs()->temp(0).reg();
+    switch (class_id()) {
+      case kArrayCid:
+        __ StoreIndexed(array, index, value);
+        break;
+      case kTypedDataFloat64ArrayCid:
+        if ((index_scale() != 8) && (index_scale() != 1)) {
+          Unsupported(compiler);
+          UNREACHABLE();
+        }
+        if (index_scale() == 1) {
+          __ ShrImm(temp, index, 3);
+        } else {
+          __ Move(temp, index);
+        }
+        __ StoreFloat64Indexed(array, temp, value);
+        break;
+      default:
+        Unsupported(compiler);
+        UNREACHABLE();
+        break;
+    }
   } else {
     ASSERT(class_id() == kArrayCid);
     __ StoreIndexedTOS();
@@ -575,6 +714,49 @@
 }
 
 
+EMIT_NATIVE_CODE(LoadIndexed, 2, Location::RequiresRegister()) {
+  ASSERT(compiler->is_optimizing());
+  if (IsExternal()) {
+    Unsupported(compiler);
+    UNREACHABLE();
+  }
+  const Register array = locs()->in(0).reg();
+  const Register index = locs()->in(1).reg();
+  const Register result = locs()->out(0).reg();
+  switch (class_id()) {
+    case kArrayCid:
+      __ LoadIndexed(result, array, index);
+      break;
+    case kTypedDataFloat64ArrayCid:
+      if ((index_scale() != 8) && (index_scale() != 1)) {
+        Unsupported(compiler);
+        UNREACHABLE();
+      }
+      if (index_scale() == 1) {
+        __ ShrImm(index, index, 3);
+      }
+      __ LoadFloat64Indexed(result, array, index);
+      break;
+    case kOneByteStringCid:
+      ASSERT(index_scale() == 1);
+      __ LoadOneByteStringIndexed(result, array, index);
+      break;
+    case kTwoByteStringCid:
+      if (index_scale() != 2) {
+        // TODO(zra): Fix-up index.
+        Unsupported(compiler);
+        UNREACHABLE();
+      }
+      __ LoadTwoByteStringIndexed(result, array, index);
+      break;
+    default:
+      Unsupported(compiler);
+      UNREACHABLE();
+      break;
+  }
+}
+
+
 EMIT_NATIVE_CODE(StringInterpolate,
                  1, Location::RegisterLocation(0),
                  LocationSummary::kCall) {
@@ -588,7 +770,6 @@
   const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor);
   __ StaticCall(kArgumentCount, argdesc_kidx);
   compiler->RecordAfterCall(this);
-
   if (compiler->is_optimizing()) {
     __ PopLocal(locs()->out(0).reg());
   }
@@ -642,7 +823,6 @@
 }
 
 
-
 EMIT_NATIVE_CODE(AllocateObject,
                  0, Location::RequiresRegister(),
                  LocationSummary::kCall) {
@@ -741,10 +921,10 @@
 
 EMIT_NATIVE_CODE(Throw, 0, Location::NoLocation(), LocationSummary::kCall) {
   __ Throw(0);
-  compiler->RecordSafepoint(locs());
   compiler->AddCurrentDescriptor(RawPcDescriptors::kOther,
                                  deopt_id(),
                                  token_pos());
+  compiler->RecordAfterCall(this);
   __ Trap();
 }
 
@@ -752,10 +932,10 @@
 EMIT_NATIVE_CODE(ReThrow, 0, Location::NoLocation(), LocationSummary::kCall) {
   compiler->SetNeedsStacktrace(catch_try_index());
   __ Throw(1);
-  compiler->RecordSafepoint(locs());
   compiler->AddCurrentDescriptor(RawPcDescriptors::kOther,
                                  deopt_id(),
                                  token_pos());
+  compiler->RecordAfterCall(this);
   __ Trap();
 }
 
@@ -986,22 +1166,9 @@
 
 
 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);
-  }
+  __ CheckEitherNonSmi(left, right);
   compiler->EmitDeopt(deopt_id(), ICData::kDeoptBinaryDoubleOp,
                       licm_hoisted_ ? ICData::kHoisted : 0);
 }
@@ -1127,9 +1294,314 @@
       break;
     default:
       UNREACHABLE();
+      break;
   }
 }
 
+
+EMIT_NATIVE_CODE(Box, 1, Location::RequiresRegister(), LocationSummary::kCall) {
+  ASSERT(from_representation() == kUnboxedDouble);
+  const Register value = locs()->in(0).reg();
+  const Register out = locs()->out(0).reg();
+  const intptr_t kidx = __ AddConstant(compiler->double_class());
+  __ Allocate(kidx);
+  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther,
+                                 Thread::kNoDeoptId,
+                                 token_pos());
+  compiler->RecordSafepoint(locs());
+  // __ Allocate puts the box at the top of the stack.
+  __ WriteIntoDouble(out, value);
+}
+
+
+EMIT_NATIVE_CODE(Unbox, 1, Location::RequiresRegister()) {
+  ASSERT(representation() == kUnboxedDouble);
+  const intptr_t value_cid = value()->Type()->ToCid();
+  const intptr_t box_cid = BoxCid();
+  const Register box = locs()->in(0).reg();
+  const Register result = locs()->out(0).reg();
+  if (value_cid == box_cid) {
+    __ UnboxDouble(result, box);
+  } else if (CanConvertSmi() && (value_cid == kSmiCid)) {
+    __ SmiToDouble(result, box);
+  } else if ((value()->Type()->ToNullableCid() == box_cid) &&
+              value()->Type()->is_nullable()) {
+    __ IfEqNull(box);
+    compiler->EmitDeopt(GetDeoptId(), ICData::kDeoptCheckClass);
+    __ UnboxDouble(result, box);
+  } else {
+    __ CheckedUnboxDouble(result, box);
+    compiler->EmitDeopt(GetDeoptId(), ICData::kDeoptCheckClass);
+  }
+}
+
+
+EMIT_NATIVE_CODE(DoubleToSmi, 1, Location::RequiresRegister()) {
+  const Register value = locs()->in(0).reg();
+  const Register result = locs()->out(0).reg();
+  __ DoubleToSmi(result, value);
+  compiler->EmitDeopt(deopt_id(), ICData::kDeoptDoubleToSmi);
+}
+
+
+EMIT_NATIVE_CODE(SmiToDouble, 1, Location::RequiresRegister()) {
+  const Register value = locs()->in(0).reg();
+  const Register result = locs()->out(0).reg();
+  __ SmiToDouble(result, value);
+}
+
+
+EMIT_NATIVE_CODE(BinaryDoubleOp, 2, Location::RequiresRegister()) {
+  const Register left = locs()->in(0).reg();
+  const Register right = locs()->in(1).reg();
+  const Register result = locs()->out(0).reg();
+  switch (op_kind()) {
+    case Token::kADD: __ DAdd(result, left, right); break;
+    case Token::kSUB: __ DSub(result, left, right); break;
+    case Token::kMUL: __ DMul(result, left, right); break;
+    case Token::kDIV: __ DDiv(result, left, right); break;
+    default: UNREACHABLE();
+  }
+}
+
+
+EMIT_NATIVE_CODE(UnaryDoubleOp, 1, Location::RequiresRegister()) {
+  const Register value = locs()->in(0).reg();
+  const Register result = locs()->out(0).reg();
+  __ DNeg(result, value);
+}
+
+
+EMIT_NATIVE_CODE(MathUnary, 1, Location::RequiresRegister()) {
+  const Register value = locs()->in(0).reg();
+  const Register result = locs()->out(0).reg();
+  if (kind() == MathUnaryInstr::kSqrt) {
+    __ DSqrt(result, value);
+  } else if (kind() == MathUnaryInstr::kDoubleSquare) {
+    __ DMul(result, value, value);
+  } else if (kind() == MathUnaryInstr::kSin) {
+    __ DSin(result, value);
+  } else if (kind() == MathUnaryInstr::kCos) {
+    __ DCos(result, value);
+  } else {
+    Unsupported(compiler);
+    UNREACHABLE();
+  }
+}
+
+
+EMIT_NATIVE_CODE(InvokeMathCFunction,
+                 InputCount(), Location::RequiresRegister()) {
+  const Register left = locs()->in(0).reg();
+  const Register result = locs()->out(0).reg();
+  if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
+    const Register right = locs()->in(1).reg();
+    __ DPow(result, left, right);
+  } else if (recognized_kind() == MethodRecognizer::kDoubleMod) {
+    const Register right = locs()->in(1).reg();
+    __ DMod(result, left, right);
+  } else {
+    Unsupported(compiler);
+    UNREACHABLE();
+  }
+}
+
+
+EMIT_NATIVE_CODE(MathMinMax, 2, Location::RequiresRegister()) {
+  ASSERT((op_kind() == MethodRecognizer::kMathMin) ||
+         (op_kind() == MethodRecognizer::kMathMax));
+  const Register left = locs()->in(0).reg();
+  const Register right = locs()->in(1).reg();
+  const Register result = locs()->out(0).reg();
+  if (result_cid() == kDoubleCid) {
+    if (op_kind() == MethodRecognizer::kMathMin) {
+      __ DMin(result, left, right);
+    } else {
+      __ DMax(result, left, right);
+    }
+  } else {
+    ASSERT(result_cid() == kSmiCid);
+    if (op_kind() == MethodRecognizer::kMathMin) {
+      __ Min(result, left, right);
+    } else {
+      __ Max(result, left, right);
+    }
+  }
+}
+
+
+static Token::Kind FlipCondition(Token::Kind kind) {
+  switch (kind) {
+    case Token::kEQ: return Token::kNE;
+    case Token::kNE: return Token::kEQ;
+    case Token::kLT: return Token::kGTE;
+    case Token::kGT: return Token::kLTE;
+    case Token::kLTE: return Token::kGT;
+    case Token::kGTE: return Token::kLT;
+    default:
+      UNREACHABLE();
+      return Token::kNE;
+  }
+}
+
+
+static Bytecode::Opcode OpcodeForSmiCondition(Token::Kind kind) {
+  switch (kind) {
+    case Token::kEQ: return Bytecode::kIfEqStrict;
+    case Token::kNE: return Bytecode::kIfNeStrict;
+    case Token::kLT: return Bytecode::kIfLt;
+    case Token::kGT: return Bytecode::kIfGt;
+    case Token::kLTE: return Bytecode::kIfLe;
+    case Token::kGTE: return Bytecode::kIfGe;
+    default:
+      UNREACHABLE();
+      return Bytecode::kTrap;
+  }
+}
+
+
+static Bytecode::Opcode OpcodeForDoubleCondition(Token::Kind kind) {
+  switch (kind) {
+    case Token::kEQ: return Bytecode::kIfDEq;
+    case Token::kNE: return Bytecode::kIfDNe;
+    case Token::kLT: return Bytecode::kIfDLt;
+    case Token::kGT: return Bytecode::kIfDGt;
+    case Token::kLTE: return Bytecode::kIfDLe;
+    case Token::kGTE: return Bytecode::kIfDGe;
+    default:
+      UNREACHABLE();
+      return Bytecode::kTrap;
+  }
+}
+
+
+static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler,
+                                     LocationSummary* locs,
+                                     Token::Kind kind,
+                                     BranchLabels labels) {
+  const Register left = locs->in(0).reg();
+  const Register right = locs->in(1).reg();
+  Token::Kind comparison = kind;
+  Condition condition = NEXT_IS_TRUE;
+  if (labels.fall_through != labels.false_label) {
+    // If we aren't falling through to the false label, we can save a Jump
+    // instruction in the case that the true case is the fall through by
+    // flipping the sense of the test such that the instruction following the
+    // test is the Jump to the false label.
+    condition = NEXT_IS_FALSE;
+    comparison = FlipCondition(kind);
+  }
+  __ Emit(Bytecode::Encode(OpcodeForSmiCondition(comparison), left, right));
+  return condition;
+}
+
+
+static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
+                                        LocationSummary* locs,
+                                        Token::Kind kind,
+                                        BranchLabels labels) {
+  const Register left = locs->in(0).reg();
+  const Register right = locs->in(1).reg();
+  Token::Kind comparison = kind;
+  Condition condition = NEXT_IS_TRUE;
+  if (labels.fall_through != labels.false_label) {
+    // If we aren't falling through to the false label, we can save a Jump
+    // instruction in the case that the true case is the fall through by
+    // flipping the sense of the test such that the instruction following the
+    // test is the Jump to the false label.
+    condition = NEXT_IS_FALSE;
+    comparison = FlipCondition(kind);
+  }
+  __ Emit(Bytecode::Encode(OpcodeForDoubleCondition(comparison), left, right));
+  return condition;
+}
+
+
+Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+                                                   BranchLabels labels) {
+  if (operation_cid() == kSmiCid) {
+    return EmitSmiComparisonOp(compiler, locs(), kind(), labels);
+  } else {
+    ASSERT(operation_cid() == kDoubleCid);
+    return EmitDoubleComparisonOp(compiler, locs(), kind(), labels);
+  }
+}
+
+
+EMIT_NATIVE_CODE(EqualityCompare, 2, Location::RequiresRegister()) {
+  ASSERT(compiler->is_optimizing());
+  ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE));
+  Label is_true, is_false;
+  // These labels are not used. They are arranged so that EmitComparisonCode
+  // emits a test that executes the following instruction when the test
+  // succeeds.
+  BranchLabels labels = { &is_true, &is_false, &is_false };
+  const Register result = locs()->out(0).reg();
+  __ LoadConstant(result, Bool::False());
+  Condition true_condition = EmitComparisonCode(compiler, labels);
+  ASSERT(true_condition == NEXT_IS_TRUE);
+  __ LoadConstant(result, Bool::True());
+}
+
+
+void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
+                                          BranchInstr* branch) {
+  ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
+  BranchLabels labels = compiler->CreateBranchLabels(branch);
+  Condition true_condition = EmitComparisonCode(compiler, labels);
+  EmitBranchOnCondition(compiler, true_condition, labels);
+}
+
+
+Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+                                                BranchLabels labels) {
+  if (operation_cid() == kSmiCid) {
+    return EmitSmiComparisonOp(compiler, locs(), kind(), labels);
+  } else {
+    ASSERT(operation_cid() == kDoubleCid);
+    return EmitDoubleComparisonOp(compiler, locs(), kind(), labels);
+  }
+}
+
+
+EMIT_NATIVE_CODE(RelationalOp, 2, Location::RequiresRegister()) {
+  ASSERT(compiler->is_optimizing());
+  Label is_true, is_false;
+  BranchLabels labels = { &is_true, &is_false, &is_false };
+  const Register result = locs()->out(0).reg();
+  __ LoadConstant(result, Bool::False());
+  Condition true_condition = EmitComparisonCode(compiler, labels);
+  ASSERT(true_condition == NEXT_IS_TRUE);
+  __ LoadConstant(result, Bool::True());
+}
+
+
+void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
+                                       BranchInstr* branch) {
+  BranchLabels labels = compiler->CreateBranchLabels(branch);
+  Condition true_condition = EmitComparisonCode(compiler, labels);
+  EmitBranchOnCondition(compiler, true_condition, labels);
+}
+
+
+EMIT_NATIVE_CODE(CheckArrayBound, 2) {
+  const Register length = locs()->in(kLengthPos).reg();
+  const Register index = locs()->in(kIndexPos).reg();
+  const intptr_t index_cid = this->index()->Type()->ToCid();
+  if (index_cid != kSmiCid) {
+    __ CheckSmi(index);
+    compiler->EmitDeopt(deopt_id(),
+                        ICData::kDeoptCheckArrayBound,
+                        (generalized_ ? ICData::kGeneralized : 0) |
+                        (licm_hoisted_ ? ICData::kHoisted : 0));
+  }
+  __ IfULe(length, index);
+  compiler->EmitDeopt(deopt_id(),
+                      ICData::kDeoptCheckArrayBound,
+                      (generalized_ ? ICData::kGeneralized : 0) |
+                      (licm_hoisted_ ? ICData::kHoisted : 0));
+}
+
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 34555dc..3ccb078 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -5847,8 +5847,7 @@
   Label* deopt = compiler->AddDeoptStub(deopt_id(),
                                         ICData::kDeoptCheckSmi,
                                         licm_hoisted_ ? ICData::kHoisted : 0);
-  __ testl(value, Immediate(kSmiTagMask));
-  __ j(NOT_ZERO, deopt);
+  __ BranchIfNotSmi(value, deopt);
 }
 
 
@@ -5871,6 +5870,20 @@
 }
 
 
+LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone,
+                                                             bool opt) const {
+  // Only needed for AOT.
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  // Only needed for AOT.
+  UNIMPLEMENTED();
+}
+
+
 // Length: register or constant.
 // Index: register, constant or stack slot.
 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone,
@@ -5910,8 +5923,12 @@
     return;
   }
 
+  const intptr_t index_cid = index()->Type()->ToCid();
   if (length_loc.IsConstant()) {
     Register index = index_loc.reg();
+    if (index_cid != kSmiCid) {
+      __ BranchIfNotSmi(index, deopt);
+    }
     const Smi& length = Smi::Cast(length_loc.constant());
     if (length.Value() == Smi::kMaxValue) {
       __ testl(index, index);
@@ -5933,11 +5950,17 @@
   } else if (length_loc.IsStackSlot()) {
     Register index = index_loc.reg();
     const Address& length = length_loc.ToStackSlotAddress();
+    if (index_cid != kSmiCid) {
+      __ BranchIfNotSmi(index, deopt);
+    }
     __ cmpl(index, length);
     __ j(ABOVE_EQUAL, deopt);
   } else {
     Register index = index_loc.reg();
     Register length = length_loc.reg();
+    if (index_cid != kSmiCid) {
+      __ BranchIfNotSmi(index, deopt);
+    }
     __ cmpl(length, index);
     __ j(BELOW_EQUAL, deopt);
   }
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 342e267..645273f 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -4836,8 +4836,7 @@
   Label* deopt = compiler->AddDeoptStub(deopt_id(),
                                         ICData::kDeoptCheckSmi,
                                         licm_hoisted_ ? ICData::kHoisted : 0);
-  __ andi(CMPRES1, value, Immediate(kSmiTagMask));
-  __ bne(CMPRES1, ZR, deopt);
+  __ BranchIfNotSmi(value, deopt);
 }
 
 
@@ -4859,6 +4858,64 @@
 }
 
 
+LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone,
+                                                             bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs = new(zone) LocationSummary(
+      zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
+  locs->set_in(kLengthPos, Location::RequiresRegister());
+  locs->set_in(kIndexPos, Location::RequiresRegister());
+  return locs;
+}
+
+
+class RangeErrorSlowPath : public SlowPathCode {
+ public:
+  RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index)
+      : instruction_(instruction), try_index_(try_index) { }
+
+  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    if (Assembler::EmittingComments()) {
+      __ Comment("slow path check bound operation");
+    }
+    __ Bind(entry_label());
+    LocationSummary* locs = instruction_->locs();
+    __ Push(locs->in(0).reg());
+    __ Push(locs->in(1).reg());
+    __ CallRuntime(kRangeErrorRuntimeEntry, 2);
+    compiler->pc_descriptors_list()->AddDescriptor(
+        RawPcDescriptors::kOther,
+        compiler->assembler()->CodeSize(),
+        instruction_->deopt_id(),
+        instruction_->token_pos(),
+        try_index_);
+    __ break_(0);
+  }
+
+ private:
+  GenericCheckBoundInstr* instruction_;
+  intptr_t try_index_;
+};
+
+
+void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  RangeErrorSlowPath* slow_path =
+      new RangeErrorSlowPath(this, compiler->CurrentTryIndex());
+  compiler->AddSlowPathCode(slow_path);
+
+  Location length_loc = locs()->in(kLengthPos);
+  Location index_loc = locs()->in(kIndexPos);
+  Register length = length_loc.reg();
+  Register index = index_loc.reg();
+  const intptr_t index_cid = this->index()->Type()->ToCid();
+  if (index_cid != kSmiCid) {
+    __ BranchIfNotSmi(index, slow_path->entry_label());
+  }
+  __ BranchUnsignedGreaterEqual(index, length, slow_path->entry_label());
+}
+
+
 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone,
                                                            bool opt) const {
   const intptr_t kNumInputs = 2;
@@ -4892,6 +4949,7 @@
     return;
   }
 
+  const intptr_t index_cid = index()->Type()->ToCid();
   if (index_loc.IsConstant()) {
     Register length = length_loc.reg();
     const Smi& index = Smi::Cast(index_loc.constant());
@@ -4900,6 +4958,9 @@
   } else if (length_loc.IsConstant()) {
     const Smi& length = Smi::Cast(length_loc.constant());
     Register index = index_loc.reg();
+    if (index_cid != kSmiCid) {
+      __ BranchIfNotSmi(index, deopt);
+    }
     if (length.Value() == Smi::kMaxValue) {
       __ BranchSignedLess(index, Immediate(0), deopt);
     } else {
@@ -4909,6 +4970,9 @@
   } else {
     Register length = length_loc.reg();
     Register index = index_loc.reg();
+    if (index_cid != kSmiCid) {
+      __ BranchIfNotSmi(index, deopt);
+    }
     __ BranchUnsignedGreaterEqual(index, length, deopt);
   }
 }
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index da4b4c2..c908d1e 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -5697,8 +5697,7 @@
   Label* deopt = compiler->AddDeoptStub(deopt_id(),
                                         ICData::kDeoptCheckSmi,
                                         licm_hoisted_ ? ICData::kHoisted : 0);
-  __ testq(value, Immediate(kSmiTagMask));
-  __ j(NOT_ZERO, deopt);
+  __ BranchIfNotSmi(value, deopt);
 }
 
 
@@ -5721,6 +5720,66 @@
 }
 
 
+LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone,
+                                                             bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs = new(zone) LocationSummary(
+      zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
+  locs->set_in(kLengthPos, Location::RequiresRegister());
+  locs->set_in(kIndexPos, Location::RequiresRegister());
+  return locs;
+}
+
+
+class RangeErrorSlowPath : public SlowPathCode {
+ public:
+  RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index)
+      : instruction_(instruction), try_index_(try_index) { }
+
+  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    if (Assembler::EmittingComments()) {
+      __ Comment("slow path check bound operation");
+    }
+    __ Bind(entry_label());
+    LocationSummary* locs = instruction_->locs();
+    __ pushq(locs->in(0).reg());
+    __ pushq(locs->in(1).reg());
+    __ CallRuntime(kRangeErrorRuntimeEntry, 2);
+    compiler->pc_descriptors_list()->AddDescriptor(
+        RawPcDescriptors::kOther,
+        compiler->assembler()->CodeSize(),
+        instruction_->deopt_id(),
+        instruction_->token_pos(),
+        try_index_);
+    compiler->RecordSafepoint(locs, 2);
+    __ int3();
+  }
+
+ private:
+  GenericCheckBoundInstr* instruction_;
+  intptr_t try_index_;
+};
+
+
+void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  RangeErrorSlowPath* slow_path =
+      new RangeErrorSlowPath(this, compiler->CurrentTryIndex());
+  compiler->AddSlowPathCode(slow_path);
+
+  Location length_loc = locs()->in(kLengthPos);
+  Location index_loc = locs()->in(kIndexPos);
+  Register length = length_loc.reg();
+  Register index = index_loc.reg();
+  const intptr_t index_cid = this->index()->Type()->ToCid();
+  if (index_cid != kSmiCid) {
+    __ BranchIfNotSmi(index, slow_path->entry_label());
+  }
+  __ cmpq(index, length);
+  __ j(ABOVE_EQUAL, slow_path->entry_label());
+}
+
+
 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone,
                                                            bool opt) const {
   const intptr_t kNumInputs = 2;
@@ -5754,6 +5813,7 @@
     return;
   }
 
+  const intptr_t index_cid = index()->Type()->ToCid();
   if (index_loc.IsConstant()) {
     Register length = length_loc.reg();
     const Smi& index = Smi::Cast(index_loc.constant());
@@ -5763,6 +5823,9 @@
   } else if (length_loc.IsConstant()) {
     const Smi& length = Smi::Cast(length_loc.constant());
     Register index = index_loc.reg();
+    if (index_cid != kSmiCid) {
+      __ BranchIfNotSmi(index, deopt);
+    }
     if (length.Value() == Smi::kMaxValue) {
       __ testq(index, index);
       __ j(NEGATIVE, deopt);
@@ -5774,6 +5837,9 @@
   } else {
     Register length = length_loc.reg();
     Register index = index_loc.reg();
+    if (index_cid != kSmiCid) {
+      __ BranchIfNotSmi(index, deopt);
+    }
     __ cmpq(index, length);
     __ j(ABOVE_EQUAL, deopt);
   }
diff --git a/runtime/vm/intrinsifier.cc b/runtime/vm/intrinsifier.cc
index 9e049d0..15a0fa9 100644
--- a/runtime/vm/intrinsifier.cc
+++ b/runtime/vm/intrinsifier.cc
@@ -373,12 +373,6 @@
                              Definition* array,
                              Definition* index,
                              intptr_t length_offset) {
-  TokenPosition token_pos = builder->TokenPos();
-  builder->AddInstruction(
-      new CheckSmiInstr(new Value(index),
-                        Thread::kNoDeoptId,
-                        token_pos));
-
   Definition* length = builder->AddDefinition(
       new LoadFieldInstr(new Value(array),
                          length_offset,
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index eee6d04..697aef8 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -45,6 +45,7 @@
 #include "vm/timeline.h"
 #include "vm/timeline_analysis.h"
 #include "vm/timer.h"
+#include "vm/verifier.h"
 #include "vm/visitor.h"
 
 
@@ -53,9 +54,14 @@
 DECLARE_FLAG(bool, print_metrics);
 DECLARE_FLAG(bool, timing);
 DECLARE_FLAG(bool, trace_service);
-DECLARE_FLAG(bool, trace_reload);
 DECLARE_FLAG(bool, warn_on_pause_with_no_debugger);
+
+// Reload flags.
 DECLARE_FLAG(bool, check_reloaded);
+DECLARE_FLAG(int, reload_every);
+DECLARE_FLAG(bool, reload_every_back_off);
+DECLARE_FLAG(bool, trace_reload);
+
 
 NOT_IN_PRODUCT(
 static void CheckedModeHandler(bool value) {
@@ -202,8 +208,10 @@
   const char* name() const;
   void MessageNotify(Message::Priority priority);
   MessageStatus HandleMessage(Message* message);
+#ifndef PRODUCT
   void NotifyPauseOnStart();
   void NotifyPauseOnExit();
+#endif  // !PRODUCT
 
 #if defined(DEBUG)
   // Check that it is safe to access this handler.
@@ -570,6 +578,7 @@
     }
   }
   delete message;
+#ifndef PRODUCT
   if (status == kOK) {
     const Object& result =
         Object::Handle(zone, I->InvokePendingServiceExtensionCalls());
@@ -579,10 +588,12 @@
       ASSERT(result.IsNull());
     }
   }
+#endif  // !PRODUCT
   return status;
 }
 
 
+#ifndef PRODUCT
 void IsolateMessageHandler::NotifyPauseOnStart() {
   if (!FLAG_support_service) {
     return;
@@ -615,6 +626,7 @@
               I->name());
   }
 }
+#endif  // !PRODUCT
 
 
 #if defined(DEBUG)
@@ -833,6 +845,7 @@
       spawn_count_(0),
       has_attempted_reload_(false),
       no_reload_scope_depth_(0),
+      reload_every_n_stack_overflow_checks_(FLAG_reload_every),
       reload_context_(NULL) {
   NOT_IN_PRODUCT(FlagsCopyFrom(api_flags));
   // TODO(asiva): A Thread is not available here, need to figure out
@@ -851,9 +864,11 @@
   delete heap_;
   delete object_store_;
   delete api_state_;
+#ifndef PRODUCT
   if (FLAG_support_debugger) {
     delete debugger_;
   }
+#endif  // !PRODUCT
 #if defined(USING_SIMULATOR)
   delete simulator_;
 #endif
@@ -871,9 +886,11 @@
   message_handler_ = NULL;  // Fail fast if we send messages to a dead isolate.
   ASSERT(deopt_context_ == NULL);  // No deopt in progress when isolate deleted.
   delete spawn_state_;
+#ifndef PRODUCT
   if (FLAG_support_service) {
     delete object_id_ring_;
   }
+#endif  // !PRODUCT
   object_id_ring_ = NULL;
   delete pause_loop_monitor_;
   pause_loop_monitor_ = NULL;
@@ -954,9 +971,11 @@
     }
   }
 
+#ifndef PRODUCT
   if (FLAG_support_service) {
     ObjectIdRing::Init(result);
   }
+#endif  // !PRODUCT
 
   // Add to isolate list. Shutdown and delete the isolate on failure.
   if (!AddIsolateToList(result)) {
@@ -1054,8 +1073,9 @@
 
 bool Isolate::CanReload() const {
 #ifndef PRODUCT
-  return (!ServiceIsolate::IsServiceIsolateDescendant(this) &&
-          is_runnable() && !IsReloading() && no_reload_scope_depth_ == 0);
+  return !ServiceIsolate::IsServiceIsolateDescendant(this) &&
+         is_runnable() && !IsReloading() && (no_reload_scope_depth_ == 0) &&
+         IsolateCreationEnabled();
 #else
   return false;
 #endif
@@ -1066,39 +1086,42 @@
 void Isolate::ReportReloadError(const Error& error) {
   ASSERT(IsReloading());
   reload_context_->AbortReload(error);
+}
+
+
+void Isolate::ReloadSources(bool dont_delete_reload_context) {
+  // TODO(asiva): Add verification of canonical objects.
+  ASSERT(!IsReloading());
+  has_attempted_reload_ = true;
+  reload_context_ = new IsolateReloadContext(this);
+  reload_context_->StartReload();
+  // TODO(asiva): Add verification of canonical objects.
+  if (dont_delete_reload_context) {
+    // Unit tests use the reload context later. Caller is responsible
+    // for deleting the context.
+    return;
+  }
+  DeleteReloadContext();
+}
+
+
+void Isolate::DeleteReloadContext() {
   delete reload_context_;
   reload_context_ = NULL;
 }
-
-
-void Isolate::ReloadSources(bool test_mode) {
-  ASSERT(!IsReloading());
-  has_attempted_reload_ = true;
-  reload_context_ = new IsolateReloadContext(this, test_mode);
-  reload_context_->StartReload();
-}
-
-#endif
+#endif  // !PRODUCT
 
 
 void Isolate::DoneFinalizing() {
   NOT_IN_PRODUCT(
     if (IsReloading()) {
       reload_context_->FinishReload();
-      if (reload_context_->has_error() && reload_context_->test_mode()) {
-        // If the reload has an error and we are in test mode keep the reload
-        // 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()) {
+      } else {
         reload_context_->ReportSuccess();
       }
-      delete reload_context_;
-      reload_context_ = NULL;
     }
   )
 }
@@ -1117,11 +1140,13 @@
   // isolate on thread pool for execution.
   ASSERT(object_store()->root_library() != Library::null());
   set_is_runnable(true);
+#ifndef PRODUCT
   if (FLAG_support_debugger && !ServiceIsolate::IsServiceIsolate(this)) {
     if (FLAG_pause_isolates_on_unhandled_exceptions) {
       debugger()->SetExceptionPauseInfo(kPauseOnUnhandledExceptions);
     }
   }
+#endif  // !PRODUCT
   IsolateSpawnState* state = spawn_state();
   if (state != NULL) {
     ASSERT(this == state->isolate());
@@ -1137,11 +1162,11 @@
       event->Complete();
     }
   }
-#endif  // !PRODUCT
   if (FLAG_support_service && Service::isolate_stream.enabled()) {
     ServiceEvent runnableEvent(this, ServiceEvent::kIsolateRunnable);
     Service::HandleEvent(&runnableEvent);
   }
+#endif  // !PRODUCT
   return true;
 }
 
@@ -1472,6 +1497,13 @@
     ASSERT(thread->isolate() == isolate);
     StackZone zone(thread);
     HandleScope handle_scope(thread);
+#if defined(DEBUG)
+    if (!isolate->HasAttemptedReload()) {
+      isolate->heap()->CollectAllGarbage();
+      VerifyCanonicalVisitor check_canonical(thread);
+      isolate->heap()->IterateObjects(&check_canonical);
+    }
+#endif  // DEBUG
     const Error& error = Error::Handle(thread->sticky_error());
     if (!error.IsNull() && !error.IsUnwindError()) {
       OS::PrintErr("in ShutdownIsolate: %s\n", error.ToErrorCString());
@@ -1624,13 +1656,13 @@
   }
   if (FLAG_print_metrics) {
     LogBlock lb;
-    THR_Print("Printing metrics for %s\n", name());
+    OS::PrintErr("Printing metrics for %s\n", name());
 #define ISOLATE_METRIC_PRINT(type, variable, name, unit)                       \
-  THR_Print("%s\n", metric_##variable##_.ToString());
+  OS::PrintErr("%s\n", metric_##variable##_.ToString());
 
     ISOLATE_METRIC_LIST(ISOLATE_METRIC_PRINT);
 #undef ISOLATE_METRIC_PRINT
-    THR_Print("\n");
+    OS::PrintErr("\n");
   }
 }
 
@@ -1643,6 +1675,21 @@
 }
 
 
+void Isolate::MaybeIncreaseReloadEveryNStackOverflowChecks() {
+  if (FLAG_reload_every_back_off) {
+    if (reload_every_n_stack_overflow_checks_ < 5000) {
+      reload_every_n_stack_overflow_checks_ += 99;
+    } else {
+      reload_every_n_stack_overflow_checks_ *= 2;
+    }
+    // Cap the value.
+    if (reload_every_n_stack_overflow_checks_ > 1000000) {
+      reload_every_n_stack_overflow_checks_ = 1000000;
+    }
+  }
+}
+
+
 void Isolate::Shutdown() {
   ASSERT(this == Isolate::Current());
   StopBackgroundCompiler();
@@ -1697,7 +1744,7 @@
     }
   }
 
-  if (FLAG_check_reloaded &&
+  if (FLAG_check_reloaded && is_runnable() &&
       (this != Dart::vm_isolate()) &&
       !ServiceIsolate::IsServiceIsolateDescendant(this)) {
     if (!HasAttemptedReload()) {
@@ -1893,36 +1940,35 @@
   jsobj.AddProperty("pauseOnExit", message_handler()->should_pause_on_exit());
   jsobj.AddProperty("_isReloading", IsReloading());
 
-  if (debugger() != NULL) {
-    if (!is_runnable()) {
-      // Isolate is not yet runnable.
-      ASSERT(debugger()->PauseEvent() == NULL);
-      ServiceEvent pause_event(this, ServiceEvent::kNone);
-      jsobj.AddProperty("pauseEvent", &pause_event);
-    } else if (message_handler()->is_paused_on_start() ||
-               message_handler()->should_pause_on_start()) {
-      ASSERT(debugger()->PauseEvent() == NULL);
-      ServiceEvent pause_event(this, ServiceEvent::kPauseStart);
-      jsobj.AddProperty("pauseEvent", &pause_event);
-    } else if (message_handler()->is_paused_on_exit()) {
-      ASSERT(debugger()->PauseEvent() == NULL);
-      ServiceEvent pause_event(this, ServiceEvent::kPauseExit);
-      jsobj.AddProperty("pauseEvent", &pause_event);
-    } else if (debugger()->PauseEvent() != NULL && !resume_request_) {
-      jsobj.AddProperty("pauseEvent", debugger()->PauseEvent());
-    } else {
-      ServiceEvent pause_event(this, ServiceEvent::kResume);
+  if (!is_runnable()) {
+    // Isolate is not yet runnable.
+    ASSERT((debugger() == NULL) || (debugger()->PauseEvent() == NULL));
+    ServiceEvent pause_event(this, ServiceEvent::kNone);
+    jsobj.AddProperty("pauseEvent", &pause_event);
+  } else if (message_handler()->is_paused_on_start() ||
+             message_handler()->should_pause_on_start()) {
+    ASSERT((debugger() == NULL) || (debugger()->PauseEvent() == NULL));
+    ServiceEvent pause_event(this, ServiceEvent::kPauseStart);
+    jsobj.AddProperty("pauseEvent", &pause_event);
+  } else if (message_handler()->is_paused_on_exit()) {
+    ASSERT((debugger() == NULL) || (debugger()->PauseEvent() == NULL));
+    ServiceEvent pause_event(this, ServiceEvent::kPauseExit);
+    jsobj.AddProperty("pauseEvent", &pause_event);
+  } else if ((debugger() != NULL) &&
+             (debugger()->PauseEvent() != NULL) &&
+             !resume_request_) {
+    jsobj.AddProperty("pauseEvent", debugger()->PauseEvent());
+  } else {
+    ServiceEvent pause_event(this, ServiceEvent::kResume);
 
+    if (debugger() != NULL) {
       // TODO(turnidge): Don't compute a full stack trace.
       DebuggerStackTrace* stack = debugger()->StackTrace();
       if (stack->Length() > 0) {
         pause_event.set_top_frame(stack->FrameAt(0));
       }
-      jsobj.AddProperty("pauseEvent", &pause_event);
     }
-
-    jsobj.AddProperty("exceptionPauseMode",
-        ExceptionPauseInfoToServiceEnum(debugger()->GetExceptionPauseInfo()));
+    jsobj.AddProperty("pauseEvent", &pause_event);
   }
 
   const Library& lib =
@@ -1959,16 +2005,22 @@
     }
   }
 
-  if (debugger() != NULL) {
-    {
-      JSONArray breakpoints(&jsobj, "breakpoints");
+  {
+    JSONArray breakpoints(&jsobj, "breakpoints");
+    if (debugger() != NULL) {
       debugger()->PrintBreakpointsToJSONArray(&breakpoints);
     }
+  }
 
-    {
-      JSONObject jssettings(&jsobj, "_debuggerSettings");
-      debugger()->PrintSettingsToJSONObject(&jssettings);
-    }
+  Dart_ExceptionPauseInfo pause_info = (debugger() != NULL)
+      ? debugger()->GetExceptionPauseInfo()
+      : kNoPauseOnExceptions;
+  jsobj.AddProperty("exceptionPauseMode",
+                    ExceptionPauseInfoToServiceEnum(pause_info));
+
+  if (debugger() != NULL) {
+    JSONObject settings(&jsobj, "_debuggerSettings");
+    debugger()->PrintSettingsToJSONObject(&settings);
   }
 
   {
@@ -2081,6 +2133,7 @@
 }
 
 
+#ifndef PRODUCT
 RawObject* Isolate::InvokePendingServiceExtensionCalls() {
   if (!FLAG_support_service) {
     return Object::null();
@@ -2261,6 +2314,7 @@
   }
   return Instance::null();
 }
+#endif  // !PRODUCT
 
 
 void Isolate::WakePauseEventHandler(Dart_Isolate isolate) {
@@ -2403,6 +2457,12 @@
 }
 
 
+bool Isolate::IsolateCreationEnabled() {
+  MonitorLocker ml(isolates_list_monitor_);
+  return creation_enabled_;
+}
+
+
 void Isolate::KillLocked(LibMsgId msg_id) {
   Dart_CObject kill_msg;
   Dart_CObject* list_values[4];
@@ -2527,7 +2587,7 @@
 
     // If a safepoint operation is in progress wait for it
     // to finish before scheduling this thread in.
-    while (!bypass_safepoint && safepoint_handler()->safepoint_in_progress()) {
+    while (!bypass_safepoint && safepoint_handler()->SafepointInProgress()) {
       ml.Wait();
     }
 
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 7f1df6d..b49d59b 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -255,7 +255,9 @@
   void DoneLoading();
   void DoneFinalizing();
 
-  void ReloadSources(bool test_mode = false);
+  // By default the reload context is deleted. This parameter allows
+  // the caller to delete is separately if it is still needed.
+  void ReloadSources(bool dont_delete_reload_context = false);
 
   bool MakeRunnable();
   void Run();
@@ -480,6 +482,8 @@
     return reload_context_;
   }
 
+  void DeleteReloadContext();
+
   bool HasAttemptedReload() const {
     return has_attempted_reload_;
   }
@@ -583,6 +587,7 @@
   // Returns Field::null() if none available in the list.
   RawField* GetDeoptimizingBoxedField();
 
+#ifndef PRODUCT
   RawObject* InvokePendingServiceExtensionCalls();
   void AppendServiceExtensionCall(const Instance& closure,
                            const String& method_name,
@@ -593,6 +598,7 @@
   void RegisterServiceExtensionHandler(const String& name,
                                        const Instance& closure);
   RawInstance* LookupServiceExtensionHandler(const String& name);
+#endif
 
   static void VisitIsolates(IsolateVisitor* visitor);
 
@@ -629,9 +635,16 @@
 
   static void DisableIsolateCreation();
   static void EnableIsolateCreation();
+  static bool IsolateCreationEnabled();
 
   void StopBackgroundCompiler();
 
+  intptr_t reload_every_n_stack_overflow_checks() const {
+    return reload_every_n_stack_overflow_checks_;
+  }
+
+  void MaybeIncreaseReloadEveryNStackOverflowChecks();
+
  private:
   friend class Dart;  // Init, InitOnce, Shutdown.
   friend class IsolateKillerVisitor;  // Kill().
@@ -815,6 +828,8 @@
   // Has a reload ever been attempted?
   bool has_attempted_reload_;
   intptr_t no_reload_scope_depth_;  // we can only reload when this is 0.
+  // Per-isolate copy of FLAG_reload_every.
+  intptr_t reload_every_n_stack_overflow_checks_;
   IsolateReloadContext* reload_context_;
 
 #define ISOLATE_METRIC_VARIABLE(type, variable, name, unit)                    \
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 15aaf29..158f655 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -24,6 +24,8 @@
 namespace dart {
 
 DEFINE_FLAG(bool, trace_reload, false, "Trace isolate reloading");
+DEFINE_FLAG(bool, trace_reload_verbose, false,
+            "trace isolate reloading verbose");
 DEFINE_FLAG(bool, identity_reload, false, "Enable checks for identity reload.");
 DEFINE_FLAG(int, reload_every, 0, "Reload every N stack overflow checks.");
 DEFINE_FLAG(bool, reload_every_optimized, true, "Only from optimized code.");
@@ -42,6 +44,152 @@
                                    #name)
 
 
+InstanceMorpher::InstanceMorpher(const Class& from, const Class& to)
+  : from_(from), to_(to), mapping_() {
+  ComputeMapping();
+  before_ = new ZoneGrowableArray<const Instance*>();
+  after_ = new ZoneGrowableArray<const Instance*>();
+  ASSERT(from_.id() == to_.id());
+  cid_ = from_.id();
+}
+
+
+void InstanceMorpher::AddObject(RawObject* object) const {
+  ASSERT(object->GetClassId() == cid());
+  const Instance& instance = Instance::Cast(Object::Handle(object));
+  before_->Add(&instance);
+}
+
+
+void InstanceMorpher::ComputeMapping() {
+  if (from_.NumTypeArguments()) {
+    // Add copying of the optional type argument field.
+    intptr_t from_offset = from_.type_arguments_field_offset();
+    ASSERT(from_offset != Class::kNoTypeArguments);
+    intptr_t to_offset = to_.type_arguments_field_offset();
+    ASSERT(to_offset != Class::kNoTypeArguments);
+    mapping_.Add(from_offset);
+    mapping_.Add(to_offset);
+  }
+
+  // Add copying of the instance fields if matching by name.
+  // Note: currently the type of the fields are ignored.
+  const Array& from_fields = Array::Handle(from_.OffsetToFieldMap());
+  const Array& to_fields = Array::Handle(to_.OffsetToFieldMap());
+  Field& from_field = Field::Handle();
+  Field& to_field = Field::Handle();
+  String& from_name = String::Handle();
+  String& to_name = String::Handle();
+  for (intptr_t i = 0; i < from_fields.Length(); i++) {
+    if (from_fields.At(i) == Field::null()) continue;  // Ignore non-fields.
+    from_field = Field::RawCast(from_fields.At(i));
+    ASSERT(from_field.is_instance());
+    from_name = from_field.name();
+    // We now have to find where this field is in the to class.
+    for (intptr_t j = 0; j < to_fields.Length(); j++) {
+      if (to_fields.At(j) == Field::null()) continue;  // Ignore non-fields.
+      to_field = Field::RawCast(to_fields.At(j));
+      ASSERT(to_field.is_instance());
+      to_name = to_field.name();
+      if (from_name.Equals(to_name)) {
+        // Success
+        mapping_.Add(from_field.Offset());
+        mapping_.Add(to_field.Offset());
+      }
+    }
+  }
+}
+
+
+RawInstance* InstanceMorpher::Morph(const Instance& instance) const {
+  const Instance& result = Instance::Handle(Instance::New(to_));
+  // Morph the context from instance to result using mapping_.
+  for (intptr_t i = 0; i < mapping_.length(); i +=2) {
+    intptr_t from_offset = mapping_.At(i);
+    intptr_t to_offset = mapping_.At(i+1);
+    const Object& value =
+        Object::Handle(instance.RawGetFieldAtOffset(from_offset));
+    result.RawSetFieldAtOffset(to_offset, value);
+  }
+  // Convert the instance into a filler object.
+  Become::MakeDummyObject(instance);
+  return result.raw();
+}
+
+
+void InstanceMorpher::CreateMorphedCopies() const {
+  for (intptr_t i = 0; i < before()->length(); i++) {
+    const Instance& copy = Instance::Handle(Morph(*before()->At(i)));
+    after()->Add(&copy);
+  }
+}
+
+
+void InstanceMorpher::DumpFormatFor(const Class& cls) const {
+  THR_Print("%s\n", cls.ToCString());
+  if (cls.NumTypeArguments()) {
+    intptr_t field_offset = cls.type_arguments_field_offset();
+    ASSERT(field_offset != Class::kNoTypeArguments);
+    THR_Print("  - @%" Pd " <type arguments>\n", field_offset);
+  }
+  const Array& fields = Array::Handle(cls.OffsetToFieldMap());
+  Field& field = Field::Handle();
+  String& name = String::Handle();
+  for (intptr_t i = 0; i < fields.Length(); i++) {
+    if (fields.At(i) != Field::null()) {
+      field = Field::RawCast(fields.At(i));
+      ASSERT(field.is_instance());
+      name = field.name();
+      THR_Print("  - @%" Pd " %s\n", field.Offset(), name.ToCString());
+    }
+  }
+
+  THR_Print("Mapping: ");
+  for (int i = 0; i < mapping_.length(); i +=2) {
+    THR_Print(" %" Pd "->%" Pd,  mapping_.At(i),  mapping_.At(i+1));
+  }
+  THR_Print("\n");
+}
+
+
+void InstanceMorpher::Dump() const {
+  LogBlock blocker;
+  THR_Print("Morphing from ");
+  DumpFormatFor(from_);
+  THR_Print("To ");
+  DumpFormatFor(to_);
+  THR_Print("\n");
+}
+
+
+void ReasonForCancelling::Report(IsolateReloadContext* context) {
+  const Error& error = Error::Handle(ToError());
+  context->ReportError(error);
+}
+
+
+RawError* ReasonForCancelling::ToError() {
+  // By default create the error returned from ToString.
+  const String& message = String::Handle(ToString());
+  return LanguageError::New(message);
+}
+
+
+RawString* ReasonForCancelling::ToString() {
+  UNREACHABLE();
+  return NULL;
+}
+
+
+RawError* IsolateReloadContext::error() const {
+  ASSERT(has_error());
+  // Report the first error to the surroundings.
+  const Error& error =
+      Error::Handle(reasons_to_cancel_reload_.At(0)->ToError());
+  OS::Print("[[%s]]\n", error.ToCString());
+  return error.raw();
+}
+
 class ScriptUrlSetTraits {
  public:
   static bool ReportStats() { return false; }
@@ -117,6 +265,8 @@
       return String::HashRawSymbol(Class::Cast(obj).Name());
     } else if (obj.IsField()) {
       return String::HashRawSymbol(Field::Cast(obj).name());
+    } else if (obj.IsInstance()) {
+      return Smi::Handle(Smi::RawCast(Instance::Cast(obj).HashCode())).Value();
     }
     return 0;
   }
@@ -173,28 +323,77 @@
 }
 
 
-IsolateReloadContext::IsolateReloadContext(Isolate* isolate, bool test_mode)
+IsolateReloadContext::IsolateReloadContext(Isolate* isolate)
     : start_time_micros_(OS::GetCurrentMonotonicMicros()),
       isolate_(isolate),
-      test_mode_(test_mode),
-      has_error_(false),
       saved_num_cids_(-1),
       saved_class_table_(NULL),
       num_saved_libs_(-1),
+      instance_morphers_(),
+      reasons_to_cancel_reload_(),
+      cid_mapper_(),
       script_uri_(String::null()),
       error_(Error::null()),
-      clean_scripts_set_storage_(Array::null()),
-      compile_time_constants_(Array::null()),
       old_classes_set_storage_(Array::null()),
       class_map_storage_(Array::null()),
       old_libraries_set_storage_(Array::null()),
       library_map_storage_(Array::null()),
       become_map_storage_(Array::null()),
+      become_enum_mappings_(GrowableObjectArray::null()),
       saved_root_library_(Library::null()),
       saved_libraries_(GrowableObjectArray::null()) {
+  // NOTE: DO NOT ALLOCATE ANY RAW OBJECTS HERE. The IsolateReloadContext is not
+  // associated with the isolate yet and if a GC is triggered here the raw
+  // objects will not be properly accounted for.
+}
+
+
+IsolateReloadContext::~IsolateReloadContext() {
+}
+
+
+void IsolateReloadContext::ReportError(const Error& error) {
+  if (FLAG_trace_reload) {
+    THR_Print("ISO-RELOAD: Error: %s\n", error.ToErrorCString());
+  }
+  ServiceEvent service_event(I, ServiceEvent::kIsolateReload);
+  service_event.set_reload_error(&error);
+  Service::HandleEvent(&service_event);
+}
+
+
+void IsolateReloadContext::ReportSuccess() {
+  ServiceEvent service_event(I, ServiceEvent::kIsolateReload);
+  Service::HandleEvent(&service_event);
+}
+
+
+class Aborted : public ReasonForCancelling {
+ public:
+  explicit Aborted(const Error& error)
+      : ReasonForCancelling(), error_(error) { }
+
+ private:
+  const Error& error_;
+
+  RawError* ToError() { return error_.raw(); }
+  RawString* ToString() {
+    return String::NewFormatted("%s", error_.ToErrorCString());
+  }
+};
+
+
+void IsolateReloadContext::StartReload() {
+  TIMELINE_SCOPE(Reload);
+  Thread* thread = Thread::Current();
+  ASSERT(isolate() == thread->isolate());
+
+  // Grab root library before calling CheckpointBeforeReload.
+  const Library& root_lib = Library::Handle(object_store()->root_library());
+  ASSERT(!root_lib.IsNull());
+  const String& root_lib_url = String::Handle(root_lib.url());
+
   // Preallocate storage for maps.
-  clean_scripts_set_storage_ =
-      HashTables::New<UnorderedHashSet<ScriptUrlSetTraits> >(4);
   old_classes_set_storage_ =
       HashTables::New<UnorderedHashSet<ClassMapTraits> >(4);
   class_map_storage_ =
@@ -205,44 +404,9 @@
       HashTables::New<UnorderedHashMap<LibraryMapTraits> >(4);
   become_map_storage_ =
       HashTables::New<UnorderedHashMap<BecomeMapTraits> >(4);
-}
-
-
-IsolateReloadContext::~IsolateReloadContext() {
-}
-
-
-void IsolateReloadContext::ReportError(const Error& error) {
-  has_error_ = true;
-  error_ = error.raw();
-  if (FLAG_trace_reload) {
-    THR_Print("ISO-RELOAD: Error: %s\n", error.ToErrorCString());
-  }
-  ServiceEvent service_event(I, ServiceEvent::kIsolateReload);
-  service_event.set_reload_error(&error);
-  Service::HandleEvent(&service_event);
-}
-
-
-void IsolateReloadContext::ReportError(const String& error_msg) {
-  ReportError(LanguageError::Handle(LanguageError::New(error_msg)));
-}
-
-
-void IsolateReloadContext::ReportSuccess() {
-  ServiceEvent service_event(I, ServiceEvent::kIsolateReload);
-  Service::HandleEvent(&service_event);
-}
-
-
-void IsolateReloadContext::StartReload() {
-  TIMELINE_SCOPE(Reload);
-  Thread* thread = Thread::Current();
-
-  // Grab root library before calling CheckpointBeforeReload.
-  const Library& root_lib = Library::Handle(object_store()->root_library());
-  ASSERT(!root_lib.IsNull());
-  const String& root_lib_url = String::Handle(root_lib.url());
+  // Keep a separate array for enum mappings to avoid having to invoke
+  // hashCode on the instances.
+  become_enum_mappings_ = GrowableObjectArray::New(Heap::kOld);
 
   // Disable the background compiler while we are performing the reload.
   BackgroundCompiler::Disable();
@@ -273,7 +437,8 @@
     result = Api::UnwrapHandle(retval);
   }
   if (result.IsError()) {
-    ReportError(Error::Cast(result));
+    const Error& error = Error::Cast(result);
+    AddReasonForCancelling(new Aborted(error));
   }
 }
 
@@ -311,6 +476,7 @@
     Commit();
     PostCommit();
   } else {
+    ReportReasonsForCancelling();
     Rollback();
   }
   // ValidateReload mutates the direct subclass information and does
@@ -328,7 +494,8 @@
 
 
 void IsolateReloadContext::AbortReload(const Error& error) {
-  ReportError(error);
+  AddReasonForCancelling(new Aborted(error));
+  ReportReasonsForCancelling();
   Rollback();
 }
 
@@ -476,86 +643,6 @@
 }
 
 
-void IsolateReloadContext::BuildCleanScriptSet() {
-  const GrowableObjectArray& libs =
-      GrowableObjectArray::Handle(object_store()->libraries());
-
-  UnorderedHashSet<ScriptUrlSetTraits>
-      clean_scripts_set(clean_scripts_set_storage_);
-
-  Library& lib = Library::Handle();
-  Array& scripts = Array::Handle();
-  Script& script = Script::Handle();
-  String& script_url = String::Handle();
-  for (intptr_t lib_idx = 0; lib_idx < libs.Length(); lib_idx++) {
-    lib = Library::RawCast(libs.At(lib_idx));
-    ASSERT(!lib.IsNull());
-    ASSERT(IsCleanLibrary(lib));
-    scripts = lib.LoadedScripts();
-    ASSERT(!scripts.IsNull());
-    for (intptr_t script_idx = 0; script_idx < scripts.Length(); script_idx++) {
-      script = Script::RawCast(scripts.At(script_idx));
-      ASSERT(!script.IsNull());
-      script_url = script.url();
-      ASSERT(!script_url.IsNull());
-      bool already_present = clean_scripts_set.Insert(script_url);
-      ASSERT(!already_present);
-    }
-  }
-
-  clean_scripts_set_storage_ = clean_scripts_set.Release().raw();
-}
-
-
-void IsolateReloadContext::FilterCompileTimeConstants() {
-  // Save the compile time constants array.
-  compile_time_constants_ = I->object_store()->compile_time_constants();
-  // Clear the compile time constants array. This will be repopulated
-  // in the loop below.
-  I->object_store()->set_compile_time_constants(Array::Handle());
-
-  if (compile_time_constants_ == Array::null()) {
-    // Nothing to do.
-    return;
-  }
-
-  // Iterate over the saved compile time constants map.
-  ConstantsMap old_constants(compile_time_constants_);
-  ConstantsMap::Iterator it(&old_constants);
-
-  Array& key = Array::Handle();
-  String& url = String::Handle();
-  Smi& token_pos = Smi::Handle();
-  Instance& value = Instance::Handle();
-
-  // We filter the compile time constants map so that after it only contains
-  // constants from scripts contained in this set.
-  UnorderedHashSet<ScriptUrlSetTraits>
-      clean_scripts_set(clean_scripts_set_storage_);
-
-  while (it.MoveNext()) {
-    const intptr_t entry = it.Current();
-    ASSERT(entry != -1);
-    key = Array::RawCast(old_constants.GetKey(entry));
-    ASSERT(!key.IsNull());
-    url = String::RawCast(key.At(0));
-    ASSERT(!url.IsNull());
-    if (clean_scripts_set.ContainsKey(url)) {
-      // We've found a cached constant from a clean script, add it to the
-      // compile time constants map again.
-      token_pos = Smi::RawCast(key.At(1));
-      TokenPosition tp(token_pos.Value());
-      // Use ^= because this might be null.
-      value ^= old_constants.GetPayload(entry, 0);
-      Parser::InsertCachedConstantValue(url, tp, value);
-    }
-  }
-
-  old_constants.Release();
-  clean_scripts_set.Release();
-}
-
-
 // While reloading everything we do must be reversible so that we can abort
 // safely if the reload fails. This function stashes things to the side and
 // prepares the isolate for the reload attempt.
@@ -563,8 +650,6 @@
   TIMELINE_SCOPE(Checkpoint);
   CheckpointClasses();
   CheckpointLibraries();
-  BuildCleanScriptSet();
-  FilterCompileTimeConstants();
 }
 
 
@@ -614,8 +699,6 @@
 
 
 void IsolateReloadContext::Rollback() {
-  I->object_store()->set_compile_time_constants(
-      Array::Handle(compile_time_constants_));
   RollbackClasses();
   RollbackLibraries();
 }
@@ -661,6 +744,15 @@
   TIMELINE_SCOPE(Commit);
   TIR_Print("---- COMMITTING REVERSE MAP\n");
 
+  // Note that the object heap contains before and after instances
+  // used for morphing. It is therefore important that morphing takes
+  // place prior to any heap walking.
+  // So please keep this code at the top of Commit().
+  if (HasInstanceMorphers()) {
+    // Perform shape shifting of instances if necessary.
+    MorphInstances();
+  }
+
 #ifdef DEBUG
   VerifyMaps();
 #endif
@@ -685,8 +777,9 @@
           ASSERT(new_cls.is_enum_class() == cls.is_enum_class());
           if (new_cls.is_enum_class() && new_cls.is_finalized()) {
             new_cls.ReplaceEnum(cls);
+          } else {
+            new_cls.CopyStaticFieldValues(cls);
           }
-          new_cls.CopyStaticFieldValues(cls);
           cls.PatchFieldsAndFunctions();
         }
       }
@@ -729,7 +822,7 @@
         I->object_store()->libraries());
     for (intptr_t i = 0; i < libs.Length(); i++) {
       lib = Library::RawCast(libs.At(i));
-      TIR_Print("Lib '%s' at index %" Pd "\n", lib.ToCString(), i);
+      VTIR_Print("Lib '%s' at index %" Pd "\n", lib.ToCString(), i);
       lib.set_index(i);
     }
 
@@ -743,8 +836,11 @@
   }
 
   {
+    const GrowableObjectArray& become_enum_mappings =
+        GrowableObjectArray::Handle(become_enum_mappings_);
     UnorderedHashMap<BecomeMapTraits> become_map(become_map_storage_);
-    intptr_t replacement_count = become_map.NumOccupied();
+    intptr_t replacement_count = become_map.NumOccupied() +
+                                 become_enum_mappings.Length() / 2;
     const Array& before =
         Array::Handle(Array::New(replacement_count, Heap::kOld));
     const Array& after =
@@ -760,6 +856,13 @@
       after.SetAt(replacement_index, obj);
       replacement_index++;
     }
+    for (intptr_t i = 0; i < become_enum_mappings.Length(); i += 2) {
+      obj = become_enum_mappings.At(i);
+      before.SetAt(replacement_index, obj);
+      obj = become_enum_mappings.At(i + 1);
+      after.SetAt(replacement_index, obj);
+      replacement_index++;
+    }
     ASSERT(replacement_index == replacement_count);
     become_map.Release();
 
@@ -801,34 +904,150 @@
   set_saved_root_library(Library::Handle());
   set_saved_libraries(GrowableObjectArray::Handle());
   InvalidateWorld();
+  TIR_Print("---- DONE COMMIT\n");
+}
+
+
+void IsolateReloadContext::AddReasonForCancelling(ReasonForCancelling* reason) {
+  reasons_to_cancel_reload_.Add(reason);
+}
+
+
+void IsolateReloadContext::AddInstanceMorpher(InstanceMorpher* morpher) {
+  instance_morphers_.Add(morpher);
+  cid_mapper_.Insert(morpher);
+}
+
+
+void IsolateReloadContext::ReportReasonsForCancelling() {
+  ASSERT(HasReasonsForCancelling());
+  for (int i = 0; i < reasons_to_cancel_reload_.length(); i++) {
+    reasons_to_cancel_reload_.At(i)->Report(this);
+  }
+}
+
+
+// The ObjectLocator is used for collecting instances that
+// needs to be morphed.
+class ObjectLocator : public ObjectVisitor {
+ public:
+  explicit ObjectLocator(IsolateReloadContext* context)
+      : context_(context), count_(0) {
+  }
+
+  void VisitObject(RawObject* obj) {
+    InstanceMorpher* morpher =
+        context_->cid_mapper_.LookupValue(obj->GetClassId());
+    if (morpher != NULL) {
+      morpher->AddObject(obj);
+      count_++;
+    }
+  }
+
+  // Return the number of located objects for morphing.
+  intptr_t count() { return count_; }
+
+ private:
+  IsolateReloadContext* context_;
+  intptr_t count_;
+};
+
+
+void IsolateReloadContext::MorphInstances() {
+  TIMELINE_SCOPE(MorphInstances);
+  ASSERT(HasInstanceMorphers());
+  if (FLAG_trace_reload) {
+    LogBlock blocker;
+    TIR_Print("MorphInstance: \n");
+    for (intptr_t i = 0; i < instance_morphers_.length(); i++) {
+      instance_morphers_.At(i)->Dump();
+    }
+  }
+
+  // Find all objects that need to be morphed.
+  ObjectLocator locator(this);
+  isolate()->heap()->VisitObjects(&locator);
+
+  // Return if no objects are located.
+  intptr_t count = locator.count();
+  if (count == 0) return;
+
+  TIR_Print("Found %" Pd " object%s subject to morphing.\n",
+            count, (count > 1) ? "s" : "");
+
+  Array& before = Array::Handle();
+  Array& after = Array::Handle();
+  { // Prevent GC to take place due object format confusion.
+    // Hint: More than one class share the same cid.
+    NoHeapGrowthControlScope scope;
+    for (intptr_t i = 0; i < instance_morphers_.length(); i++) {
+      instance_morphers_.At(i)->CreateMorphedCopies();
+    }
+    // Create the inputs for Become.
+    intptr_t index = 0;
+    before = Array::New(count);
+    after = Array::New(count);
+    for (intptr_t i = 0; i < instance_morphers_.length(); i++) {
+      InstanceMorpher* morpher = instance_morphers_.At(i);
+      for (intptr_t j = 0; j < morpher->before()->length(); j++) {
+        before.SetAt(index, *morpher->before()->At(j));
+        after.SetAt(index, *morpher->after()->At(j));
+        index++;
+      }
+    }
+    ASSERT(index == count);
+  }
+
+  // This is important: The saved class table (describing before objects)
+  // must be zapped to prevent the forwarding in GetClassForHeapWalkAt.
+  // Instance will from now be described by the isolate's class table.
+  free(saved_class_table_);
+  saved_class_table_ = NULL;
+  Become::ElementsForwardIdentity(before, after);
 }
 
 
 bool IsolateReloadContext::ValidateReload() {
   TIMELINE_SCOPE(ValidateReload);
-  if (has_error_) {
-    return false;
-  }
+  if (has_error()) return false;
 
-  // Already built.
-  ASSERT(class_map_storage_ != Array::null());
-  UnorderedHashMap<ClassMapTraits> map(class_map_storage_);
-  UnorderedHashMap<ClassMapTraits>::Iterator it(&map);
-  Class& cls = Class::Handle();
-  Class& new_cls = Class::Handle();
-  while (it.MoveNext()) {
-    const intptr_t entry = it.Current();
-    new_cls = Class::RawCast(map.GetKey(entry));
-    cls = Class::RawCast(map.GetPayload(entry, 0));
-    if (new_cls.raw() != cls.raw()) {
-      if (!cls.CanReload(new_cls)) {
-        map.Release();
-        return false;
+  // Validate libraries.
+  {
+    ASSERT(library_map_storage_ != Array::null());
+    UnorderedHashMap<LibraryMapTraits> map(library_map_storage_);
+    UnorderedHashMap<LibraryMapTraits>::Iterator it(&map);
+    Library& lib = Library::Handle();
+    Library& new_lib = Library::Handle();
+    while (it.MoveNext()) {
+      const intptr_t entry = it.Current();
+      new_lib = Library::RawCast(map.GetKey(entry));
+      lib = Library::RawCast(map.GetPayload(entry, 0));
+      if (new_lib.raw() != lib.raw()) {
+        lib.CheckReload(new_lib, this);
       }
     }
+    map.Release();
   }
-  map.Release();
-  return true;
+
+  // Validate classes.
+  {
+    ASSERT(class_map_storage_ != Array::null());
+    UnorderedHashMap<ClassMapTraits> map(class_map_storage_);
+    UnorderedHashMap<ClassMapTraits>::Iterator it(&map);
+    Class& cls = Class::Handle();
+    Class& new_cls = Class::Handle();
+    while (it.MoveNext()) {
+      const intptr_t entry = it.Current();
+      new_cls = Class::RawCast(map.GetKey(entry));
+      cls = Class::RawCast(map.GetPayload(entry, 0));
+      if (new_cls.raw() != cls.raw()) {
+        cls.CheckReload(new_cls, this);
+      }
+    }
+    map.Release();
+  }
+
+  return !HasReasonsForCancelling();
 }
 
 
@@ -950,6 +1169,8 @@
 
       if (!stub_code) {
         if (clear_code) {
+          VTIR_Print("Marking %s for recompilation, clearning code\n",
+              func.ToCString());
           ClearAllCode(func);
         } else {
           PreserveUnoptimizedCode();
@@ -995,6 +1216,7 @@
 
 void IsolateReloadContext::MarkAllFunctionsForRecompilation() {
   TIMELINE_SCOPE(MarkAllFunctionsForRecompilation);
+  TIR_Print("---- MARKING ALL FUNCTIONS FOR RECOMPILATION\n");
   NoSafepointScope no_safepoint;
   HeapIterationScope heap_iteration_scope;
   MarkFunctionsForRecompilation visitor(isolate_, this);
@@ -1003,6 +1225,7 @@
 
 
 void IsolateReloadContext::InvalidateWorld() {
+  TIR_Print("---- INVALIDATING WORLD\n");
   ResetMegamorphicCaches();
   DeoptimizeFunctionsOnStack();
   ResetUnoptimizedICsOnStack();
@@ -1129,6 +1352,16 @@
 }
 
 
+void IsolateReloadContext::AddEnumBecomeMapping(const Object& old,
+                                                const Object& neu) {
+  const GrowableObjectArray& become_enum_mappings =
+      GrowableObjectArray::Handle(become_enum_mappings_);
+  become_enum_mappings.Add(old);
+  become_enum_mappings.Add(neu);
+  ASSERT((become_enum_mappings.Length() % 2) == 0);
+}
+
+
 void IsolateReloadContext::RebuildDirectSubclasses() {
   ClassTable* class_table = I->class_table();
   intptr_t num_cids = class_table->NumCids();
diff --git a/runtime/vm/isolate_reload.h b/runtime/vm/isolate_reload.h
index de6ff00..ce316f6 100644
--- a/runtime/vm/isolate_reload.h
+++ b/runtime/vm/isolate_reload.h
@@ -5,11 +5,13 @@
 #ifndef VM_ISOLATE_RELOAD_H_
 #define VM_ISOLATE_RELOAD_H_
 
+#include "vm/hash_map.h"
 #include "vm/globals.h"
 #include "vm/growable_array.h"
 #include "vm/log.h"
 
 DECLARE_FLAG(bool, trace_reload);
+DECLARE_FLAG(bool, trace_reload_verbose);
 
 // 'Trace Isolate Reload' TIR_Print
 #if defined(_MSC_VER)
@@ -20,6 +22,15 @@
     if (FLAG_trace_reload) Log::Current()->Print(format, ##__VA_ARGS__)
 #endif
 
+// 'Verbose Trace Isolate Reload' VTIR_Print
+#if defined(_MSC_VER)
+#define VTIR_Print(format, ...) \
+    if (FLAG_trace_reload_verbose) Log::Current()->Print(format, __VA_ARGS__)
+#else
+#define VTIR_Print(format, ...) \
+    if (FLAG_trace_reload_verbose) Log::Current()->Print(format, ##__VA_ARGS__)
+#endif
+
 namespace dart {
 
 class GrowableObjectArray;
@@ -34,9 +45,80 @@
 class ObjectStore;
 class UpdateClassesVisitor;
 
+
+class InstanceMorpher : public ZoneAllocated {
+ public:
+  InstanceMorpher(const Class& from, const Class& to);
+  virtual ~InstanceMorpher() {}
+
+  // Called on each instance that needs to be morphed.
+  RawInstance* Morph(const Instance& instance) const;
+
+  // Adds an object to be morphed.
+  void AddObject(RawObject* object) const;
+
+  // Create the morphed objects based on the before() list.
+  void CreateMorphedCopies() const;
+
+  // Dump the state of the morpher.
+  void Dump() const;
+
+  // Returns the list of objects that need to be morphed.
+  ZoneGrowableArray<const Instance*>* before() const { return before_; }
+  // Returns the list of morphed objects (matches order in before()).
+  ZoneGrowableArray<const Instance*>* after() const { return after_; }
+
+  // Returns the cid associated with the from_ and to_ class.
+  intptr_t cid() const { return cid_; }
+
+ private:
+  const Class& from_;
+  const Class& to_;
+  ZoneGrowableArray<intptr_t> mapping_;
+  ZoneGrowableArray<const Instance*>* before_;
+  ZoneGrowableArray<const Instance*>* after_;
+  intptr_t cid_;
+
+  void ComputeMapping();
+  void DumpFormatFor(const Class& cls) const;
+};
+
+
+class ReasonForCancelling : public ZoneAllocated {
+ public:
+  ReasonForCancelling() {}
+  virtual ~ReasonForCancelling() {}
+
+  // Reports a reason for cancelling reload.
+  void Report(IsolateReloadContext* context);
+
+  // Conversion to a VM error object.
+  // Default implementation calls ToString.
+  virtual RawError* ToError();
+
+  // Conversion to a string object.
+  // Default implementation calls ToError.
+  virtual RawString* ToString();
+
+  // Concrete subclasses must override either ToError or ToString.
+};
+
+
+// Abstract class for also capturing the from_ and to_ class.
+class ClassReasonForCancelling : public ReasonForCancelling {
+ public:
+  ClassReasonForCancelling(const Class& from, const Class& to)
+      : from_(from), to_(to) { }
+
+ protected:
+  const Class& from_;
+  const Class& to_;
+};
+
+
 class IsolateReloadContext {
  public:
-  explicit IsolateReloadContext(Isolate* isolate, bool test_mode = false);
+  explicit IsolateReloadContext(Isolate* isolate);
   ~IsolateReloadContext();
 
   void StartReload();
@@ -47,13 +129,12 @@
 
   RawGrowableObjectArray* saved_libraries() const;
 
+  // Report back through the observatory channels.
   void ReportError(const Error& error);
-  void ReportError(const String& error_msg);
   void ReportSuccess();
 
-  bool has_error() const { return has_error_; }
-  RawError* error() const { return error_; }
-  bool test_mode() const { return test_mode_; }
+  bool has_error() const { return HasReasonsForCancelling(); }
+  RawError* error() const;
 
   static bool IsSameField(const Field& a, const Field& b);
   static bool IsSameLibrary(const Library& a_lib, const Library& b_lib);
@@ -74,6 +155,25 @@
 
   int64_t start_time_micros() const { return start_time_micros_; }
 
+  // Tells whether there are reasons for cancelling the reload.
+  bool HasReasonsForCancelling() const {
+    return !reasons_to_cancel_reload_.is_empty();
+  }
+
+  // Record problem for this reload.
+  void AddReasonForCancelling(ReasonForCancelling* reason);
+
+  // Report all reasons for cancelling reload.
+  void ReportReasonsForCancelling();
+
+  // Store morphing operation.
+  void AddInstanceMorpher(InstanceMorpher* morpher);
+
+  // Tells whether instance in the heap must be morphed.
+  bool HasInstanceMorphers() const {
+    return !instance_morphers_.is_empty();
+  }
+
  private:
   void set_saved_root_library(const Library& value);
 
@@ -95,6 +195,9 @@
   bool IsCleanLibrary(const Library& lib);
   void CheckpointLibraries();
 
+  // Transforms the heap based on instance_morphers_.
+  void MorphInstances();
+
   bool ValidateReload();
 
   void Rollback();
@@ -112,9 +215,6 @@
 
   void ClearReplacedObjectBits();
 
-  void BuildCleanScriptSet();
-  void FilterCompileTimeConstants();
-
   // atomic_install:
   void MarkAllFunctionsForRecompilation();
   void ResetUnoptimizedICsOnStack();
@@ -123,13 +223,32 @@
 
   int64_t start_time_micros_;
   Isolate* isolate_;
-  bool test_mode_;
-  bool has_error_;
 
   intptr_t saved_num_cids_;
   RawClass** saved_class_table_;
-
   intptr_t num_saved_libs_;
+
+  // Collect the necessary instance transformation for schema changes.
+  ZoneGrowableArray<InstanceMorpher*> instance_morphers_;
+
+  // Collects the reasons for cancelling the reload.
+  ZoneGrowableArray<ReasonForCancelling*> reasons_to_cancel_reload_;
+
+  // Required trait for the cid_mapper_;
+  struct MorpherTrait {
+    typedef InstanceMorpher* Value;
+    typedef intptr_t Key;
+    typedef InstanceMorpher* Pair;
+
+    static Key KeyOf(Pair kv) { return kv->cid(); }
+    static Value ValueOf(Pair kv) { return kv; }
+    static intptr_t Hashcode(Key key) { return key; }
+    static bool IsKeyEqual(Pair kv, Key key) { return kv->cid() == key; }
+  };
+
+  // Hash map from cid to InstanceMorpher.
+  DirectChainedHashMap<MorpherTrait> cid_mapper_;
+
   struct LibraryInfo {
     bool dirty;
   };
@@ -148,7 +267,8 @@
 
   void AddStaticFieldMapping(const Field& old_field, const Field& new_field);
 
-  void AddBecomeMapping(const Object& old, const Object& nue);
+  void AddBecomeMapping(const Object& old, const Object& neu);
+  void AddEnumBecomeMapping(const Object& old, const Object& neu);
 
   void RebuildDirectSubclasses();
 
@@ -158,19 +278,19 @@
   RawObject** from() { return reinterpret_cast<RawObject**>(&script_uri_); }
   RawString* script_uri_;
   RawError* error_;
-  RawArray* clean_scripts_set_storage_;
-  RawArray* compile_time_constants_;
   RawArray* old_classes_set_storage_;
   RawArray* class_map_storage_;
   RawArray* old_libraries_set_storage_;
   RawArray* library_map_storage_;
   RawArray* become_map_storage_;
+  RawGrowableObjectArray* become_enum_mappings_;
   RawLibrary* saved_root_library_;
   RawGrowableObjectArray* saved_libraries_;
   RawObject** to() { return reinterpret_cast<RawObject**>(&saved_libraries_); }
 
   friend class Isolate;
-  friend class Class;  // AddStaticFieldMapping.
+  friend class Class;  // AddStaticFieldMapping, AddEnumBecomeMapping.
+  friend class ObjectLocator;
 };
 
 }  // namespace dart
diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc
index aa8f188..d060680 100644
--- a/runtime/vm/isolate_reload_test.cc
+++ b/runtime/vm/isolate_reload_test.cc
@@ -65,7 +65,6 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
   EXPECT_EQ(10, SimpleInvoke(lib, "main"));
 }
 
@@ -83,7 +82,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_EQ(4, SimpleInvoke(lib, "main"));
 
   const char* kReloadScript =
@@ -99,7 +97,6 @@
 
   Dart_Handle result = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_ERROR(result, "unexpected token");
-
   EXPECT_EQ(4, SimpleInvoke(lib, "main"));
 }
 
@@ -114,7 +111,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("init()=old value,value=old value",
                SimpleInvokeStr(lib, "main"));
 
@@ -128,7 +124,6 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("init()=new value,value=old value",
                SimpleInvokeStr(lib, "main"));
 }
@@ -149,7 +144,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("antediluvian!", SimpleInvokeStr(lib, "main"));
 
   // Remove the original closure from the source code.  The closure is
@@ -166,7 +160,6 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("postapocalyptic!", SimpleInvokeStr(lib, "main"));
 }
 
@@ -180,7 +173,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("value1=10", SimpleInvokeStr(lib, "main"));
 
   const char* kReloadScript =
@@ -192,9 +184,7 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
-  EXPECT_STREQ("value1=10,value2=20",
-               SimpleInvokeStr(lib, "main"));
+  EXPECT_STREQ("value1=10,value2=20", SimpleInvokeStr(lib, "main"));
 }
 
 
@@ -210,7 +200,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_EQ(44, SimpleInvoke(lib, "main"));
 
   const char* kReloadScript =
@@ -224,7 +213,8 @@
       "}\n";
 
   lib = TestCase::ReloadTestScript(kReloadScript);
-  EXPECT_ERROR(lib, "Number of instance fields changed");
+  EXPECT_VALID(lib);
+  EXPECT_EQ(44, SimpleInvoke(lib, "main"));
 }
 
 
@@ -241,7 +231,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_EQ(44, SimpleInvoke(lib, "main"));
 
   const char* kReloadScript =
@@ -256,7 +245,8 @@
       "}\n";
 
   lib = TestCase::ReloadTestScript(kReloadScript);
-  EXPECT_ERROR(lib, "Number of instance fields changed");
+  EXPECT_VALID(lib);
+  EXPECT_EQ(44, SimpleInvoke(lib, "main"));
 }
 
 
@@ -273,7 +263,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_EQ(44, SimpleInvoke(lib, "main"));
 
   const char* kReloadScript =
@@ -286,7 +275,8 @@
       "}\n";
 
   lib = TestCase::ReloadTestScript(kReloadScript);
-  EXPECT_ERROR(lib, "Number of instance fields changed");
+  EXPECT_VALID(lib);
+  EXPECT_EQ(44, SimpleInvoke(lib, "main"));
 }
 
 
@@ -298,7 +288,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("hello", SimpleInvokeStr(lib, "main"));
 
   const char* kReloadScript =
@@ -312,7 +301,6 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("hello from A", SimpleInvokeStr(lib, "main"));
 }
 
@@ -325,7 +313,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_ERROR(SimpleInvokeError(lib, "main"), "max");;
 
   const char* kReloadScript =
@@ -336,7 +323,6 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
   EXPECT_EQ(4, SimpleInvoke(lib, "main"));
 }
 
@@ -350,7 +336,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_EQ(4, SimpleInvoke(lib, "main"));
 
   const char* kReloadScript =
@@ -420,7 +405,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("saved:20 new:20", SimpleInvokeStr(lib, "main"));
 
   const char* kReloadScript =
@@ -435,7 +419,6 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("saved:20 new:10", SimpleInvokeStr(lib, "main"));
 }
 
@@ -454,7 +437,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("saved:20 new:20", SimpleInvokeStr(lib, "main"));
 
   const char* kReloadScript =
@@ -471,7 +453,6 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("saved:20 new:10", SimpleInvokeStr(lib, "main"));
 }
 
@@ -489,7 +470,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("(true/false, true/true)", SimpleInvokeStr(lib, "main"));
 
   const char* kReloadScript =
@@ -505,7 +485,6 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("(true/true, false/true)", SimpleInvokeStr(lib, "main"));
 }
 
@@ -525,7 +504,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("Instance of 'B<A>'", SimpleInvokeStr(lib, "main"));
 
   const char* kReloadScript =
@@ -539,11 +517,108 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("Instance of 'B<A>'", SimpleInvokeStr(lib, "main"));
 }
 
 
+TEST_CASE(IsolateReload_TypeIdentity) {
+  const char* kScript =
+      "import 'test:isolate_reload_helper';\n"
+      "class T { }\n"
+      "getType() => T;\n"
+      "main() {\n"
+      "  var oldType = getType();\n"
+      "  reloadTest();\n"
+      "  var newType = getType();\n"
+      "  return identical(oldType, newType).toString();\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+
+  const char* kReloadScript =
+      "import 'test:isolate_reload_helper';\n"
+      "class T extends Stopwatch { }\n"
+      "getType() => T;\n"
+      "main() {\n"
+      "  var oldType = getType();\n"
+      "  reloadTest();\n"
+      "  var newType = getType();\n"
+      "  return identical(oldType, newType).toString();\n"
+      "}\n";
+
+  TestCase::SetReloadTestScript(kReloadScript);
+
+  EXPECT_STREQ("true", SimpleInvokeStr(lib, "main"));
+}
+
+
+TEST_CASE(IsolateReload_TypeIdentityGeneric) {
+  const char* kScript =
+      "import 'test:isolate_reload_helper';\n"
+      "class T<G> { }\n"
+      "getType() => new T<int>().runtimeType;\n"
+      "main() {\n"
+      "  var oldType = getType();\n"
+      "  reloadTest();\n"
+      "  var newType = getType();\n"
+      "  return identical(oldType, newType).toString();\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+
+  const char* kReloadScript =
+      "import 'test:isolate_reload_helper';\n"
+      "class T<G> extends Stopwatch { }\n"
+      "getType() => new T<int>().runtimeType;\n"
+      "main() {\n"
+      "  var oldType = getType();\n"
+      "  reloadTest();\n"
+      "  var newType = getType();\n"
+      "  return identical(oldType, newType).toString();\n"
+      "}\n";
+
+  TestCase::SetReloadTestScript(kReloadScript);
+
+  EXPECT_STREQ("true", SimpleInvokeStr(lib, "main"));
+}
+
+
+TEST_CASE(IsolateReload_TypeIdentityParameter) {
+  const char* kScript =
+      "import 'dart:mirrors';\n"
+      "import 'test:isolate_reload_helper';\n"
+      "class T<G> { }\n"
+      "getTypeVar() => reflectType(T).typeVariables[0];\n"
+      "main() {\n"
+      "  var oldType = getTypeVar();\n"
+      "  reloadTest();\n"
+      "  var newType = getTypeVar();\n"
+      "  return (oldType == newType).toString();\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+
+  const char* kReloadScript =
+      "import 'dart:mirrors';\n"
+      "import 'test:isolate_reload_helper';\n"
+      "class T<G> extends Stopwatch { }\n"
+      "getTypeVar() => reflectType(T).typeVariables[0];\n"
+      "main() {\n"
+      "  var oldType = getTypeVar();\n"
+      "  reloadTest();\n"
+      "  var newType = getTypeVar();\n"
+      "  return (oldType == newType).toString();\n"
+      "}\n";
+
+  TestCase::SetReloadTestScript(kReloadScript);
+
+  EXPECT_STREQ("true", SimpleInvokeStr(lib, "main"));
+}
+
+
 TEST_CASE(IsolateReload_MixinChanged) {
   const char* kScript =
       "class Mixin1 {\n"
@@ -559,7 +634,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("saved:field=mixin1,func=mixin1",
                SimpleInvokeStr(lib, "main"));
 
@@ -609,7 +683,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("(a is A(true)/ B(false)/ C(false),"
                " b is A(true)/ B(true)/ C(false),"
                " c is A(true)/ B(true)/ C(true))",
@@ -636,7 +709,6 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("(a is A(true)/ C(true)/ X(true),"
                " b is A(true)/ C(true)/ X(true),"  // still extends A...
                " c is A(false)/ C(true)/ X(false),"
@@ -669,7 +741,6 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript2);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("(a is A(true)/ B(false)/ C(false)/ X(true),"
                " b is A(false)/ B(true)/ C(false)/ X(true),"
                " c is A(true)/ B(false)/ C(true)/ X(true),"
@@ -708,7 +779,6 @@
 
   lib = TestCase::GetReloadErrorOrRootLibrary();
   EXPECT_VALID(lib);
-
   EXPECT_EQ(105, SimpleInvoke(lib, "main"));
 }
 
@@ -723,7 +793,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_ERROR(SimpleInvokeError(lib, "main"), "importedFunc");
 
   // Fail to find 'test:importable_lib' in the isolate.
@@ -739,7 +808,6 @@
   // Reload and add 'test:importable_lib' to isolate.
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("a", SimpleInvokeStr(lib, "main"));
 
   // Find 'test:importable_lib' in the isolate.
@@ -769,7 +837,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_ERROR(SimpleInvokeError(lib, "main"), "importedFunc");
 
   // Import 'test:importable_lib'.
@@ -781,7 +848,6 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("a", SimpleInvokeStr(lib, "main"));
 }
 
@@ -880,7 +946,6 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("mixin", SimpleInvokeStr(lib, "main"));
 }
 
@@ -893,7 +958,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_EQ(4, SimpleInvoke(lib, "main"));
 
   const char* kReloadScript =
@@ -943,7 +1007,6 @@
 
   lib = TestCase::GetReloadErrorOrRootLibrary();
   EXPECT_VALID(lib);
-
   EXPECT_EQ("instance", SimpleInvokeStr(lib, "main"));
 }
 
@@ -984,7 +1047,6 @@
 
   lib = TestCase::GetReloadErrorOrRootLibrary();
   EXPECT_VALID(lib);
-
   EXPECT_EQ("static", SimpleInvokeStr(lib, "main"));
 }
 
@@ -1035,7 +1097,6 @@
 
   lib = TestCase::GetReloadErrorOrRootLibrary();
   EXPECT_VALID(lib);
-
   EXPECT_EQ("okay", SimpleInvokeStr(lib, "main"));
 }
 
@@ -1086,7 +1147,6 @@
 
   lib = TestCase::GetReloadErrorOrRootLibrary();
   EXPECT_VALID(lib);
-
   EXPECT_EQ("exception", SimpleInvokeStr(lib, "main"));
 }
 
@@ -1134,7 +1194,6 @@
 
   lib = TestCase::GetReloadErrorOrRootLibrary();
   EXPECT_VALID(lib);
-
   EXPECT_EQ("exception", SimpleInvokeStr(lib, "main"));
 }
 
@@ -1182,11 +1241,54 @@
 
   lib = TestCase::GetReloadErrorOrRootLibrary();
   EXPECT_VALID(lib);
-
   EXPECT_EQ("static", SimpleInvokeStr(lib, "main"));
 }
 
 
+TEST_CASE(IsolateReload_PendingSuperCall) {
+  const char* kScript =
+      "import 'test:isolate_reload_helper';\n"
+      "class S {\n"
+      "  foo() => 1;\n"
+      "}\n"
+      "class C extends S {\n"
+      "  foo() => 100;\n"
+      "  test() {\n"
+      "    var n = super.foo();\n"
+      "    reloadTest();\n"
+      "    return n + super.foo();\n"
+      "  }\n"
+      "}\n"
+      "main() {\n"
+      "  return new C().test();\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+
+  const char* kReloadScript =
+      "import 'test:isolate_reload_helper';\n"
+      "class S {\n"
+      "  foo() => 10;\n"
+      "}\n"
+      "class C extends S {\n"
+      "  foo() => 100;\n"
+      "  test() {\n"
+      "    var n = super.foo();\n"
+      "    reloadTest();\n"
+      "    return n + super.foo();\n"
+      "  }\n"
+      "}\n"
+      "main() {\n"
+      "  return new C().test();\n"
+      "}\n";
+
+  TestCase::SetReloadTestScript(kReloadScript);
+
+  EXPECT_EQ(11, SimpleInvoke(lib, "main"));
+}
+
+
 TEST_CASE(IsolateReload_EnumEquality) {
   const char* kScript =
       "enum Fruit {\n"
@@ -1220,7 +1322,6 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("yes", SimpleInvokeStr(lib, "main"));
 }
 
@@ -1239,7 +1340,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("Fruit.Apple", SimpleInvokeStr(lib, "main"));
 
   const char* kReloadScript =
@@ -1258,7 +1358,6 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("yes", SimpleInvokeStr(lib, "main"));
 }
 
@@ -1277,7 +1376,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("Fruit.Apple", SimpleInvokeStr(lib, "main"));
 
   const char* kReloadScript =
@@ -1296,7 +1394,6 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("yes", SimpleInvokeStr(lib, "main"));
 }
 
@@ -1314,7 +1411,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("Fruit.Apple", SimpleInvokeStr(lib, "main"));
 
   const char* kReloadScript =
@@ -1333,7 +1429,6 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("0/Fruit.Apple 1/Fruit.Cantalope 2/Fruit.Banana",
                SimpleInvokeStr(lib, "main"));
 }
@@ -1350,7 +1445,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("Fruit.Apple", SimpleInvokeStr(lib, "main"));
 
   const char* kReloadScript =
@@ -1376,7 +1470,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("yes", SimpleInvokeStr(lib, "main"));
 
   const char* kReloadScript =
@@ -1401,129 +1494,31 @@
       "}\n"
       "var x;\n"
       "main() {\n"
-      "  return Fruit.Apple.toString();\n"
-      "}\n";
-
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-
-  EXPECT_STREQ("Fruit.Apple", SimpleInvokeStr(lib, "main"));
-
-  // Delete 'Cantalope'.
-
-  const char* kReloadScript =
-      "enum Fruit {\n"
-      "  Apple,\n"
-      "  Banana,\n"
-      "}\n"
-      "var x;\n"
-      "main() {\n"
-      "  String r = '${Fruit.Apple.index}/${Fruit.Apple} ';\n"
-      "  r += '${Fruit.Banana.index}/${Fruit.Banana} ';\n"
-      "  r += '${Fruit.Cantalope.index}/${Fruit.Cantalope}';\n"
-      "  return r;\n"
-      "}\n";
-
-  lib = TestCase::ReloadTestScript(kReloadScript);
-  EXPECT_VALID(lib);
-
-  EXPECT_STREQ("0/Fruit.Apple 1/Fruit.Banana 2/Fruit.Cantalope",
-               SimpleInvokeStr(lib, "main"));
-}
-
-
-TEST_CASE(IsolateReload_EnumComplex) {
-  const char* kScript =
-      "enum Fruit {\n"
-      "  Apple,\n"
-      "  Banana,\n"
-      "  Cantalope,\n"
-      "}\n"
-      "var x;\n"
-      "var y;\n"
-      "var z;\n"
-      "main() {\n"
-      "  x = Fruit.Apple;\n"
-      "  y = Fruit.Banana;\n"
-      "  z = Fruit.Cantalope;\n"
-      "  return Fruit.Apple.toString();\n"
-      "}\n";
-
-  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(lib);
-
-  EXPECT_STREQ("Fruit.Apple", SimpleInvokeStr(lib, "main"));
-
-  // Delete 'Cantalope'. Add 'Dragon'. Move 'Apple' and 'Banana'.
-
-  const char* kReloadScript =
-      "enum Fruit {\n"
-      "  Dragon,\n"
-      "  Apple,\n"
-      "  Banana,\n"
-      "}\n"
-      "var x;\n"
-      "var y;\n"
-      "var z;\n"
-      "main() {\n"
-      "  String r = '';\n"
-      "  r += '${identical(x, Fruit.Apple)}';\n"
-      "  r += ' ${identical(y, Fruit.Banana)}';\n"
-      "  r += ' ${identical(z, Fruit.Cantalope)}';\n"
-      "  r += ' ${Fruit.Dragon}';\n"
-      "  return r;\n"
-      "}\n";
-
-  lib = TestCase::ReloadTestScript(kReloadScript);
-  EXPECT_VALID(lib);
-
-  EXPECT_STREQ("true true true Fruit.Dragon", SimpleInvokeStr(lib, "main"));
-}
-
-
-TEST_CASE(IsolateReload_EnumValuesArray) {
-  const char* kScript =
-      "enum Fruit {\n"
-      "  Cantalope,\n"
-      "  Apple,\n"
-      "  Banana,\n"
-      "}\n"
-      "var x;\n"
-      "main() {\n"
       "  x = Fruit.Cantalope;\n"
       "  return Fruit.Apple.toString();\n"
       "}\n";
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("Fruit.Apple", SimpleInvokeStr(lib, "main"));
 
-  // Delete 'Cantalope'.
+  // Delete 'Cantalope' but make sure that we can still invoke toString,
+  // and access the hashCode and index properties.
 
   const char* kReloadScript =
       "enum Fruit {\n"
+      "  Apple,\n"
       "  Banana,\n"
-      "  Apple\n"
       "}\n"
       "var x;\n"
-      "bool identityCheck(Fruit f) {\n"
-      "  return identical(Fruit.values[f.index], f);\n"
-      "}\n"
       "main() {\n"
-      "  if ((x is Fruit) && identical(x, Fruit.Cantalope)) {\n"
-      "    String r = '${identityCheck(Fruit.Apple)}';\n"
-      "    r += ' ${identityCheck(Fruit.Banana)}';\n"
-      "    r += ' ${identityCheck(Fruit.Cantalope)}';\n"
-      "    r += ' ${identityCheck(x)}';\n"
-      "    return r;\n"
-      "  }\n"
+      "  String r = '$x ${x.hashCode is int} ${x.index}';\n"
+      "  return r;\n"
       "}\n";
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
-  EXPECT_STREQ("true true true true",
+  EXPECT_STREQ("Fruit.Cantalope true 2",
                SimpleInvokeStr(lib, "main"));
 }
 
@@ -1551,7 +1546,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("Fruit.Apple", SimpleInvokeStr(lib, "main"));
 
   const char* kReloadScript =
@@ -1583,7 +1577,6 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("true true true true true true true true true ",
                SimpleInvokeStr(lib, "main"));
 }
@@ -1604,7 +1597,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("Pear", SimpleInvokeStr(lib, "main"));
 
   const char* kReloadScript =
@@ -1624,7 +1616,6 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("yes", SimpleInvokeStr(lib, "main"));
 }
 
@@ -1646,7 +1637,6 @@
 
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("Fruit.Apple Fruit.Banana", SimpleInvokeStr(lib, "main"));
 
   // Insert 'Cantalope'.
@@ -1670,7 +1660,6 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-
   EXPECT_STREQ("Fruit.Apple Fruit.Cantalope Fruit.Banana",
                SimpleInvokeStr(lib, "main"));
 }
@@ -1859,6 +1848,278 @@
   EXPECT_STREQ("AIterator", name.ToCString());
 }
 
+
+// Tests reload succeeds when instance format changes.
+// Change: Foo {a, b, c:42}  -> Foo {c:42}
+// Validate: c keeps the value in the retained Foo object.
+TEST_CASE(IsolateReload_ChangeInstanceFormat0) {
+  const char* kScript =
+      "class Foo {\n"
+      "  var a;\n"
+      "  var b;\n"
+      "  var c;\n"
+      "}\n"
+      "var f;\n"
+      "main() {\n"
+      "  f = new Foo();\n"
+      "  f.c = 42;\n"
+      "  return f.c;\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(42, SimpleInvoke(lib, "main"));
+
+  const char* kReloadScript =
+      "class Foo {\n"
+      "  var c;\n"
+      "}\n"
+      "var f;\n"
+      "main() {\n"
+      "  return f.c;\n"
+      "}\n";
+
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(42, SimpleInvoke(lib, "main"));
+}
+
+
+// Tests reload succeeds when instance format changes.
+// Change: Foo {}  -> Foo {c:null}
+// Validate: c is initialized to null the retained Foo object.
+TEST_CASE(IsolateReload_ChangeInstanceFormat1) {
+  const char* kScript =
+      "class Foo {\n"
+      "}\n"
+      "var f;\n"
+      "main() {\n"
+      "  f = new Foo();\n"
+      "  return 42;\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(42, SimpleInvoke(lib, "main"));
+
+  const char* kReloadScript =
+      "class Foo {\n"
+      "  var c;\n"
+      "}\n"
+      "var f;\n"
+      "main() {\n"
+      "  return (f.c == null) ? 42: 21;\n"
+      "}\n";
+
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(42, SimpleInvoke(lib, "main"));
+}
+
+// Tests reload succeeds when instance format changes.
+// Change: Foo {c:42}  -> Foo {}
+// Validate: running the after script fails.
+TEST_CASE(IsolateReload_ChangeInstanceFormat2) {
+  const char* kScript =
+      "class Foo {\n"
+      "  var c;\n"
+      "}\n"
+      "var f;\n"
+      "main() {\n"
+      "  f = new Foo();\n"
+      "  f.c = 42;\n"
+      "  return f.c;\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(42, SimpleInvoke(lib, "main"));
+
+  const char* kReloadScript =
+      "class Foo {\n"
+      "}\n"
+      "var f;\n"
+      "main() {\n"
+      "  try {\n"
+      "    return f.c;\n"
+      "  } catch (e) {\n"
+      "    return 24;\n"
+      "  }\n"
+      "}\n";
+
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(24, SimpleInvoke(lib, "main"));
+}
+
+
+// Tests reload succeeds when instance format changes.
+// Change: Foo {a, b, c:42, d}  -> Foo {c:42, g}
+// Validate: c keeps the value in the retained Foo object.
+TEST_CASE(IsolateReload_ChangeInstanceFormat3) {
+  const char* kScript =
+      "class Foo<A,B> {\n"
+      "  var a;\n"
+      "  var b;\n"
+      "  var c;\n"
+      "  var d;\n"
+      "}\n"
+      "var f;\n"
+      "main() {\n"
+      "  f = new Foo();\n"
+      "  f.a = 1;\n"
+      "  f.b = 2;\n"
+      "  f.c = 3;\n"
+      "  f.d = 4;\n"
+      "  return f.c;\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(3, SimpleInvoke(lib, "main"));
+
+  const char* kReloadScript =
+      "class Foo<A,B> {\n"
+      "  var c;\n"
+      "  var g;\n"
+      "}\n"
+      "var f;\n"
+      "main() {\n"
+      "  return f.c;\n"
+      "}\n";
+
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(3, SimpleInvoke(lib, "main"));
+}
+
+
+// Tests reload succeeds when instance format changes.
+// Change: Bar {c:42}, Foo : Bar {d, e} -> Foo {c:42}
+// Validate: c keeps the value in the retained Foo object.
+TEST_CASE(IsolateReload_ChangeInstanceFormat4) {
+  const char* kScript =
+      "class Bar{\n"
+      "  var c;\n"
+      "}\n"
+      "class Foo extends Bar{\n"
+      "  var d;\n"
+      "  var e;\n"
+      "}\n"
+      "var f;\n"
+      "main() {\n"
+      "  f = new Foo();\n"
+      "  f.c = 44;\n"
+      "  return f.c;\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 c;\n"
+      "}\n"
+      "var f;\n"
+      "main() {\n"
+      "  return f.c;\n"
+      "}\n";
+
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(44, SimpleInvoke(lib, "main"));
+}
+
+
+// Tests reload succeeds when instance format changes.
+// Change: Bar {a, b}, Foo : Bar {c:42} -> Bar {c:42}, Foo : Bar {}
+// Validate: c keeps the value in the retained Foo object.
+TEST_CASE(IsolateReload_ChangeInstanceFormat5) {
+  const char* kScript =
+      "class Bar{\n"
+      "  var a;\n"
+      "  var b;\n"
+      "}\n"
+      "class Foo extends Bar{\n"
+      "  var c;\n"
+      "}\n"
+      "var f;\n"
+      "main() {\n"
+      "  f = new Foo();\n"
+      "  f.c = 44;\n"
+      "  return f.c;\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(44, SimpleInvoke(lib, "main"));
+
+  const char* kReloadScript =
+      "class Bar{\n"
+      "  var c;\n"
+      "}\n"
+      "class Foo extends Bar {\n"
+      "}\n"
+      "var f;\n"
+      "main() {\n"
+      "  return f.c;\n"
+      "}\n";
+
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(44, SimpleInvoke(lib, "main"));
+}
+
+
+// Tests reload fails when type parameters change.
+// Change: Foo<A,B> {a, b}  -> Foo<A> {a}
+// Validate: the right error message is returned.
+TEST_CASE(IsolateReload_ChangeInstanceFormat6) {
+  const char* kScript =
+      "class Foo<A, B> {\n"
+      "  var a;\n"
+      "  var b;\n"
+      "}\n"
+      "main() {\n"
+      "  new Foo();\n"
+      "  return 43;\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(43, SimpleInvoke(lib, "main"));
+
+  const char* kReloadScript =
+      "class Foo<A> {\n"
+      "  var a;\n"
+      "}\n";
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_ERROR(lib, "type parameters have changed");
+}
+
+// Tests reload succeeds when type parameters are changed for allocated class.
+// Change: Foo<A,B> {a, b} -> Foo<A> {a}
+// Validate: return value from main is correct.
+// Please note: This test works because no instances are created from Foo.
+TEST_CASE(IsolateReload_ChangeInstanceFormat7) {
+  const char* kScript =
+      "class Foo<A, B> {\n"
+      "  var a;\n"
+      "  var b;\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+
+  const char* kReloadScript =
+      "class Foo<A> {\n"
+      "  var a;\n"
+      "}\n";
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_VALID(lib);
+}
+
 #endif  // !PRODUCT
 
 }  // namespace dart
diff --git a/runtime/vm/jit_optimizer.cc b/runtime/vm/jit_optimizer.cc
index e40cf12..56074a2 100644
--- a/runtime/vm/jit_optimizer.cc
+++ b/runtime/vm/jit_optimizer.cc
@@ -1680,7 +1680,7 @@
 bool JitOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) {
   ASSERT(call->HasICData());
   const ICData& ic_data = *call->ic_data();
-  if ((ic_data.NumberOfUsedChecks() == 0) || !ic_data.HasOneTarget()) {
+  if (ic_data.NumberOfUsedChecks() != 1) {
     // No type feedback collected or multiple targets found.
     return false;
   }
@@ -1696,14 +1696,13 @@
       (recognized_kind == MethodRecognizer::kExternalOneByteStringCodeUnitAt) ||
       (recognized_kind == MethodRecognizer::kExternalTwoByteStringCodeUnitAt) ||
       (recognized_kind == MethodRecognizer::kGrowableArraySetData) ||
-      (recognized_kind == MethodRecognizer::kGrowableArraySetLength)) {
-      ASSERT(ic_data.NumberOfChecks() == 1);
+      (recognized_kind == MethodRecognizer::kGrowableArraySetLength) ||
+      (recognized_kind == MethodRecognizer::kSmi_bitAndFromSmi)) {
     return FlowGraphInliner::TryReplaceInstanceCallWithInline(
         flow_graph_, current_iterator(), call);
   }
 
-  if ((recognized_kind == MethodRecognizer::kStringBaseCharAt) &&
-      (ic_data.NumberOfChecks() == 1)) {
+  if (recognized_kind == MethodRecognizer::kStringBaseCharAt) {
       ASSERT((class_ids[0] == kOneByteStringCid) ||
              (class_ids[0] == kTwoByteStringCid) ||
              (class_ids[0] == kExternalOneByteStringCid) ||
@@ -1712,7 +1711,7 @@
         flow_graph_, current_iterator(), call);
   }
 
-  if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) {
+  if (class_ids[0] == kOneByteStringCid) {
     if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) {
       // This is an internal method, no need to check argument types nor
       // range.
@@ -1735,8 +1734,7 @@
   }
 
   if (CanUnboxDouble() &&
-      (recognized_kind == MethodRecognizer::kIntegerToDouble) &&
-      (ic_data.NumberOfChecks() == 1)) {
+      (recognized_kind == MethodRecognizer::kIntegerToDouble)) {
     if (class_ids[0] == kSmiCid) {
       AddReceiverCheck(call);
       ReplaceCall(call,
@@ -1805,36 +1803,23 @@
     }
   }
 
-  if (IsSupportedByteArrayViewCid(class_ids[0]) &&
-      (ic_data.NumberOfChecks() == 1)) {
+  if (IsSupportedByteArrayViewCid(class_ids[0])) {
     return FlowGraphInliner::TryReplaceInstanceCallWithInline(
         flow_graph_, current_iterator(), call);
   }
 
-  if ((class_ids[0] == kFloat32x4Cid) && (ic_data.NumberOfChecks() == 1)) {
+  if (class_ids[0] == kFloat32x4Cid) {
     return TryInlineFloat32x4Method(call, recognized_kind);
   }
 
-  if ((class_ids[0] == kInt32x4Cid) && (ic_data.NumberOfChecks() == 1)) {
+  if (class_ids[0] == kInt32x4Cid) {
     return TryInlineInt32x4Method(call, recognized_kind);
   }
 
-  if ((class_ids[0] == kFloat64x2Cid) && (ic_data.NumberOfChecks() == 1)) {
+  if (class_ids[0] == kFloat64x2Cid) {
     return TryInlineFloat64x2Method(call, recognized_kind);
   }
 
-  if (recognized_kind == MethodRecognizer::kSmi_bitAndFromSmi) {
-    AddReceiverCheck(call);
-    BinarySmiOpInstr* op =
-        new(Z) BinarySmiOpInstr(
-            Token::kBIT_AND,
-            new(Z) Value(call->ArgumentAt(0)),
-            new(Z) Value(call->ArgumentAt(1)),
-            call->deopt_id());
-    ReplaceCall(call, op);
-    return true;
-  }
-
   return false;
 }
 
@@ -2347,6 +2332,12 @@
 }
 
 
+// Tells whether the function of the call matches the core private name.
+static bool matches_core(InstanceCallInstr* call, const String& name) {
+  return call->function_name().raw() == Library::PrivateCoreLibName(name).raw();
+}
+
+
 // TODO(srdjan): Use ICData to check if always true or false.
 void JitOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
   ASSERT(Token::IsTypeTestOperator(call->token_kind()));
@@ -2356,26 +2347,27 @@
   bool negate = false;
   if (call->ArgumentCount() == 2) {
     type_args = flow_graph()->constant_null();
-    if (call->function_name().raw() ==
-        Library::PrivateCoreLibName(Symbols::_instanceOfNum()).raw()) {
-      type = Type::Number();
-    } else if (call->function_name().raw() ==
-        Library::PrivateCoreLibName(Symbols::_instanceOfInt()).raw()) {
-      type = Type::IntType();
-    } else if (call->function_name().raw() ==
-        Library::PrivateCoreLibName(Symbols::_instanceOfSmi()).raw()) {
-      type = Type::SmiType();
-    } else if (call->function_name().raw() ==
-        Library::PrivateCoreLibName(Symbols::_instanceOfDouble()).raw()) {
-      type = Type::Double();
-    } else if (call->function_name().raw() ==
-        Library::PrivateCoreLibName(Symbols::_instanceOfString()).raw()) {
-      type = Type::StringType();
+    if (matches_core(call, Symbols::_simpleInstanceOf())) {
+      type =
+          AbstractType::Cast(call->ArgumentAt(1)->AsConstant()->value()).raw();
+      negate = false;  // Just to be sure.
     } else {
-      UNIMPLEMENTED();
+      if (matches_core(call, Symbols::_instanceOfNum())) {
+        type = Type::Number();
+      } else if (matches_core(call, Symbols::_instanceOfInt())) {
+        type = Type::IntType();
+      } else if (matches_core(call, Symbols::_instanceOfSmi())) {
+        type = Type::SmiType();
+      } else if (matches_core(call, Symbols::_instanceOfDouble())) {
+        type = Type::Double();
+      } else if (matches_core(call, Symbols::_instanceOfString())) {
+        type = Type::StringType();
+      } else {
+        UNIMPLEMENTED();
+      }
+      negate = Bool::Cast(call->ArgumentAt(1)->OriginalDefinition()
+                          ->AsConstant()->value()).value();
     }
-    negate = Bool::Cast(call->ArgumentAt(1)->OriginalDefinition()
-        ->AsConstant()->value()).value();
   } else {
     type_args = call->ArgumentAt(1);
     type = AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()).raw();
diff --git a/runtime/vm/message.cc b/runtime/vm/message.cc
index 035428d..0cb618a 100644
--- a/runtime/vm/message.cc
+++ b/runtime/vm/message.cc
@@ -181,6 +181,7 @@
 
 
 void MessageQueue::PrintJSON(JSONStream* stream) {
+#ifndef PRODUCT
   if (!FLAG_support_service) {
     return;
   }
@@ -221,6 +222,7 @@
       }
     }
   }
+#endif  // !PRODUCT
 }
 
 }  // namespace dart
diff --git a/runtime/vm/method_recognizer.h b/runtime/vm/method_recognizer.h
index 083b477..08226f8 100644
--- a/runtime/vm/method_recognizer.h
+++ b/runtime/vm/method_recognizer.h
@@ -359,6 +359,7 @@
   V(_ImmutableList, get:length, ImmutableArrayLength, 0x25943ad2)              \
   V(_TypedList, get:length, TypedDataLength, 0x2090dc1a)                       \
   V(_GrowableList, get:length, GrowableArrayLength, 0x18dc9df6)                \
+  V(_GrowableList, get:_capacity, GrowableArrayCapacity, 0x02734d82)           \
   V(_GrowableList, add, GrowableListAdd, 0x0d1358ed)                           \
   V(_GrowableList, removeLast, GrowableListRemoveLast, 0x135d7384)             \
   V(_StringBase, get:length, StringBaseLength, 0x2a2c1b13)                     \
diff --git a/runtime/vm/metrics.cc b/runtime/vm/metrics.cc
index cb6c205..137042e 100644
--- a/runtime/vm/metrics.cc
+++ b/runtime/vm/metrics.cc
@@ -67,6 +67,7 @@
 }
 
 
+#ifndef PRODUCT
 static const char* UnitString(intptr_t unit) {
   switch (unit) {
     case Metric::kCounter: return "counter";
@@ -97,6 +98,7 @@
   double value_as_double = static_cast<double>(Value());
   obj.AddProperty("value", value_as_double);
 }
+#endif  // !PRODUCT
 
 
 char* Metric::ValueToString(int64_t value, Unit unit) {
@@ -306,13 +308,13 @@
   if (FLAG_print_metrics) {
     // Create a zone to allocate temporary strings in.
     StackZone sz(Thread::Current());
-    OS::Print("Printing metrics for VM\n");
+    OS::PrintErr("Printing metrics for VM\n");
     Metric* current = Metric::vm_head();
     while (current != NULL) {
-      OS::Print("%s\n", current->ToString());
+      OS::PrintErr("%s\n", current->ToString());
       current = current->next();
     }
-    OS::Print("\n");
+    OS::PrintErr("\n");
   }
 }
 
diff --git a/runtime/vm/metrics.h b/runtime/vm/metrics.h
index 9fde2d8..c34f02d 100644
--- a/runtime/vm/metrics.h
+++ b/runtime/vm/metrics.h
@@ -56,7 +56,9 @@
 
   virtual ~Metric();
 
+#ifndef PRODUCT
   void PrintJSON(JSONStream* stream);
+#endif  // !PRODUCT
 
   // Returns a zone allocated string.
   static char* ValueToString(int64_t value, Unit unit);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 9b2e319..71cd044 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -1845,6 +1845,7 @@
     Exceptions::Throw(thread, exception);
     UNREACHABLE();
   }
+#ifndef PRODUCT
   ClassTable* class_table = isolate->class_table();
   if (space == Heap::kNew) {
     class_table->UpdateAllocatedNew(cls_id, size);
@@ -1855,6 +1856,7 @@
   if (FLAG_profiler && cls.TraceAllocation(isolate)) {
     Profiler::SampleAllocation(thread, cls_id);
   }
+#endif  // !PRODUCT
   NoSafepointScope no_safepoint;
   InitializeObject(address, cls_id, size, (isolate == Dart::vm_isolate()));
   RawObject* raw_obj = reinterpret_cast<RawObject*>(address + kHeapObjectTag);
@@ -2074,7 +2076,7 @@
       fields = cls.fields();
       for (intptr_t i = 0; i < fields.Length(); ++i) {
         f ^= fields.At(i);
-        if (!f.is_static()) {
+        if (f.is_instance()) {
           array.SetAt(f.Offset() >> kWordSizeLog2, f);
         }
       }
@@ -2808,12 +2810,17 @@
 
 
 bool Class::TraceAllocation(Isolate* isolate) const {
+#ifndef PRODUCT
   ClassTable* class_table = isolate->class_table();
   return class_table->TraceAllocationFor(id());
+#else
+  return false;
+#endif
 }
 
 
 void Class::SetTraceAllocation(bool trace_allocation) const {
+#ifndef PRODUCT
   Isolate* isolate = Isolate::Current();
   const bool changed = trace_allocation != this->TraceAllocation(isolate);
   if (changed) {
@@ -2821,6 +2828,9 @@
     class_table->SetTraceAllocationFor(id(), trace_allocation);
     DisableAllocationStub();
   }
+#else
+  UNREACHABLE();
+#endif
 }
 
 
@@ -4189,7 +4199,8 @@
 }
 
 
-RawField* Class::LookupFieldAllowPrivate(const String& name) const {
+RawField* Class::LookupFieldAllowPrivate(const String& name,
+                                         bool instance_only) const {
   // Use slow string compare, ignoring privacy name mangling.
   Thread* thread = Thread::Current();
   if (EnsureIsFinalized(thread) != Error::null()) {
@@ -4207,6 +4218,10 @@
   for (intptr_t i = 0; i < len; i++) {
     field ^= flds.At(i);
     field_name ^= field.name();
+    if (field.is_static() && instance_only) {
+      // If we only care about instance fields, skip statics.
+      continue;
+    }
     if (String::EqualsIgnoringPrivateKey(field_name, name)) {
       return field.raw();
     }
@@ -4216,7 +4231,7 @@
 
 
 RawField* Class::LookupInstanceFieldAllowPrivate(const String& name) const {
-  Field& field = Field::Handle(LookupFieldAllowPrivate(name));
+  Field& field = Field::Handle(LookupFieldAllowPrivate(name, true));
   if (!field.IsNull() && !field.is_static()) {
     return field.raw();
   }
@@ -5272,7 +5287,6 @@
 
 void Function::ClearCode() const {
   ASSERT(Thread::Current()->IsMutatorThread());
-  ASSERT((usage_counter() != 0) || (ic_data_array() == Array::null()));
   StorePointer(&raw_ptr()->unoptimized_code_, Code::null());
   SetInstructions(Code::Handle(StubCode::LazyCompile_entry()->code()));
 }
@@ -8687,6 +8701,11 @@
 }
 
 
+void Script::set_compile_time_constants(const Array& value) const {
+  StorePointer(&raw_ptr()->compile_time_constants_, value.raw());
+}
+
+
 RawGrowableObjectArray* Script::GenerateLineNumberArray() const {
   Zone* zone = Thread::Current()->zone();
   const GrowableObjectArray& info =
@@ -10304,18 +10323,10 @@
 }
 
 
-void Library::InitResolvedNamesCache(intptr_t size,
-                                     SnapshotReader* reader) const {
+void Library::InitResolvedNamesCache(intptr_t size) const {
   ASSERT(Thread::Current()->IsMutatorThread());
-  if (reader == NULL) {
-    StorePointer(&raw_ptr()->resolved_names_,
-                 HashTables::New<ResolvedNamesMap>(size));
-  } else {
-    intptr_t len = ResolvedNamesMap::ArrayLengthForNumOccupied(size);
-    *reader->ArrayHandle() ^= reader->NewArray(len);
-    StorePointer(&raw_ptr()->resolved_names_,
-                 HashTables::New<ResolvedNamesMap>(*reader->ArrayHandle()));
-  }
+  StorePointer(&raw_ptr()->resolved_names_,
+               HashTables::New<ResolvedNamesMap>(size));
 }
 
 
@@ -12469,7 +12480,10 @@
 
 RawFunction* ICData::Owner() const {
   Object& obj = Object::Handle(raw_ptr()->owner_);
-  if (obj.IsFunction()) {
+  if (obj.IsNull()) {
+    ASSERT(Dart::snapshot_kind() == Snapshot::kAppNoJIT);
+    return Function::null();
+  } else if (obj.IsFunction()) {
     return Function::Cast(obj).raw();
   } else {
     ICData& original = ICData::Handle();
@@ -12834,10 +12848,20 @@
 }
 
 
+bool ICData::ValidateInterceptor(const Function& target) const {
+  ObjectStore* store = Isolate::Current()->object_store();
+  ASSERT((target.raw() == store->simple_instance_of_true_function()) ||
+         (target.raw() == store->simple_instance_of_false_function()));
+  const String& instance_of_name = String::Handle(
+      Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()).raw());
+  ASSERT(target_name() == instance_of_name.raw());
+  return true;
+}
+
 void ICData::AddCheck(const GrowableArray<intptr_t>& class_ids,
                       const Function& target) const {
   ASSERT(!target.IsNull());
-  ASSERT(target.name() == target_name());
+  ASSERT((target.name() == target_name()) || ValidateInterceptor(target));
   DEBUG_ASSERT(!HasCheck(class_ids));
   ASSERT(NumArgsTested() > 1);  // Otherwise use 'AddReceiverCheck'.
   ASSERT(class_ids.length() == NumArgsTested());
@@ -13520,95 +13544,6 @@
 }
 
 
-static Token::Kind RecognizeArithmeticOp(const String& name) {
-  ASSERT(name.IsSymbol());
-  if (name.raw() == Symbols::Plus().raw()) {
-    return Token::kADD;
-  } else if (name.raw() == Symbols::Minus().raw()) {
-    return Token::kSUB;
-  } else if (name.raw() == Symbols::Star().raw()) {
-    return Token::kMUL;
-  } else if (name.raw() == Symbols::Slash().raw()) {
-    return Token::kDIV;
-  } else if (name.raw() == Symbols::TruncDivOperator().raw()) {
-    return Token::kTRUNCDIV;
-  } else if (name.raw() == Symbols::Percent().raw()) {
-    return Token::kMOD;
-  } else if (name.raw() == Symbols::BitOr().raw()) {
-    return Token::kBIT_OR;
-  } else if (name.raw() == Symbols::Ampersand().raw()) {
-    return Token::kBIT_AND;
-  } else if (name.raw() == Symbols::Caret().raw()) {
-    return Token::kBIT_XOR;
-  } else if (name.raw() == Symbols::LeftShiftOperator().raw()) {
-    return Token::kSHL;
-  } else if (name.raw() == Symbols::RightShiftOperator().raw()) {
-    return Token::kSHR;
-  } else if (name.raw() == Symbols::Tilde().raw()) {
-    return Token::kBIT_NOT;
-  } else if (name.raw() == Symbols::UnaryMinus().raw()) {
-    return Token::kNEGATE;
-  }
-  return Token::kILLEGAL;
-}
-
-
-bool ICData::HasRangeFeedback() const {
-  const String& target = String::Handle(target_name());
-  const Token::Kind token_kind = RecognizeArithmeticOp(target);
-  if (!Token::IsBinaryArithmeticOperator(token_kind) &&
-      !Token::IsUnaryArithmeticOperator(token_kind)) {
-    return false;
-  }
-
-  bool initialized = false;
-  const intptr_t len = NumberOfChecks();
-  GrowableArray<intptr_t> class_ids;
-  for (intptr_t i = 0; i < len; i++) {
-    if (IsUsedAt(i)) {
-      initialized = true;
-      GetClassIdsAt(i, &class_ids);
-      for (intptr_t j = 0; j < class_ids.length(); j++) {
-        const intptr_t cid = class_ids[j];
-        if ((cid != kSmiCid) && (cid != kMintCid)) {
-          return false;
-        }
-      }
-    }
-  }
-
-  return initialized;
-}
-
-
-ICData::RangeFeedback ICData::DecodeRangeFeedbackAt(intptr_t idx) const {
-  ASSERT((0 <= idx) && (idx < 3));
-  const uint32_t raw_feedback =
-      RangeFeedbackBits::decode(raw_ptr()->state_bits_);
-  const uint32_t feedback =
-      (raw_feedback >> (idx * kBitsPerRangeFeedback)) & kRangeFeedbackMask;
-  if ((feedback & kInt64RangeBit) != 0) {
-    return kInt64Range;
-  }
-
-  if ((feedback & kUint32RangeBit) != 0) {
-    if ((feedback & kSignedRangeBit) == 0) {
-      return kUint32Range;
-    }
-
-    // Check if Smi is large enough to accomodate Int33: a mixture of Uint32
-    // and negative Int32 values.
-    return (kSmiBits < 33) ? kInt64Range : kSmiRange;
-  }
-
-  if ((feedback & kInt32RangeBit) != 0) {
-    return kInt32Range;
-  }
-
-  return kSmiRange;
-}
-
-
 Code::Comments& Code::Comments::New(intptr_t count) {
   Comments* comments;
   if (count < 0 || count > (kIntptrMax / kNumberOfEntries)) {
@@ -13844,6 +13779,7 @@
 
 
 void Code::Disassemble(DisassemblyFormatter* formatter) const {
+#ifndef PRODUCT
   if (!FLAG_support_disassembler) {
     return;
   }
@@ -13854,6 +13790,7 @@
   } else {
     Disassembler::Disassemble(start, start + instr.size(), formatter, *this);
   }
+#endif
 }
 
 
@@ -15365,6 +15302,19 @@
 }
 
 
+#if defined(DEBUG)
+bool Instance::CheckIsCanonical(Thread* thread) const {
+  Zone* zone = thread->zone();
+  Isolate* isolate = thread->isolate();
+  Instance& result = Instance::Handle(zone);
+  const Class& cls = Class::Handle(zone, this->clazz());
+  SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
+  result ^= cls.LookupCanonicalInstance(zone, *this);
+  return (result.raw() == this->raw());
+}
+#endif  // DEBUG
+
+
 RawAbstractType* Instance::GetType() const {
   if (IsNull()) {
     return Type::NullType();
@@ -16813,7 +16763,8 @@
         }
       } else if (!type_args.IsSubvectorEquivalent(other_type_args,
                                                   from_index,
-                                                  num_type_params)) {
+                                                  num_type_params,
+                                                  trail)) {
         return false;
       }
 #ifdef DEBUG
@@ -17172,6 +17123,38 @@
 }
 
 
+#if defined(DEBUG)
+bool Type::CheckIsCanonical(Thread* thread) const {
+  if (IsMalformed()) {
+    return true;
+  }
+  if (type_class() == Object::dynamic_class()) {
+    return (raw() == Object::dynamic_type().raw());
+  }
+  Zone* zone = thread->zone();
+  Isolate* isolate = thread->isolate();
+  AbstractType& type = Type::Handle(zone);
+  const Class& cls = Class::Handle(zone, type_class());
+
+  // Fast canonical lookup/registry for simple types.
+  if (!cls.IsGeneric() && !cls.IsClosureClass() && !cls.IsTypedefClass()) {
+    ASSERT(!IsFunctionType());
+    type = cls.CanonicalType();
+    return (raw() == type.raw());
+  }
+
+  ObjectStore* object_store = isolate->object_store();
+  {
+    SafepointMutexLocker ml(isolate->type_canonicalization_mutex());
+    CanonicalTypeSet table(zone, object_store->canonical_types());
+    type ^= table.GetOrNull(CanonicalTypeKey(*this));
+    object_store->set_canonical_types(table.Release());
+  }
+  return (raw() == type.raw());
+}
+#endif  // DEBUG
+
+
 RawString* Type::EnumerateURIs() const {
   if (IsDynamicType() || IsVoidType()) {
     return Symbols::Empty().raw();
@@ -17434,6 +17417,14 @@
 }
 
 
+#if defined(DEBUG)
+bool TypeRef::CheckIsCanonical(Thread* thread) const {
+  AbstractType& ref_type = AbstractType::Handle(type());
+  return ref_type.CheckIsCanonical(thread);
+}
+#endif  // DEBUG
+
+
 RawString* TypeRef::EnumerateURIs() const {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
@@ -18097,11 +18088,11 @@
     case kDoubleCid:
       return Double::NewCanonical(Double::Cast(*this).value());
     case kBigintCid: {
+      if (this->IsCanonical()) {
+        return this->raw();
+      }
       Zone* zone = thread->zone();
       Isolate* isolate = thread->isolate();
-      if (!CheckAndCanonicalizeFields(thread, error_str)) {
-        return Instance::null();
-      }
       Bigint& result = Bigint::Handle(zone);
       const Class& cls = Class::Handle(zone, this->clazz());
       intptr_t index = 0;
@@ -18141,6 +18132,38 @@
 }
 
 
+#if defined(DEBUG)
+bool Number::CheckIsCanonical(Thread* thread) const {
+  intptr_t cid = GetClassId();
+  intptr_t idx = 0;
+  Zone* zone = thread->zone();
+  const Class& cls = Class::Handle(zone, this->clazz());
+  switch (cid) {
+    case kSmiCid:
+      return true;
+    case kMintCid: {
+      Mint& result = Mint::Handle(zone);
+      result ^= cls.LookupCanonicalMint(zone, Mint::Cast(*this).value(), &idx);
+      return (result.raw() == this->raw());
+    }
+    case kDoubleCid: {
+      Double& dbl = Double::Handle(zone);
+      dbl ^= cls.LookupCanonicalDouble(zone, Double::Cast(*this).value(), &idx);
+      return (dbl.raw() == this->raw());
+    }
+    case kBigintCid: {
+      Bigint& result = Bigint::Handle(zone);
+      result ^= cls.LookupCanonicalBigint(zone, Bigint::Cast(*this), &idx);
+      return (result.raw() == this->raw());
+    }
+    default:
+      UNREACHABLE();
+  }
+  return false;
+}
+#endif  // DEBUG
+
+
 const char* Number::ToCString() const {
   // Number is an interface. No instances of Number should exist.
   UNREACHABLE();
@@ -19841,6 +19864,15 @@
 }
 
 
+#if defined(DEBUG)
+bool String::CheckIsCanonical(Thread* thread) const {
+  Zone* zone = thread->zone();
+  const String& str = String::Handle(zone, Symbols::Lookup(thread, *this));
+  return (str.raw() == this->raw());
+}
+#endif  // DEBUG
+
+
 RawString* String::New(const char* cstr, Heap::Space space) {
   ASSERT(cstr != NULL);
   intptr_t array_len = strlen(cstr);
@@ -21361,6 +21393,7 @@
 
 void Array::MakeImmutable() const {
   if (IsImmutable()) return;
+  ASSERT(!IsCanonical());
   NoSafepointScope no_safepoint;
   uword tags = raw_ptr()->tags_;
   uword old_tags;
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 143cf9e..82f01cb 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1157,13 +1157,14 @@
 
   bool IsPrivate() const;
 
+  // Returns an array of instance and static fields defined by this class.
   RawArray* fields() const { return raw_ptr()->fields_; }
   void SetFields(const Array& value) const;
   void AddField(const Field& field) const;
   void AddFields(const GrowableArray<const Field*>& fields) const;
 
-  // Returns an array of all fields of this class and its superclasses indexed
-  // by offset in words.
+  // Returns an array of all instance fields of this class and its superclasses
+  // indexed by offset in words.
   RawArray* OffsetToFieldMap() const;
 
   // Returns true if non-static fields are defined.
@@ -1194,7 +1195,8 @@
   RawField* LookupInstanceField(const String& name) const;
   RawField* LookupStaticField(const String& name) const;
   RawField* LookupField(const String& name) const;
-  RawField* LookupFieldAllowPrivate(const String& name) const;
+  RawField* LookupFieldAllowPrivate(const String& name,
+                                    bool instance_only = false) const;
   RawField* LookupInstanceFieldAllowPrivate(const String& name) const;
   RawField* LookupStaticFieldAllowPrivate(const String& name) const;
 
@@ -1326,6 +1328,7 @@
   void DisableAllocationStub() const;
 
   RawArray* constants() const;
+  void set_constants(const Array& value) const;
 
   intptr_t FindInvocationDispatcherFunctionIndex(const Function& needle) const;
   RawFunction* InvocationDispatcherFunctionFromIndex(intptr_t idx) const;
@@ -1400,9 +1403,18 @@
   void PatchFieldsAndFunctions() const;
   void CopyCanonicalConstants(const Class& old_cls) const;
   void CopyCanonicalType(const Class& old_cls) const;
-  bool CanReload(const Class& replacement) const;
+  void CheckReload(const Class& replacement,
+                   IsolateReloadContext* context) const;
 
  private:
+  bool CanReloadFinalized(const Class& replacement,
+                          IsolateReloadContext* context) const;
+  bool CanReloadPreFinalized(const Class& replacement,
+                             IsolateReloadContext* context) const;
+
+  // Tells whether instances need morphing for reload.
+  bool RequiresInstanceMorphing(const Class& replacement) const;
+
   template <class FakeObject> static RawClass* NewCommon(intptr_t index);
 
   enum MemberKind {
@@ -1459,8 +1471,6 @@
   RawString* GenerateUserVisibleName() const;
   void set_state_bits(intptr_t bits) const;
 
-  void set_constants(const Array& value) const;
-
   void set_canonical_type(const Type& value) const;
   RawType* canonical_type() const;
 
@@ -1861,7 +1871,6 @@
     V(CheckClass)                                                              \
     V(CheckArrayBound)                                                         \
     V(AtCall)                                                                  \
-    V(Uint32Load)                                                              \
     V(GuardField)                                                              \
     V(TestCids)                                                                \
     V(NumReasons)                                                              \
@@ -2055,78 +2064,6 @@
   void GetUsedCidsForTwoArgs(GrowableArray<intptr_t>* first,
                              GrowableArray<intptr_t>* second) const;
 
-  // Range feedback tracking functionality.
-
-  // For arithmetic operations we store range information for inputs and the
-  // result. The goal is to discover:
-  //
-  //    - on 32-bit platforms:
-  //         - when Mint operation is actually a int32/uint32 operation;
-  //         - when Smi operation produces non-smi results;
-  //
-  //    - on 64-bit platforms:
-  //         - when Smi operation is actually int32/uint32 operation;
-  //         - when Mint operation produces non-smi results;
-  //
-  enum RangeFeedback {
-    kSmiRange,
-    kInt32Range,
-    kUint32Range,
-    kInt64Range
-  };
-
-  // We use 4 bits per operand/result feedback. Our lattice allows us to
-  // express the following states:
-  //
-  //   - usmi   0000 [used only on 32bit platforms]
-  //   - smi    0001
-  //   - uint31 0010
-  //   - int32  0011
-  //   - uint32 0100
-  //   - int33  x1x1
-  //   - int64  1xxx
-  //
-  // DecodeRangeFeedbackAt() helper maps these states into the RangeFeedback
-  // enumeration.
-  enum RangeFeedbackLatticeBits {
-    kSignedRangeBit = 1 << 0,
-    kInt32RangeBit = 1 << 1,
-    kUint32RangeBit = 1 << 2,
-    kInt64RangeBit = 1 << 3,
-    kBitsPerRangeFeedback = 4,
-    kRangeFeedbackMask = (1 << kBitsPerRangeFeedback) - 1,
-    kRangeFeedbackSlots = 3
-  };
-
-  static bool IsValidRangeFeedbackIndex(intptr_t index) {
-    return (0 <= index) && (index < kRangeFeedbackSlots);
-  }
-
-  static intptr_t RangeFeedbackShift(intptr_t index) {
-    return (index * kBitsPerRangeFeedback) + kRangeFeedbackPos;
-  }
-
-  static const char* RangeFeedbackToString(RangeFeedback feedback) {
-    switch (feedback) {
-      case kSmiRange:
-        return "smi";
-      case kInt32Range:
-        return "int32";
-      case kUint32Range:
-        return "uint32";
-      case kInt64Range:
-        return "int64";
-      default:
-        UNREACHABLE();
-        return "?";
-    }
-  }
-
-  // It is only meaningful to interpret range feedback stored in the ICData
-  // when all checks are Mint or Smi.
-  bool HasRangeFeedback() const;
-  RangeFeedback DecodeRangeFeedbackAt(intptr_t idx) const;
-
   void PrintToJSONArray(const JSONArray& jsarray,
                         TokenPosition token_pos,
                         bool is_static_call) const;
@@ -2164,14 +2101,14 @@
   void set_ic_data_array(const Array& value) const;
   void set_state_bits(uint32_t bits) const;
 
+  bool ValidateInterceptor(const Function& target) const;
+
   enum {
     kNumArgsTestedPos = 0,
     kNumArgsTestedSize = 2,
     kDeoptReasonPos = kNumArgsTestedPos + kNumArgsTestedSize,
     kDeoptReasonSize = kLastRecordedDeoptReason + 1,
-    kRangeFeedbackPos = kDeoptReasonPos + kDeoptReasonSize,
-    kRangeFeedbackSize = kBitsPerRangeFeedback * kRangeFeedbackSlots,
-    kStaticCallPos = kRangeFeedbackPos + kRangeFeedbackSize,
+    kStaticCallPos = kDeoptReasonPos + kDeoptReasonSize,
     kStaticCallSize = 1,
   };
 
@@ -2183,11 +2120,6 @@
                                           uint32_t,
                                           ICData::kDeoptReasonPos,
                                           ICData::kDeoptReasonSize> {};
-  class RangeFeedbackBits : public BitField<uint32_t,
-                                            uint32_t,
-                                            ICData::kRangeFeedbackPos,
-                                            ICData::kRangeFeedbackSize> {};
-
   class StaticCallBit : public BitField<uint32_t,
                                         bool,
                                         ICData::kStaticCallPos,
@@ -2814,8 +2746,8 @@
   void set_modifier(RawFunction::AsyncModifier value) const;
 
   // 'was_compiled' is true if the function was compiled once in this
-  // VM instantiation. It independent from presence of type feedback
-  // (ic_data_array) and code, whihc may be loaded from a snapshot.
+  // VM instantiation. It is independent from presence of type feedback
+  // (ic_data_array) and code, which may be loaded from a snapshot.
   void set_was_compiled(bool value) const {
     StoreNonPointer(&raw_ptr()->was_compiled_, value ? 1 : 0);
   }
@@ -3048,6 +2980,7 @@
   virtual RawString* DictionaryName() const { return name(); }
 
   bool is_static() const { return StaticBit::decode(raw_ptr()->kind_bits_); }
+  bool is_instance() const { return !is_static(); }
   bool is_final() const { return FinalBit::decode(raw_ptr()->kind_bits_); }
   bool is_const() const { return ConstBit::decode(raw_ptr()->kind_bits_); }
   bool is_reflectable() const {
@@ -3477,6 +3410,11 @@
   // The load time in milliseconds since epoch.
   int64_t load_timestamp() const { return raw_ptr()->load_timestamp_; }
 
+  RawArray* compile_time_constants() const {
+    return raw_ptr()->compile_time_constants_;
+  }
+  void set_compile_time_constants(const Array& value) const;
+
   RawTokenStream* tokens() const { return raw_ptr()->tokens_; }
 
   void Tokenize(const String& private_key,
@@ -3524,6 +3462,7 @@
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Script, Object);
   friend class Class;
+  friend class Precompiler;
 };
 
 
@@ -3807,7 +3746,8 @@
   // the library-specific key.
   static const char kPrivateKeySeparator = '@';
 
-  bool CanReload(const Library& replacement) const;
+  void CheckReload(const Library& replacement,
+                   IsolateReloadContext* context) const;
 
  private:
   static const int kInitialImportsCapacity = 4;
@@ -3823,8 +3763,7 @@
   void InitClassDictionary() const;
 
   RawArray* resolved_names() const { return raw_ptr()->resolved_names_; }
-  void InitResolvedNamesCache(intptr_t size,
-                              SnapshotReader* reader = NULL) const;
+  void InitResolvedNamesCache(intptr_t size) const;
   void AllocateExportedNamesCache() const;
   void InitExportedNamesCache() const;
   static void InvalidateExportedNamesCaches();
@@ -5318,6 +5257,11 @@
   virtual bool CheckAndCanonicalizeFields(Thread* thread,
                                           const char** error_str) const;
 
+#if defined(DEBUG)
+  // Check if instance is canonical.
+  virtual bool CheckIsCanonical(Thread* thread) const;
+#endif  // DEBUG
+
   RawObject* GetField(const Field& field) const {
     return *FieldAddr(field);
   }
@@ -5398,7 +5342,6 @@
   RawObject** NativeFieldsAddr() const {
     return FieldAddrAtOffset(sizeof(RawObject));
   }
-
   void SetFieldAtOffset(intptr_t offset, const Object& value) const {
     StorePointer(FieldAddrAtOffset(offset), value.raw());
   }
@@ -5408,6 +5351,18 @@
     return sizeof(RawInstance);
   }
 
+  // The follwoing raw methods are used for morphing.
+  // They are needed due to the extraction of the class in IsValidFieldOffset.
+  RawObject** RawFieldAddrAtOffset(intptr_t offset) const {
+    return reinterpret_cast<RawObject**>(raw_value() - kHeapObjectTag + offset);
+  }
+  RawObject* RawGetFieldAtOffset(intptr_t offset) const {
+    return *RawFieldAddrAtOffset(offset);
+  }
+  void RawSetFieldAtOffset(intptr_t offset, const Object& value) const {
+    StorePointer(RawFieldAddrAtOffset(offset), value.raw());
+  }
+
   // TODO(iposva): Determine if this gets in the way of Smi.
   HEAP_OBJECT_IMPLEMENTATION(Instance, Object);
   friend class ByteBuffer;
@@ -5421,6 +5376,7 @@
   friend class InstanceSerializationCluster;
   friend class InstanceDeserializationCluster;
   friend class ClassDeserializationCluster;  // vtable
+  friend class InstanceMorpher;
 };
 
 
@@ -5552,6 +5508,14 @@
   // Return the canonical version of this type.
   virtual RawAbstractType* Canonicalize(TrailPtr trail = NULL) const;
 
+#if defined(DEBUG)
+  // Check if abstract type is canonical.
+  virtual bool CheckIsCanonical(Thread* thread) const {
+    UNREACHABLE();
+    return false;
+  }
+#endif  // DEBUG
+
   // Return the object associated with the receiver in the trail or
   // AbstractType::null() if the receiver is not contained in the trail.
   RawAbstractType* OnlyBuddyInTrail(TrailPtr trail) const;
@@ -5743,6 +5707,10 @@
       const Class& new_owner,
       TrailPtr trail = NULL) const;
   virtual RawAbstractType* Canonicalize(TrailPtr trail = NULL) const;
+#if defined(DEBUG)
+  // Check if type is canonical.
+  virtual bool CheckIsCanonical(Thread* thread) const;
+#endif  // DEBUG
   virtual RawString* EnumerateURIs() const;
 
   virtual intptr_t Hash() const;
@@ -5871,6 +5839,10 @@
       const Class& new_owner,
       TrailPtr trail = NULL) const;
   virtual RawAbstractType* Canonicalize(TrailPtr trail = NULL) const;
+#if defined(DEBUG)
+  // Check if typeref is canonical.
+  virtual bool CheckIsCanonical(Thread* thread) const;
+#endif  // DEBUG
   virtual RawString* EnumerateURIs() const;
 
   virtual intptr_t Hash() const;
@@ -5946,6 +5918,12 @@
   virtual RawAbstractType* Canonicalize(TrailPtr trail = NULL) const {
     return raw();
   }
+#if defined(DEBUG)
+  // Check if type parameter is canonical.
+  virtual bool CheckIsCanonical(Thread* thread) const {
+    return true;
+  }
+#endif  // DEBUG
   virtual RawString* EnumerateURIs() const;
 
   virtual intptr_t Hash() const;
@@ -6036,6 +6014,12 @@
   virtual RawAbstractType* Canonicalize(TrailPtr trail = NULL) const {
     return raw();
   }
+#if defined(DEBUG)
+  // Check if bounded type is canonical.
+  virtual bool CheckIsCanonical(Thread* thread) const {
+    return true;
+  }
+#endif  // DEBUG
   virtual RawString* EnumerateURIs() const;
 
   virtual intptr_t Hash() const;
@@ -6124,6 +6108,11 @@
   virtual RawInstance* CheckAndCanonicalize(Thread* thread,
                                             const char** error_str) const;
 
+#if defined(DEBUG)
+  // Check if number is canonical.
+  virtual bool CheckIsCanonical(Thread* thread) const;
+#endif  // DEBUG
+
  private:
   OBJECT_IMPLEMENTATION(Number, Instance);
 
@@ -6600,6 +6589,11 @@
   virtual RawInstance* CheckAndCanonicalize(Thread* thread,
                                             const char** error_str) const;
 
+#if defined(DEBUG)
+  // Check if string is canonical.
+  virtual bool CheckIsCanonical(Thread* thread) const;
+#endif  // DEBUG
+
   bool IsSymbol() const { return raw()->IsCanonical(); }
 
   bool IsOneByteString() const {
@@ -8531,9 +8525,7 @@
 
 
 DART_FORCE_INLINE void Object::SetRaw(RawObject* value) {
-  // NOTE: The assignment "raw_ = value" should be the first statement in
-  // this function. Also do not use 'value' in this function after the
-  // assignment (use 'raw_' instead).
+  NoSafepointScope no_safepoint_scope;
   raw_ = value;
   if ((reinterpret_cast<uword>(value) & kSmiTagMask) == kSmiTag) {
     set_vtable(Smi::handle_vtable_);
@@ -8560,14 +8552,14 @@
 
 
 intptr_t Field::Offset() const {
-  ASSERT(!is_static());  // Valid only for dart instance fields.
+  ASSERT(is_instance());  // Valid only for dart instance fields.
   intptr_t value = Smi::Value(raw_ptr()->value_.offset_);
   return (value * kWordSize);
 }
 
 
 void Field::SetOffset(intptr_t offset_in_bytes) const {
-  ASSERT(!is_static());  // Valid only for dart instance fields.
+  ASSERT(is_instance());  // Valid only for dart instance fields.
   ASSERT(kWordSize != 0);
   StorePointer(&raw_ptr()->value_.offset_,
                Smi::New(offset_in_bytes / kWordSize));
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index f9c5ad9..577cb91 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -4,6 +4,7 @@
 
 #include "vm/object.h"
 
+#include "vm/hash_table.h"
 #include "vm/isolate_reload.h"
 #include "vm/log.h"
 #include "vm/resolver.h"
@@ -14,9 +15,9 @@
 #ifndef PRODUCT
 
 DECLARE_FLAG(bool, trace_reload);
+DECLARE_FLAG(bool, trace_reload_verbose);
 DECLARE_FLAG(bool, two_args_smi_icd);
 
-#define IRC (Isolate::Current()->reload_context())
 
 class ObjectReloadUtils : public AllStatic {
   static void DumpLibraryDictionary(const Library& lib) {
@@ -141,6 +142,8 @@
 
 void Class::CopyCanonicalConstants(const Class& old_cls) const {
   if (is_enum_class()) {
+    // We do not copy enum classes's canonical constants because we explicitly
+    // become the old enum values to the new enum values.
     return;
   }
 #if defined(DEBUG)
@@ -171,31 +174,47 @@
 }
 
 
-static intptr_t IndexOfEnum(const Array& enum_names, const String& name) {
-  ASSERT(!enum_names.IsNull());
-  ASSERT(!name.IsNull());
-  String& enum_name = String::Handle();
-  for (intptr_t i = 0; i < enum_names.Length(); i++) {
-    enum_name = String::RawCast(enum_names.At(i));
-    ASSERT(!enum_name.IsNull());
-    if (enum_name.Equals(name)) {
-      return i;
-    }
+class EnumMapTraits {
+ public:
+  static bool ReportStats() { return false; }
+  static const char* Name() { return "EnumMapTraits"; }
+
+  static bool IsMatch(const Object& a, const Object& b) {
+    return a.raw() == b.raw();
   }
 
-  return -1;
-}
+  static uword Hash(const Object& obj) {
+    ASSERT(obj.IsString());
+    return String::Cast(obj).Hash();
+  }
+};
 
 
-static void UpdateEnumIndex(const Instance& enum_value,
-                            const Field& enum_index_field,
-                            const intptr_t index) {
-  enum_value.SetField(enum_index_field, Smi::Handle(Smi::New(index)));
-}
-
-
-// TODO(johnmccutchan): The code in the class finalizer canonicalizes all
-// instances and the values array. We probably should do the same thing.
+// Given an old enum class, add become mappings from old values to new values.
+// Some notes about how we reload enums below:
+//
+// When an enum is reloaded the following three things can happen, possibly
+// simultaneously.
+//
+// 1) A new enum value is added.
+//   This case is handled automatically.
+// 2) Enum values are reordered.
+//   We pair old and new enums and the old enums 'become' the new ones so
+//   the ordering is always correct (i.e. enum indicies match slots in values
+//   array)
+// 3) An existing enum value is removed.
+//   We leave old enum values that have no mapping to the reloaded class
+//   in the heap. This means that if a programmer does the following:
+//   enum Foo { A, B }; var x = Foo.A;
+//   *reload*
+//   enum Foo { B };
+//   *reload*
+//   enum Foo { A, B }; expect(identical(x, Foo.A));
+//   The program will fail because we were not able to pair Foo.A on the second
+//   reload.
+//
+//   Deleted enum values still in the heap continue to function but their
+//   index field will not be valid.
 void Class::ReplaceEnum(const Class& old_enum) const {
   // We only do this for finalized enum classes.
   ASSERT(is_enum_class());
@@ -204,160 +223,98 @@
   ASSERT(old_enum.is_finalized());
 
   Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
   IsolateReloadContext* reload_context = Isolate::Current()->reload_context();
   ASSERT(reload_context != NULL);
 
-  TIR_Print("ReplaceEnum `%s` (%" Pd " and %" Pd ")\n",
-            ToCString(), id(), old_enum.id());
+  Array& enum_fields = Array::Handle(zone);
+  Field& field = Field::Handle(zone);
+  String& enum_ident = String::Handle();
+  Instance& old_enum_value = Instance::Handle(zone);
+  Instance& enum_value = Instance::Handle(zone);
 
-  // Grab '_enum_names' from |old_enum|.
-  const Field& old_enum_names_field = Field::Handle(
-      old_enum.LookupStaticFieldAllowPrivate(Symbols::_EnumNames()));
-  ASSERT(!old_enum_names_field.IsNull());
-  const Array& old_enum_names =
-      Array::Handle(Array::RawCast(old_enum_names_field.StaticValue()));
-  ASSERT(!old_enum_names.IsNull());
+  Array& enum_map_storage = Array::Handle(zone,
+      HashTables::New<UnorderedHashMap<EnumMapTraits> >(4));
+  ASSERT(!enum_map_storage.IsNull());
 
-  // Grab 'values' from |old_enum|.
-  const Field& old_enum_values_field = Field::Handle(
-      old_enum.LookupStaticField(Symbols::Values()));
-  ASSERT(!old_enum_values_field.IsNull());
-  const Array& old_enum_values =
-      Array::Handle(Array::RawCast(old_enum_values_field.StaticValue()));
-  ASSERT(!old_enum_values.IsNull());
+  TIR_Print("Replacing enum `%s`\n", String::Handle(Name()).ToCString());
 
-  // Grab _enum_names from |this|.
-  const Field& enum_names_field = Field::Handle(
-      LookupStaticFieldAllowPrivate(Symbols::_EnumNames()));
-  ASSERT(!enum_names_field.IsNull());
-  Array& enum_names =
-      Array::Handle(Array::RawCast(enum_names_field.StaticValue()));
-  ASSERT(!enum_names.IsNull());
-
-  // Grab values from |this|.
-  const Field& enum_values_field = Field::Handle(
-      LookupStaticField(Symbols::Values()));
-  ASSERT(!enum_values_field.IsNull());
-  Array& enum_values =
-      Array::Handle(Array::RawCast(enum_values_field.StaticValue()));
-  ASSERT(!enum_values.IsNull());
-
-  // Grab the |index| field.
-  const Field& index_field =
-      Field::Handle(old_enum.LookupInstanceField(Symbols::Index()));
-  ASSERT(!index_field.IsNull());
-
-  // Build list of enum from |old_enum| that aren't present in |this|.
-  // This array holds pairs: (name, value).
-  const GrowableObjectArray& to_add =
-      GrowableObjectArray::Handle(GrowableObjectArray::New(Heap::kOld));
-  const String& enum_class_name = String::Handle(UserVisibleName());
-  String& enum_name = String::Handle();
-  String& enum_field_name = String::Handle();
-  Object& enum_value = Object::Handle();
-  Field& enum_field = Field::Handle();
-
-  TIR_Print("New version of enum has %" Pd " elements\n",
-            enum_values.Length());
-  TIR_Print("Old version of enum had %" Pd " elements\n",
-            old_enum_values.Length());
-
-  for (intptr_t i = 0; i < old_enum_names.Length(); i++) {
-    enum_name = String::RawCast(old_enum_names.At(i));
-    const intptr_t index_in_new_cls = IndexOfEnum(enum_names, enum_name);
-    if (index_in_new_cls < 0) {
-      // Doesn't exist in new enum, add.
-      TIR_Print("Adding enum value `%s` to %s\n",
-                enum_name.ToCString(),
-                this->ToCString());
-      enum_value = old_enum_values.At(i);
-      ASSERT(!enum_value.IsNull());
-      to_add.Add(enum_name);
-      to_add.Add(enum_value);
-    } else {
-      // Exists in both the new and the old.
-      TIR_Print("Moving enum value `%s` to %" Pd "\n",
-                enum_name.ToCString(),
-                index_in_new_cls);
-      // Grab old value.
-      enum_value = old_enum_values.At(i);
-      // Update index to the be new index.
-      UpdateEnumIndex(Instance::Cast(enum_value),
-                      index_field,
-                      index_in_new_cls);
-      // Chop off the 'EnumClass.'
-      enum_field_name = String::SubString(enum_name,
-                                          enum_class_name.Length() + 1);
-      ASSERT(!enum_field_name.IsNull());
-      // Grab the static field.
-      enum_field = LookupStaticField(enum_field_name);
-      ASSERT(!enum_field.IsNull());
-      // Use old value with updated index.
-      enum_field.SetStaticValue(Instance::Cast(enum_value), true);
-      enum_values.SetAt(index_in_new_cls, enum_value);
-      enum_names.SetAt(index_in_new_cls, enum_name);
+  {
+    UnorderedHashMap<EnumMapTraits> enum_map(enum_map_storage.raw());
+    // Build a map of all enum name -> old enum instance.
+    enum_fields = old_enum.fields();
+    for (intptr_t i = 0; i < enum_fields.Length(); i++) {
+      field = Field::RawCast(enum_fields.At(i));
+      enum_ident = field.name();
+      if (!field.is_static()) {
+        // Enum instances are only held in static fields.
+        continue;
+      }
+      if (enum_ident.Equals(Symbols::Values())) {
+        // Non-enum instance.
+        continue;
+      }
+      old_enum_value = field.StaticValue();
+      ASSERT(!old_enum_value.IsNull());
+      VTIR_Print("Element %s being added to mapping\n", enum_ident.ToCString());
+      bool update = enum_map.UpdateOrInsert(enum_ident, old_enum_value);
+      VTIR_Print("Element %s added to mapping\n", enum_ident.ToCString());
+      ASSERT(!update);
     }
+    // The storage given to the map may have been reallocated, remember the new
+    // address.
+    enum_map_storage = enum_map.Release().raw();
   }
 
-  if (to_add.Length() == 0) {
-    // Nothing to do.
-    TIR_Print("Found no missing enums in %s\n", ToCString());
-    return;
+  bool enums_deleted = false;
+  {
+    UnorderedHashMap<EnumMapTraits> enum_map(enum_map_storage.raw());
+    // Add a become mapping from the old instances to the new instances.
+    enum_fields = fields();
+    for (intptr_t i = 0; i < enum_fields.Length(); i++) {
+      field = Field::RawCast(enum_fields.At(i));
+      enum_ident = field.name();
+      if (!field.is_static()) {
+        // Enum instances are only held in static fields.
+        continue;
+      }
+      if (enum_ident.Equals(Symbols::Values())) {
+        // Non-enum instance.
+        continue;
+      }
+      enum_value = field.StaticValue();
+      ASSERT(!enum_value.IsNull());
+      old_enum_value ^= enum_map.GetOrNull(enum_ident);
+      if (old_enum_value.IsNull()) {
+        VTIR_Print("New element %s was not found in mapping\n",
+                   enum_ident.ToCString());
+      } else {
+        VTIR_Print("Adding element `%s` to become mapping\n",
+                   enum_ident.ToCString());
+        bool removed = enum_map.Remove(enum_ident);
+        ASSERT(removed);
+        reload_context->AddEnumBecomeMapping(old_enum_value, enum_value);
+      }
+    }
+    enums_deleted = enum_map.NumOccupied() > 0;
+    // The storage given to the map may have been reallocated, remember the new
+    // address.
+    enum_map_storage = enum_map.Release().raw();
   }
 
-  // Grow the values and enum_names arrays.
-  const intptr_t offset = enum_names.Length();
-  const intptr_t num_to_add = to_add.Length() / 2;
-  ASSERT(offset == enum_values.Length());
-  enum_names = Array::Grow(enum_names,
-                           enum_names.Length() + num_to_add,
-                           Heap::kOld);
-  enum_values = Array::Grow(enum_values,
-                            enum_values.Length() + num_to_add,
-                            Heap::kOld);
-
-  // Install new names and values into the grown arrays. Also, update
-  // the index of the new enum values and add static fields for the new
-  // enum values.
-  Field& enum_value_field = Field::Handle();
-  for (intptr_t i = 0; i < num_to_add; i++) {
-    const intptr_t target_index = offset + i;
-    enum_name = String::RawCast(to_add.At(i * 2));
-    enum_value = to_add.At(i * 2 + 1);
-
-    // Update the enum value's index into the new arrays.
-    TIR_Print("Updating index of %s in %s to %" Pd "\n",
-              enum_name.ToCString(),
-              ToCString(),
-              target_index);
-    UpdateEnumIndex(Instance::Cast(enum_value), index_field, target_index);
-
-    enum_names.SetAt(target_index, enum_name);
-    enum_values.SetAt(target_index, enum_value);
-
-    // Install new static field into class.
-    // Chop off the 'EnumClass.'
-    enum_field_name = String::SubString(enum_name,
-                                        enum_class_name.Length() + 1);
-    ASSERT(!enum_field_name.IsNull());
-    enum_field_name = Symbols::New(thread, enum_field_name);
-    enum_value_field = Field::New(enum_field_name,
-                                  /* is_static = */ true,
-                                  /* is_final = */ true,
-                                  /* is_const = */ true,
-                                  /* is_reflectable = */ true,
-                                  *this,
-                                  Object::dynamic_type(),
-                                  token_pos());
-    enum_value_field.set_has_initializer(false);
-    enum_value_field.SetStaticValue(Instance::Cast(enum_value), true);
-    enum_value_field.RecordStore(Instance::Cast(enum_value));
-    AddField(enum_value_field);
+  if (enums_deleted && FLAG_trace_reload_verbose) {
+    // TODO(johnmccutchan): Add this to the reload 'notices' list.
+    VTIR_Print("The following enum values were deleted and are forever lost in "
+               "the heap:\n");
+    UnorderedHashMap<EnumMapTraits> enum_map(enum_map_storage.raw());
+    UnorderedHashMap<EnumMapTraits>::Iterator it(&enum_map);
+    while (it.MoveNext()) {
+      const intptr_t entry = it.Current();
+      enum_ident = String::RawCast(enum_map.GetKey(entry));
+      ASSERT(!enum_ident.IsNull());
+    }
+    enum_map.Release();
   }
-
-  // Replace the arrays stored in the static fields.
-  enum_names_field.SetStaticValue(enum_names, true);
-  enum_values_field.SetStaticValue(enum_values, true);
 }
 
 
@@ -406,133 +363,257 @@
 }
 
 
-bool Class::CanReload(const Class& replacement) const {
+class EnumClassConflict : public ClassReasonForCancelling {
+ public:
+  EnumClassConflict(const Class& from, const Class& to)
+      : ClassReasonForCancelling(from, to) { }
+
+  RawString* ToString() {
+    return String::NewFormatted(
+        from_.is_enum_class()
+        ? "Enum class cannot be redefined to be a non-enum class: %s"
+        : "Class cannot be redefined to be a enum class: %s",
+        from_.ToCString());
+  }
+};
+
+
+class EnsureFinalizedError : public ClassReasonForCancelling {
+ public:
+  EnsureFinalizedError(const Class& from, const Class& to, const Error& error)
+      : ClassReasonForCancelling(from, to), error_(error) { }
+
+ private:
+  const Error& error_;
+
+  RawError* ToError() { return error_.raw(); }
+};
+
+
+class NativeFieldsConflict : public ClassReasonForCancelling {
+ public:
+  NativeFieldsConflict(const Class& from, const Class& to)
+      : ClassReasonForCancelling(from, to) { }
+
+ private:
+  RawString* ToString() {
+    return String::NewFormatted(
+        "Number of native fields changed in %s", from_.ToCString());
+  }
+};
+
+
+class TypeParametersChanged : public ClassReasonForCancelling {
+ public:
+  TypeParametersChanged(const Class& from, const Class& to)
+      : ClassReasonForCancelling(from, to) {}
+
+  RawString* ToString() {
+    return String::NewFormatted(
+        "Limitation: type parameters have changed for %s", from_.ToCString());
+  }
+};
+
+
+class PreFinalizedConflict :  public ClassReasonForCancelling {
+ public:
+  PreFinalizedConflict(const Class& from, const Class& to)
+      : ClassReasonForCancelling(from, to) {}
+
+ private:
+  RawString* ToString() {
+    return String::NewFormatted(
+        "Original class ('%s') is prefinalized and replacement class "
+        "('%s') is not ",
+        from_.ToCString(), to_.ToCString());
+  }
+};
+
+
+class InstanceSizeConflict :  public ClassReasonForCancelling {
+ public:
+  InstanceSizeConflict(const Class& from, const Class& to)
+      : ClassReasonForCancelling(from, to) {}
+
+ private:
+  RawString* ToString() {
+    return String::NewFormatted(
+        "Instance size mismatch between '%s' (%" Pd ") and replacement "
+        "'%s' ( %" Pd ")",
+        from_.ToCString(),
+        from_.instance_size(),
+        to_.ToCString(),
+        to_.instance_size());
+  }
+};
+
+
+class UnimplementedDeferredLibrary : public ReasonForCancelling {
+ public:
+  UnimplementedDeferredLibrary(const Library& from,
+                               const Library& to,
+                               const String& name)
+      : ReasonForCancelling(), from_(from), to_(to), name_(name) {}
+
+ private:
+  const Library& from_;
+  const Library& to_;
+  const String& name_;
+
+  RawString* ToString() {
+    const String& lib_url = String::Handle(to_.url());
+    from_.ToCString();
+    return String::NewFormatted(
+        "Reloading support for deferred loading has not yet been implemented:"
+        " library '%s' has deferred import '%s'",
+        lib_url.ToCString(), name_.ToCString());
+  }
+};
+
+
+// This is executed before interating over the instances.
+void Class::CheckReload(const Class& replacement,
+                        IsolateReloadContext* context) const {
   ASSERT(IsolateReloadContext::IsSameClass(*this, replacement));
 
-  if (is_enum_class() && !replacement.is_enum_class()) {
-    IRC->ReportError(String::Handle(String::NewFormatted(
-        "Enum class cannot be redefined to be a non-enum class: %s",
-        ToCString())));
-    return false;
-  }
-
-  if (!is_enum_class() && replacement.is_enum_class()) {
-    IRC->ReportError(String::Handle(String::NewFormatted(
-        "Class cannot be redefined to be a enum class: %s",
-        ToCString())));
-    return false;
+  // Class cannot change enum property.
+  if (is_enum_class() != replacement.is_enum_class()) {
+    context->AddReasonForCancelling(
+        new EnumClassConflict(*this, replacement));
+    return;
   }
 
   if (is_finalized()) {
+    // Ensure the replacement class is also finalized.
     const Error& error =
         Error::Handle(replacement.EnsureIsFinalized(Thread::Current()));
     if (!error.IsNull()) {
-      IRC->ReportError(error);
-      return false;
+      context->AddReasonForCancelling(
+          new EnsureFinalizedError(*this, replacement, error));
+      return;  // No reason to check other properties.
     }
     TIR_Print("Finalized replacement class for %s\n", ToCString());
   }
 
-  // At this point the original and replacement must be in the same state.
-  ASSERT(is_finalized() == replacement.is_finalized());
+  // Native field count cannot change.
+  if (num_native_fields() != replacement.num_native_fields()) {
+      context->AddReasonForCancelling(
+          new NativeFieldsConflict(*this, replacement));
+      return;
+  }
+
+  // Just checking.
+  ASSERT(is_enum_class() == replacement.is_enum_class());
+  ASSERT(num_native_fields() == replacement.num_native_fields());
 
   if (is_finalized()) {
-    // Get the field maps for both classes. These field maps walk the class
-    // hierarchy.
-    const Array& fields =
-        Array::Handle(OffsetToFieldMap());
-    const Array& replacement_fields =
-        Array::Handle(replacement.OffsetToFieldMap());
-
-    // 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())));
-      return false;
-    }
-
-    // Verify that field names / offsets match across the entire hierarchy.
-    Field& field = Field::Handle();
-    String& field_name = String::Handle();
-    Field& replacement_field = Field::Handle();
-    String& replacement_field_name = String::Handle();
-    for (intptr_t i = 0; i < fields.Length(); i++) {
-      if (fields.At(i) == Field::null()) {
-        ASSERT(replacement_fields.At(i) == Field::null());
-        continue;
-      }
-      field = Field::RawCast(fields.At(i));
-      replacement_field = Field::RawCast(replacement_fields.At(i));
-      field_name = field.name();
-      replacement_field_name = replacement_field.name();
-      if (!field_name.Equals(replacement_field_name)) {
-        IRC->ReportError(String::Handle(String::NewFormatted(
-            "Name of instance field changed ('%s' vs '%s') in '%s'",
-            field_name.ToCString(),
-            replacement_field_name.ToCString(),
-            ToCString())));
-        return false;
-      }
-    }
-  } else if (is_prefinalized()) {
-    if (!replacement.is_prefinalized()) {
-      IRC->ReportError(String::Handle(String::NewFormatted(
-          "Original class ('%s') is prefinalized and replacement class "
-          "('%s') is not ",
-          ToCString(), replacement.ToCString())));
-      return false;
-    }
-    if (instance_size() != replacement.instance_size()) {
-     IRC->ReportError(String::Handle(String::NewFormatted(
-         "Instance size mismatch between '%s' (%" Pd ") and replacement "
-         "'%s' ( %" Pd ")",
-         ToCString(),
-         instance_size(),
-         replacement.ToCString(),
-         replacement.instance_size())));
-     return false;
-    }
+    if (!CanReloadFinalized(replacement, context)) return;
   }
+  if (is_prefinalized()) {
+    if (!CanReloadPreFinalized(replacement, context)) return;
+  }
+  ASSERT(is_finalized() == replacement.is_finalized());
+  TIR_Print("Class `%s` can be reloaded (%" Pd " and %" Pd ")\n",
+            ToCString(), id(), replacement.id());
+}
 
-  // native field count check.
-  if (num_native_fields() != replacement.num_native_fields()) {
-    IRC->ReportError(String::Handle(String::NewFormatted(
-        "Number of native fields changed in %s", ToCString())));
+
+
+bool Class::RequiresInstanceMorphing(const Class& replacement) const {
+  // Get the field maps for both classes. These field maps walk the class
+  // hierarchy.
+  const Array& fields = Array::Handle(OffsetToFieldMap());
+  const Array& replacement_fields
+      = Array::Handle(replacement.OffsetToFieldMap());
+
+  // Check that the size of the instance is the same.
+  if (fields.Length() != replacement_fields.Length()) return true;
+
+  // 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()) return true;
+
+  // Verify that field names / offsets match across the entire hierarchy.
+  Field& field = Field::Handle();
+  String& field_name = String::Handle();
+  Field& replacement_field = Field::Handle();
+  String& replacement_field_name = String::Handle();
+
+  for (intptr_t i = 0; i < fields.Length(); i++) {
+    if (fields.At(i) == Field::null()) {
+      ASSERT(replacement_fields.At(i) == Field::null());
+      continue;
+    }
+    field = Field::RawCast(fields.At(i));
+    replacement_field = Field::RawCast(replacement_fields.At(i));
+    field_name = field.name();
+    replacement_field_name = replacement_field.name();
+    if (!field_name.Equals(replacement_field_name)) return true;
+  }
+  return false;
+}
+
+
+bool Class::CanReloadFinalized(const Class& replacement,
+                               IsolateReloadContext* context) const {
+  // Make sure the declaration types matches for the two classes.
+  // ex. class A<int,B> {} cannot be replace with class A<B> {}.
+
+  const AbstractType& dt = AbstractType::Handle(DeclarationType());
+  const AbstractType& replacement_dt =
+      AbstractType::Handle(replacement.DeclarationType());
+  if (!dt.Equals(replacement_dt)) {
+    context->AddReasonForCancelling(
+        new TypeParametersChanged(*this, replacement));
     return false;
   }
-
-  // TODO(johnmccutchan) type parameter count check.
-
-  TIR_Print("Class `%s` can be reloaded (%" Pd " and %" Pd ")\n",
-            ToCString(),
-            id(),
-            replacement.id());
+  if (RequiresInstanceMorphing(replacement)) {
+    context->AddInstanceMorpher(new InstanceMorpher(*this, replacement));
+  }
   return true;
 }
 
 
-bool Library::CanReload(const Library& replacement) const {
+bool Class::CanReloadPreFinalized(const Class& replacement,
+                                  IsolateReloadContext* context) const {
+  // The replacement class must also prefinalized.
+  if (!replacement.is_prefinalized()) {
+      context->AddReasonForCancelling(
+          new PreFinalizedConflict(*this, replacement));
+      return false;
+  }
+  // Check the instance sizes are equal.
+  if (instance_size() != replacement.instance_size()) {
+      context->AddReasonForCancelling(
+          new InstanceSizeConflict(*this, replacement));
+      return false;
+  }
   return true;
 }
 
 
+void Library::CheckReload(const Library& replacement,
+                          IsolateReloadContext* context) const {
+  // TODO(26878): If the replacement library uses deferred loading,
+  // reject it.  We do not yet support reloading deferred libraries.
+  LibraryPrefix& prefix = LibraryPrefix::Handle();
+  LibraryPrefixIterator it(replacement);
+  while (it.HasNext()) {
+    prefix = it.GetNext();
+    if (prefix.is_deferred_load()) {
+      const String& prefix_name = String::Handle(prefix.name());
+      context->AddReasonForCancelling(
+          new UnimplementedDeferredLibrary(*this, replacement, prefix_name));
+      return;
+    }
+  }
+}
+
+
 static const Function* static_call_target = NULL;
 
+
 void ICData::Reset() const {
   if (is_static_call()) {
     const Function& old_target = Function::Handle(GetTargetAt(0));
@@ -540,22 +621,62 @@
       FATAL("old_target is NULL.\n");
     }
     static_call_target = &old_target;
-    if (!old_target.is_static()) {
-      // TODO(johnmccutchan): Improve this.
-      TIR_Print("Cannot rebind super-call to %s from %s\n",
-                old_target.ToCString(),
-                Object::Handle(Owner()).ToCString());
-      return;
-    }
+
     const String& selector = String::Handle(old_target.name());
-    const Class& cls = Class::Handle(old_target.Owner());
-    const Function& new_target =
-        Function::Handle(cls.LookupStaticFunction(selector));
-    if (new_target.IsNull()) {
-      // TODO(johnmccutchan): Improve this.
-      TIR_Print("Cannot rebind static call to %s from %s\n",
-                old_target.ToCString(),
-                Object::Handle(Owner()).ToCString());
+    Function& new_target = Function::Handle();
+    if (!old_target.is_static()) {
+      if (old_target.kind() == RawFunction::kConstructor) {
+        return;  // Super constructor call.
+      }
+      Function& caller = Function::Handle();
+      caller ^= Owner();
+      ASSERT(!caller.is_static());
+      Class& cls = Class::Handle(caller.Owner());
+      if (cls.raw() == old_target.Owner()) {
+        // Dispatcher.
+        if (caller.IsImplicitClosureFunction()) {
+          return;  // Tear-off.
+        }
+        if (caller.kind() == RawFunction::kNoSuchMethodDispatcher) {
+          // TODO(rmacnak): noSuchMethod might have been redefined.
+          return;
+        }
+        const Function& caller_parent =
+            Function::Handle(caller.parent_function());
+        if (!caller_parent.IsNull()) {
+          if (caller_parent.kind() == RawFunction::kInvokeFieldDispatcher) {
+            return;  // Call-through-getter.
+          }
+        }
+        FATAL2("Unexpected dispatcher-like call site: %s from %s\n",
+               selector.ToCString(), caller.ToQualifiedCString());
+      }
+      // Super call.
+      cls = cls.SuperClass();
+      while (!cls.IsNull()) {
+        // TODO(rmacnak): Should use Resolver::ResolveDynamicAnyArgs to handle
+        // method-extractors and call-through-getters, but we're in a no
+        // safepoint scope here.
+        new_target = cls.LookupDynamicFunction(selector);
+        if (!new_target.IsNull()) {
+          break;
+        }
+        cls = cls.SuperClass();
+      }
+    } else {
+      // This can be incorrect if the call site was an unqualified invocation.
+      const Class& cls = Class::Handle(old_target.Owner());
+      new_target = cls.LookupStaticFunction(selector);
+    }
+
+    const Array& args_desc_array = Array::Handle(arguments_descriptor());
+    ArgumentsDescriptor args_desc(args_desc_array);
+    if (new_target.IsNull() ||
+        !new_target.AreValidArguments(args_desc, NULL)) {
+      // TODO(rmacnak): Patch to a NSME stub.
+      VTIR_Print("Cannot rebind static call to %s from %s\n",
+                 old_target.ToCString(),
+                 Object::Handle(Owner()).ToCString());
       return;
     }
     ClearAndSetStaticTarget(new_target);
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index e1ca9dd..e0bf805 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -89,8 +89,10 @@
     lookup_port_handler_(Function::null()),
     empty_uint32_array_(TypedData::null()),
     handle_message_function_(Function::null()),
+    simple_instance_of_function_(Function::null()),
+    simple_instance_of_true_function_(Function::null()),
+    simple_instance_of_false_function_(Function::null()),
     library_load_error_table_(Array::null()),
-    compile_time_constants_(Array::null()),
     unique_dynamic_targets_(Array::null()),
     token_objects_(GrowableObjectArray::null()),
     token_objects_map_(Array::null()),
@@ -120,6 +122,7 @@
 }
 
 
+#ifndef PRODUCT
 void ObjectStore::PrintToJSONObject(JSONObject* jsobj) {
   if (!FLAG_support_service) {
     return;
@@ -136,6 +139,7 @@
 #undef PRINT_OBJECT_STORE_FIELD
   }
 }
+#endif  // !PRODUCT
 
 
 RawError* ObjectStore::PreallocateObjects() {
@@ -202,6 +206,16 @@
 }
 
 
+RawFunction* ObjectStore::PrivateObjectLookup(const String& name) {
+  const Library& core_lib = Library::Handle(core_library());
+  const String& mangled = String::ZoneHandle(core_lib.PrivateName(name));
+  const Class& cls = Class::Handle(object_class());
+  const Function& result = Function::Handle(cls.LookupDynamicFunction(mangled));
+  ASSERT(!result.IsNull());
+  return result.raw();
+}
+
+
 void ObjectStore::InitKnownObjects() {
 #ifdef DART_PRECOMPILED_RUNTIME
   // These objects are only needed for code generation.
@@ -228,6 +242,14 @@
   const Library& internal_lib = Library::Handle(internal_library());
   cls = internal_lib.LookupClass(Symbols::Symbol());
   set_symbol_class(cls);
+
+  // Cache the core private functions used for fast instance of checks.
+  simple_instance_of_function_ =
+      PrivateObjectLookup(Symbols::_simpleInstanceOf());
+  simple_instance_of_true_function_ =
+      PrivateObjectLookup(Symbols::_simpleInstanceOfTrue());
+  simple_instance_of_false_function_ =
+      PrivateObjectLookup(Symbols::_simpleInstanceOfFalse());
 #endif
 }
 
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 6ab93de..e6d6293 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -440,13 +440,6 @@
     return OFFSET_OF(ObjectStore, library_load_error_table_);
   }
 
-  RawArray* compile_time_constants() const {
-    return compile_time_constants_;
-  }
-  void set_compile_time_constants(const Array& value) {
-    compile_time_constants_ = value.raw();
-  }
-
   RawArray* unique_dynamic_targets() const {
     return unique_dynamic_targets_;
   }
@@ -486,6 +479,16 @@
     megamorphic_miss_function_ = func.raw();
   }
 
+  RawFunction* simple_instance_of_function() const {
+    return simple_instance_of_function_;
+  }
+  RawFunction* simple_instance_of_true_function() const {
+    return simple_instance_of_true_function_;
+  }
+  RawFunction* simple_instance_of_false_function() const {
+    return simple_instance_of_false_function_;
+  }
+
   // Visit all object pointers.
   void VisitObjectPointers(ObjectPointerVisitor* visitor);
 
@@ -498,11 +501,16 @@
 
   static void Init(Isolate* isolate);
 
+#ifndef PRODUCT
   void PrintToJSONObject(JSONObject* jsobj);
+#endif
 
  private:
   ObjectStore();
 
+  // Finds a core library private method in Object.
+  RawFunction* PrivateObjectLookup(const String& name);
+
 #define OBJECT_STORE_FIELD_LIST(V)                                             \
   V(RawClass*, object_class_)                                                  \
   V(RawType*, object_type_)                                                    \
@@ -578,14 +586,17 @@
   V(RawFunction*, lookup_port_handler_)                                        \
   V(RawTypedData*, empty_uint32_array_)                                        \
   V(RawFunction*, handle_message_function_)                                    \
+  V(RawFunction*, simple_instance_of_function_)                                \
+  V(RawFunction*, simple_instance_of_true_function_)                           \
+  V(RawFunction*, simple_instance_of_false_function_)                          \
   V(RawArray*, library_load_error_table_)                                      \
-  V(RawArray*, compile_time_constants_)                                        \
   V(RawArray*, unique_dynamic_targets_)                                        \
   V(RawGrowableObjectArray*, token_objects_)                                   \
   V(RawArray*, token_objects_map_)                                             \
   V(RawGrowableObjectArray*, megamorphic_cache_table_)                         \
   V(RawCode*, megamorphic_miss_code_)                                          \
   V(RawFunction*, megamorphic_miss_function_)                                  \
+  // Please remember the last entry must be referred in the 'to' function below.
 
   RawObject** from() { return reinterpret_cast<RawObject**>(&object_class_); }
 #define DECLARE_OBJECT_STORE_FIELD(type, name)                                 \
@@ -598,7 +609,7 @@
   RawObject** to_snapshot(Snapshot::Kind kind) {
     switch (kind) {
       case Snapshot::kCore:
-        return reinterpret_cast<RawObject**>(&compile_time_constants_);
+        return reinterpret_cast<RawObject**>(&library_load_error_table_);
       case Snapshot::kAppWithJIT:
       case Snapshot::kAppNoJIT:
         return to();
diff --git a/runtime/vm/os_fuchsia.cc b/runtime/vm/os_fuchsia.cc
index 10faf1c..b634352 100644
--- a/runtime/vm/os_fuchsia.cc
+++ b/runtime/vm/os_fuchsia.cc
@@ -7,13 +7,22 @@
 
 #include "vm/os.h"
 
+#include <errno.h>
 #include <magenta/syscalls.h>
 #include <magenta/types.h>
 
 #include "platform/assert.h"
+#include "vm/zone.h"
 
 namespace dart {
 
+#ifndef PRODUCT
+
+DEFINE_FLAG(bool, generate_perf_events_symbols, false,
+    "Generate events symbols for profiling with perf");
+
+#endif  // !PRODUCT
+
 const char* OS::Name() {
   return "fuchsia";
 }
@@ -49,25 +58,24 @@
 
 
 int64_t OS::GetCurrentTimeMicros() {
-  return _magenta_current_time() / 1000;
+  return mx_current_time() / 1000;
 }
 
 
 int64_t OS::GetCurrentMonotonicTicks() {
-  UNIMPLEMENTED();
-  return 0;
+  return mx_current_time();
 }
 
 
 int64_t OS::GetCurrentMonotonicFrequency() {
-  UNIMPLEMENTED();
-  return 0;
+  return kNanosecondsPerSecond;
 }
 
 
 int64_t OS::GetCurrentMonotonicMicros() {
-  UNIMPLEMENTED();
-  return 0;
+  int64_t ticks = GetCurrentMonotonicTicks();
+  ASSERT(GetCurrentMonotonicFrequency() == kNanosecondsPerSecond);
+  return ticks / kNanosecondsPerMicrosecond;
 }
 
 
@@ -89,16 +97,45 @@
 
 
 // TODO(5411554):  May need to hoist these architecture dependent code
-// into a architecture specific file e.g: os_ia32_linux.cc
+// into a architecture specific file e.g: os_ia32_fuchsia.cc
 intptr_t OS::ActivationFrameAlignment() {
-  UNIMPLEMENTED();
-  return 0;
+#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) || \
+    defined(TARGET_ARCH_ARM64)
+  const int kMinimumAlignment = 16;
+#elif defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_DBC)
+  const int kMinimumAlignment = 8;
+#else
+#error Unsupported architecture.
+#endif
+  intptr_t alignment = kMinimumAlignment;
+  // TODO(5411554): Allow overriding default stack alignment for
+  // testing purposes.
+  // Flags::DebugIsInt("stackalign", &alignment);
+  ASSERT(Utils::IsPowerOfTwo(alignment));
+  ASSERT(alignment >= kMinimumAlignment);
+  return alignment;
 }
 
 
 intptr_t OS::PreferredCodeAlignment() {
-  UNIMPLEMENTED();
-  return 0;
+#if defined(TARGET_ARCH_IA32) ||                                               \
+    defined(TARGET_ARCH_X64) ||                                                \
+    defined(TARGET_ARCH_ARM64) ||                                              \
+    defined(TARGET_ARCH_DBC)
+  const int kMinimumAlignment = 32;
+#elif defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_MIPS)
+  const int kMinimumAlignment = 16;
+#else
+#error Unsupported architecture.
+#endif
+  intptr_t alignment = kMinimumAlignment;
+  // TODO(5411554): Allow overriding default code alignment for
+  // testing purposes.
+  // Flags::DebugIsInt("codealign", &alignment);
+  ASSERT(Utils::IsPowerOfTwo(alignment));
+  ASSERT(alignment >= kMinimumAlignment);
+  ASSERT(alignment <= OS::kMaxPreferredCodeAlignment);
+  return alignment;
 }
 
 
@@ -130,19 +167,20 @@
 
 
 char* OS::StrNDup(const char* s, intptr_t n) {
-  UNIMPLEMENTED();
-  return NULL;
+  return strndup(s, n);
 }
 
 
 intptr_t OS::StrNLen(const char* s, intptr_t n) {
-  UNIMPLEMENTED();
-  return 0;
+  return strnlen(s, n);
 }
 
 
 void OS::Print(const char* format, ...) {
-  UNIMPLEMENTED();
+  va_list args;
+  va_start(args, format);
+  VFPrint(stdout, format, args);
+  va_end(args);
 }
 
 
@@ -153,37 +191,81 @@
 
 
 int OS::SNPrint(char* str, size_t size, const char* format, ...) {
-  UNIMPLEMENTED();
-  return 0;
+  va_list args;
+  va_start(args, format);
+  int retval = VSNPrint(str, size, format, args);
+  va_end(args);
+  return retval;
 }
 
 
 int OS::VSNPrint(char* str, size_t size, const char* format, va_list args) {
-  UNIMPLEMENTED();
-  return 0;
+  int retval = vsnprintf(str, size, format, args);
+  if (retval < 0) {
+    FATAL1("Fatal error in OS::VSNPrint with format '%s'", format);
+  }
+  return retval;
 }
 
 
 char* OS::SCreate(Zone* zone, const char* format, ...) {
-  UNIMPLEMENTED();
-  return NULL;
+  va_list args;
+  va_start(args, format);
+  char* buffer = VSCreate(zone, format, args);
+  va_end(args);
+  return buffer;
 }
 
 
 char* OS::VSCreate(Zone* zone, const char* format, va_list args) {
-  UNIMPLEMENTED();
-  return NULL;
+  // Measure.
+  va_list measure_args;
+  va_copy(measure_args, args);
+  intptr_t len = VSNPrint(NULL, 0, format, measure_args);
+  va_end(measure_args);
+
+  char* buffer;
+  if (zone) {
+    buffer = zone->Alloc<char>(len + 1);
+  } else {
+    buffer = reinterpret_cast<char*>(malloc(len + 1));
+  }
+  ASSERT(buffer != NULL);
+
+  // Print.
+  va_list print_args;
+  va_copy(print_args, args);
+  VSNPrint(buffer, len + 1, format, print_args);
+  va_end(print_args);
+  return buffer;
 }
 
 
 bool OS::StringToInt64(const char* str, int64_t* value) {
-  UNIMPLEMENTED();
-  return false;
+  ASSERT(str != NULL && strlen(str) > 0 && value != NULL);
+  int32_t base = 10;
+  char* endptr;
+  int i = 0;
+  if (str[0] == '-') {
+    i = 1;
+  }
+  if ((str[i] == '0') &&
+      (str[i + 1] == 'x' || str[i + 1] == 'X') &&
+      (str[i + 2] != '\0')) {
+    base = 16;
+  }
+  errno = 0;
+  *value = strtoll(str, &endptr, base);
+  return ((errno == 0) && (endptr != str) && (*endptr == 0));
 }
 
 
 void OS::RegisterCodeObservers() {
-  UNIMPLEMENTED();
+#ifndef PRODUCT
+  if (FLAG_generate_perf_events_symbols) {
+    UNIMPLEMENTED();
+  }
+#endif  // !PRODUCT
 }
 
 
diff --git a/runtime/vm/os_thread_fuchsia.cc b/runtime/vm/os_thread_fuchsia.cc
index c3e8d25..cca791c 100644
--- a/runtime/vm/os_thread_fuchsia.cc
+++ b/runtime/vm/os_thread_fuchsia.cc
@@ -47,7 +47,7 @@
 
 static void ComputeTimeSpecMicros(struct timespec* ts, int64_t micros) {
   // time in nanoseconds.
-  mx_time_t now = _magenta_current_time();
+  mx_time_t now = mx_current_time();
   mx_time_t target = now + (micros * kNanosecondsPerMicrosecond);
   int64_t secs = target / kNanosecondsPerSecond;
   int64_t nanos = target - (secs * kNanosecondsPerSecond);
@@ -169,8 +169,7 @@
 
 #ifndef PRODUCT
 ThreadId OSThread::GetCurrentThreadTraceId() {
-  UNIMPLEMENTED();
-  return 0;
+  return pthread_self();
 }
 #endif  // PRODUCT
 
diff --git a/runtime/vm/pages.cc b/runtime/vm/pages.cc
index a10d097..2f894b5 100644
--- a/runtime/vm/pages.cc
+++ b/runtime/vm/pages.cc
@@ -969,7 +969,7 @@
   {
     MonitorLocker ml(tasks_lock());
     set_tasks(tasks() - 1);
-    ml.Notify();
+    ml.NotifyAll();
   }
 }
 
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index c902639..9e7dcbd 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -3387,17 +3387,6 @@
     ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved());
     ASSERT(func.NumParameters() == params.parameters->length());
 
-    // Check whether the function has any field initializer formal parameters,
-    // which are not allowed in non-constructor functions.
-    if (params.has_field_initializer) {
-      for (int i = 0; i < params.parameters->length(); i++) {
-        ParamDesc& param = (*params.parameters)[i];
-        if (param.is_field_initializer) {
-          ReportError(param.name_pos,
-                      "field initializer only allowed in constructors");
-        }
-      }
-    }
     // Populate function scope with the formal parameters.
     AddFormalParamsToScope(&params, current_block_->scope);
 
@@ -4743,6 +4732,10 @@
   TRACE_PARSER("ParseEnumDefinition");
   INC_STAT(thread(), num_classes_parsed, 1);
 
+  const Class& helper_class =
+      Class::Handle(Z, Library::LookupCoreClass(Symbols::_EnumHelper()));
+  ASSERT(!helper_class.IsNull());
+
   SkipMetadata();
   ExpectToken(Token::kENUM);
 
@@ -4754,9 +4747,9 @@
   const Type& int_type = Type::Handle(Z, Type::IntType());
   index_field = Field::New(Symbols::Index(),
                            false,  // Not static.
-                           true,  // Field is final.
+                           true,   // Field is final.
                            false,  // Not const.
-                           true,  // Is reflectable.
+                           true,   // Is reflectable.
                            cls,
                            int_type,
                            cls.token_pos());
@@ -4782,18 +4775,12 @@
   AddFormalParamsToFunction(&params, getter);
   enum_members.AddFunction(getter);
 
-  GrowableObjectArray& enum_names = GrowableObjectArray::Handle(Z,
-      GrowableObjectArray::New(8, Heap::kOld));
-  const String& name_prefix =
-      String::Handle(String::Concat(enum_name, Symbols::Dot()));
-
   ASSERT(IsIdentifier());
   ASSERT(CurrentLiteral()->raw() == cls.Name());
 
   ConsumeToken();  // Enum type name.
   ExpectToken(Token::kLBRACE);
   Field& enum_value = Field::Handle(Z);
-  String& enum_value_name = String::Handle(Z);
   intptr_t i = 0;
   GrowableArray<String*> declared_names(8);
 
@@ -4841,14 +4828,6 @@
     enum_value.RecordStore(ordinal_value);
     i++;
 
-    // For the user-visible name of the enumeration value, we need to
-    // unmangle private names.
-    if (enum_ident->CharAt(0) == '_') {
-      *enum_ident = String::ScrubName(*enum_ident);
-    }
-    enum_value_name = Symbols::FromConcat(T, name_prefix, *enum_ident);
-    enum_names.Add(enum_value_name, Heap::kOld);
-
     ConsumeToken();  // Enum value name.
     if (CurrentToken() == Token::kCOMMA) {
       ConsumeToken();
@@ -4856,10 +4835,6 @@
   }
   ExpectToken(Token::kRBRACE);
 
-  const Class& helper_class =
-      Class::Handle(Z, Library::LookupCoreClass(Symbols::_EnumHelper()));
-  ASSERT(!helper_class.IsNull());
-
   // Add static field 'const List values'.
   Field& values_field = Field::ZoneHandle(Z);
   values_field = Field::New(Symbols::Values(),
@@ -4878,16 +4853,35 @@
   values_field.SetStaticValue(values_array, true);
   values_field.RecordStore(values_array);
 
-  // Create a static field that contains the list of enumeration names.
-  // Clone the _enum_names field from the helper class.
-  Field& names_field = Field::Handle(Z,
-      helper_class.LookupStaticFieldAllowPrivate(Symbols::_EnumNames()));
-  ASSERT(!names_field.IsNull());
-  names_field = names_field.Clone(cls);
-  enum_members.AddField(names_field);
-  const Array& names_array = Array::Handle(Array::MakeArray(enum_names));
-  names_field.SetStaticValue(names_array, true);
-  names_field.RecordStore(names_array);
+  // Clone the _name field from the helper class.
+  Field& _name_field = Field::Handle(Z,
+      helper_class.LookupInstanceFieldAllowPrivate(Symbols::_name()));
+  ASSERT(!_name_field.IsNull());
+  _name_field = _name_field.Clone(cls);
+  enum_members.AddField(_name_field);
+
+  // Add an implicit getter function for the _name field. We use the field's
+  // name directly here so that the private key matches those of the other
+  // cloned helper functions and fields.
+  const Type& string_type = Type::Handle(Z, Type::StringType());
+  const String& name_getter_name = String::Handle(Z,
+      Field::GetterSymbol(String::Handle(_name_field.name())));
+  Function& name_getter = Function::Handle(Z);
+  name_getter = Function::New(name_getter_name,
+                              RawFunction::kImplicitGetter,
+                              /* is_static = */ false,
+                              /* is_const = */ true,
+                              /* is_abstract = */ false,
+                              /* is_external = */ false,
+                              /* is_native = */ false,
+                              cls,
+                              cls.token_pos());
+  name_getter.set_result_type(string_type);
+  name_getter.set_is_debuggable(false);
+  ParamList name_params;
+  name_params.AddReceiver(&Object::dynamic_type(), cls.token_pos());
+  AddFormalParamsToFunction(&name_params, name_getter);
+  enum_members.AddFunction(name_getter);
 
   // Clone the toString() function from the helper class.
   Function& to_string_func = Function::Handle(Z,
@@ -7397,6 +7391,12 @@
     ParamDesc& param_desc = (*params->parameters)[i];
     func.SetParameterTypeAt(i, *param_desc.type);
     func.SetParameterNameAt(i, *param_desc.name);
+    if (param_desc.is_field_initializer && !func.IsGenerativeConstructor()) {
+      // Redirecting constructors are detected later in ParseConstructor.
+      ReportError(param_desc.name_pos,
+                  "only generative constructors may have "
+                  "initializing formal parameters");
+    }
   }
 }
 
@@ -12134,21 +12134,21 @@
 }
 
 
-void Parser::InsertCachedConstantValue(const String& url,
+void Parser::InsertCachedConstantValue(const Script& script,
                                        TokenPosition token_pos,
                                        const Instance& value) {
   ASSERT(Thread::Current()->IsMutatorThread());
-  Isolate* isolate = Isolate::Current();
-  ConstantPosKey key(url, token_pos);
-  if (isolate->object_store()->compile_time_constants() == Array::null()) {
-    const intptr_t kInitialConstMapSize = 16;
-    isolate->object_store()->set_compile_time_constants(
+  const intptr_t kInitialConstMapSize = 16;
+  ASSERT(!script.InVMHeap());
+  if (script.compile_time_constants() == Array::null()) {
+    const Array& array =
         Array::Handle(HashTables::New<ConstantsMap>(kInitialConstMapSize,
-                                                    Heap::kNew)));
+                                                    Heap::kNew));
+    script.set_compile_time_constants(array);
   }
-  ConstantsMap constants(isolate->object_store()->compile_time_constants());
-  constants.InsertNewOrGetValue(key, value);
-  isolate->object_store()->set_compile_time_constants(constants.Release());
+  ConstantsMap constants(script.compile_time_constants());
+  constants.InsertNewOrGetValue(token_pos, value);
+  script.set_compile_time_constants(constants.Release());
 }
 
 
@@ -12159,26 +12159,20 @@
     // evaluated only once.
     return;
   }
-  const String& url = String::Handle(Z, script_.url());
-  InsertCachedConstantValue(url, token_pos, value);
-  if (FLAG_compiler_stats) {
-    ConstantsMap constants(isolate()->object_store()->compile_time_constants());
-    thread_->compiler_stats()->num_cached_consts = constants.NumOccupied();
-    constants.Release();
-  }
+  InsertCachedConstantValue(script_, token_pos, value);
 }
 
 
 bool Parser::GetCachedConstant(TokenPosition token_pos, Instance* value) {
-  if (isolate()->object_store()->compile_time_constants() == Array::null()) {
+  bool is_present = false;
+  ASSERT(!script_.InVMHeap());
+  if (script_.compile_time_constants() == Array::null()) {
     return false;
   }
-  ConstantPosKey key(String::Handle(Z, script_.url()), token_pos);
-  ConstantsMap constants(isolate()->object_store()->compile_time_constants());
-  bool is_present = false;
-  *value ^= constants.GetOrNull(key, &is_present);
+  ConstantsMap constants(script_.compile_time_constants());
+  *value ^= constants.GetOrNull(token_pos, &is_present);
   // Mutator compiler thread may add constants while background compiler
-  // is running , and thus change the value of 'compile_time_constants';
+  // is running, and thus change the value of 'compile_time_constants';
   // do not assert that 'compile_time_constants' has not changed.
   constants.Release();
   if (FLAG_compiler_stats && is_present) {
@@ -12230,6 +12224,8 @@
     // not been evaluated. If the field is const, call the static getter method
     // to evaluate the expression and canonicalize the value.
     if (field.is_const()) {
+      NoReloadScope no_reload_scope(isolate(), thread());
+      NoOOBMessageScope no_msg_scope(thread());
       field.SetStaticValue(Object::transition_sentinel());
       const int kNumArguments = 0;  // no arguments.
       const Function& func = Function::Handle(Z,
@@ -12287,6 +12283,8 @@
     const TypeArguments& type_arguments,
     const Function& constructor,
     ArgumentListNode* arguments) {
+  NoReloadScope no_reload_scope(isolate(), thread());
+  NoOOBMessageScope no_msg_scope(thread());
   // Factories have one extra argument: the type arguments.
   // Constructors have 1 extra arguments: receiver.
   const int kNumExtraArgs = 1;
@@ -13801,6 +13799,8 @@
 
 
 String& Parser::Interpolate(const GrowableArray<AstNode*>& values) {
+  NoReloadScope no_reload_scope(isolate(), thread());
+  NoOOBMessageScope no_msg_scope(thread());
   const Class& cls = Class::Handle(
       Z, Library::LookupCoreClass(Symbols::StringBase()));
   ASSERT(!cls.IsNull());
@@ -14148,6 +14148,8 @@
 // be a compile time constant.
 const Instance& Parser::EvaluateConstExpr(TokenPosition expr_pos,
                                           AstNode* expr) {
+  NoReloadScope no_reload_scope(isolate(), thread());
+  NoOOBMessageScope no_msg_scope(thread());
   if (expr->IsLiteralNode()) {
     return expr->AsLiteralNode()->literal();
   } else if (expr->IsLoadLocalNode() &&
@@ -14623,7 +14625,7 @@
 }
 
 
-void Parser::InsertCachedConstantValue(const String& url,
+void Parser::InsertCachedConstantValue(const Script& script,
                                        TokenPosition token_pos,
                                        const Instance& value) {
   UNREACHABLE();
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index 815f978..e29f86e 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -39,61 +39,44 @@
 class TopLevel;
 class RecursionChecker;
 
-// We cache computed compile-time constants in a map so we can look them
-// up when the same code gets compiled again. The map key is a pair
-// (script url, token position) which is encoded in an array with 2
-// elements:
-// - key[0] contains the canonicalized url of the script.
-// - key[1] contains the token position of the constant in the script.
-
-// ConstantPosKey allows us to look up a constant in the map without
-// allocating a key pair (array).
-struct ConstantPosKey : ValueObject {
-  ConstantPosKey(const String& url, TokenPosition pos)
-      : script_url(url), token_pos(pos) { }
-  const String& script_url;
-  TokenPosition token_pos;
-};
-
-
+// We cache compile time constants during compilation.  This allows us
+// to look them up when the same code gets compiled again.  During
+// background compilation, we are not able to evaluate the constants
+// so this cache is necessary to support background compilation.
+//
+// We cache the constants with the script itself. This is helpful during isolate
+// reloading, as it allows us to reference the compile time constants associated
+// with a particular version of a script. The map key is simply the
+// TokenPosition where the constant is defined.
 class ConstMapKeyEqualsTraits {
  public:
   static const char* Name() { return "ConstMapKeyEqualsTraits"; }
   static bool ReportStats() { return false; }
 
   static bool IsMatch(const Object& a, const Object& b) {
-    const Array& key1 = Array::Cast(a);
-    const Array& key2 = Array::Cast(b);
-    // Compare raw strings of script url symbol and raw smi of token positon.
-    return (key1.At(0) == key2.At(0)) && (key1.At(1) == key2.At(1));
+    const Smi& key1 = Smi::Cast(a);
+    const Smi& key2 = Smi::Cast(b);
+    return (key1.Value() == key2.Value());
   }
-  static bool IsMatch(const ConstantPosKey& key1, const Object& b) {
-    const Array& key2 = Array::Cast(b);
-    // Compare raw strings of script url symbol and token positon.
-    return (key1.script_url.raw() == key2.At(0))
-        && (key1.token_pos.value() == Smi::Value(Smi::RawCast(key2.At(1))));
+  static bool IsMatch(const TokenPosition& key1, const Object& b) {
+    const Smi& key2 = Smi::Cast(b);
+    return (key1.value() == key2.Value());
   }
   static uword Hash(const Object& obj) {
-    const Array& key = Array::Cast(obj);
-    intptr_t url_hash = String::HashRawSymbol(String::RawCast(key.At(0)));
-    intptr_t pos = Smi::Value(Smi::RawCast(key.At(1)));
-    return HashValue(url_hash, pos);
+    const Smi& key = Smi::Cast(obj);
+    return HashValue(key.Value());
   }
-  static uword Hash(const ConstantPosKey& key) {
-    return HashValue(String::HashRawSymbol(key.script_url.raw()),
-                     key.token_pos.value());
+  static uword Hash(const TokenPosition& key) {
+    return HashValue(key.value());
   }
-  // Used by CachConstantValue if a new constant is added to the map.
-  static RawObject* NewKey(const ConstantPosKey& key) {
-    const Array& key_obj = Array::Handle(Array::New(2));
-    key_obj.SetAt(0, key.script_url);
-    key_obj.SetAt(1, Smi::Handle(Smi::New(key.token_pos.value())));
-    return key_obj.raw();;
+  // Used by CacheConstantValue if a new constant is added to the map.
+  static RawObject* NewKey(const TokenPosition& key) {
+    return Smi::New(key.value());
   }
 
  private:
-  static uword HashValue(intptr_t url_hash, intptr_t pos) {
-    return url_hash * pos % (Smi::kMaxValue - 13);
+  static uword HashValue(intptr_t pos) {
+    return pos % (Smi::kMaxValue - 13);
   }
 };
 typedef UnorderedHashMap<ConstMapKeyEqualsTraits> ConstantsMap;
@@ -278,7 +261,7 @@
   // given static field.
   static ParsedFunction* ParseStaticFieldInitializer(const Field& field);
 
-  static void InsertCachedConstantValue(const String& url,
+  static void InsertCachedConstantValue(const Script& script,
                                         TokenPosition token_pos,
                                         const Instance& value);
 
@@ -617,8 +600,7 @@
   ClosureNode* CreateImplicitClosureNode(const Function& func,
                                          TokenPosition token_pos,
                                          AstNode* receiver);
-  static void AddFormalParamsToFunction(const ParamList* params,
-                                        const Function& func);
+  void AddFormalParamsToFunction(const ParamList* params, const Function& func);
   void AddFormalParamsToScope(const ParamList* params, LocalScope* scope);
 
   SequenceNode* ParseConstructor(const Function& func);
diff --git a/runtime/vm/port.cc b/runtime/vm/port.cc
index 8ef15c5..2541b38 100644
--- a/runtime/vm/port.cc
+++ b/runtime/vm/port.cc
@@ -303,6 +303,7 @@
 
 void PortMap::PrintPortsForMessageHandler(MessageHandler* handler,
                                           JSONStream* stream) {
+#ifndef PRODUCT
   if (!FLAG_support_service) {
     return;
   }
@@ -324,6 +325,7 @@
       }
     }
   }
+#endif
 }
 
 
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc
index 35df46b..dc0edb5 100644
--- a/runtime/vm/precompiler.cc
+++ b/runtime/vm/precompiler.cc
@@ -240,8 +240,8 @@
       DropTypeArguments();
 
       // Clear these before dropping classes as they may hold onto otherwise
-      // dead instances of classes we will remove.
-      I->object_store()->set_compile_time_constants(Array::null_array());
+      // dead instances of classes we will remove or otherwise unused symbols.
+      DropScriptData();
       I->object_store()->set_unique_dynamic_targets(Array::null_array());
       Class& null_class = Class::Handle(Z);
       I->object_store()->set_future_class(null_class);
@@ -1560,6 +1560,24 @@
 }
 
 
+void Precompiler::DropScriptData() {
+  Library& lib = Library::Handle(Z);
+  Array& scripts = Array::Handle(Z);
+  Script& script = Script::Handle(Z);
+  const TokenStream& null_tokens = TokenStream::Handle(Z);
+  for (intptr_t i = 0; i < libraries_.Length(); i++) {
+    lib ^= libraries_.At(i);
+    scripts = lib.LoadedScripts();
+    for (intptr_t j = 0; j < scripts.Length(); j++) {
+      script ^= scripts.At(j);
+      script.set_compile_time_constants(Array::null_array());
+      script.set_source(String::null_string());
+      script.set_tokens(null_tokens);
+    }
+  }
+}
+
+
 void Precompiler::TraceTypesFromRetainedClasses() {
   Library& lib = Library::Handle(Z);
   Class& cls = Class::Handle(Z);
@@ -2659,6 +2677,9 @@
           sinking->DetachMaterializations();
         }
 
+        // Replace bounds check instruction with a generic one.
+        optimizer.ReplaceArrayBoundChecks();
+
         // Compute and store graph informations (call & instruction counts)
         // to be later used by the inliner.
         FlowGraphInliner::CollectGraphInfo(flow_graph, true);
diff --git a/runtime/vm/precompiler.h b/runtime/vm/precompiler.h
index 6ec2ed3..5cae27e 100644
--- a/runtime/vm/precompiler.h
+++ b/runtime/vm/precompiler.h
@@ -306,6 +306,7 @@
   void TraceTypesFromRetainedClasses();
   void DropTypes();
   void DropTypeArguments();
+  void DropScriptData();
   void DropClasses();
   void DropLibraries();
 
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index dd8ff93..fb1f06e 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -640,6 +640,9 @@
   friend class NativeEntry;  // GetClassId
   friend class Simulator;
   friend class SimulatorHelpers;
+  friend class ObjectLocator;
+  friend class InstanceMorpher;  // GetClassId
+  friend class VerifyCanonicalVisitor;
 
   DISALLOW_ALLOCATION();
   DISALLOW_IMPLICIT_CONSTRUCTORS(RawObject);
@@ -995,9 +998,10 @@
 
   RawObject** from() { return reinterpret_cast<RawObject**>(&ptr()->url_); }
   RawString* url_;
+  RawArray* compile_time_constants_;
   RawTokenStream* tokens_;
   RawString* source_;
-  RawObject** to() { return reinterpret_cast<RawObject**>(&ptr()->source_); }
+  RawObject** to() {return reinterpret_cast<RawObject**>(&ptr()->source_); }
   RawObject** to_snapshot(Snapshot::Kind kind) {
     switch (kind) {
       case Snapshot::kAppNoJIT:
@@ -1170,7 +1174,6 @@
   Entry* first_entry() { return &ptr()->data()[0]; }
 
   friend class Object;
-  friend class SnapshotReader;
 };
 
 
@@ -1253,7 +1256,6 @@
   const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, intptr_t); }
 
   friend class Object;
-  friend class SnapshotReader;
 };
 
 
@@ -1270,7 +1272,6 @@
   const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, intptr_t); }
 
   friend class Object;
-  friend class SnapshotReader;
 };
 
 
@@ -1297,8 +1298,6 @@
   // Variable length data follows here (bitmap of the stack layout).
   uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
   const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
-
-  friend class SnapshotReader;
 };
 
 
@@ -1372,7 +1371,6 @@
   }
 
   friend class Object;
-  friend class SnapshotReader;
 };
 
 
@@ -1402,7 +1400,6 @@
   HandlerInfo* data() { OPEN_ARRAY_START(HandlerInfo, intptr_t); }
 
   friend class Object;
-  friend class SnapshotReader;
 };
 
 
@@ -1501,8 +1498,7 @@
     return NULL;
   }
   int32_t deopt_id_;     // Deoptimization id corresponding to this IC.
-  uint32_t state_bits_;  // Number of arguments tested in IC, deopt reasons,
-                         // range feedback.
+  uint32_t state_bits_;  // Number of arguments tested in IC, deopt reasons.
 #if defined(TAG_IC_DATA)
   intptr_t tag_;  // Debugging, verifying that the icdata is assigned to the
                   // same instruction again. Store -1 or Instruction::Tag.
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index c2448a3..d94ce4e 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -14,16 +14,6 @@
 
 DECLARE_FLAG(bool, remove_script_timestamps_for_test);
 
-#define NEW_OBJECT(type)                                                       \
-  ((Snapshot::IsFull(kind)) ? reader->New##type() : type::New())
-
-#define NEW_OBJECT_WITH_LEN(type, len)                                         \
-  ((Snapshot::IsFull(kind)) ? reader->New##type(len) : type::New(len))
-
-#define NEW_OBJECT_WITH_LEN_SPACE(type, len, kind)                             \
-  ((Snapshot::IsFull(kind)) ?                                                  \
-  reader->New##type(len) : type::New(len, HEAP_SPACE(kind)))
-
 #define OFFSET_OF_FROM(obj)                                                    \
   obj.raw()->from() - reinterpret_cast<RawObject**>(obj.raw()->ptr())
 
@@ -48,21 +38,16 @@
 
   Class& cls = Class::ZoneHandle(reader->zone(), Class::null());
   bool is_in_fullsnapshot = reader->Read<bool>();
-  if (Snapshot::IsFull(kind) ||
-      (kind == Snapshot::kScript && !is_in_fullsnapshot)) {
+  if ((kind == Snapshot::kScript) && !is_in_fullsnapshot) {
     // Read in the base information.
     classid_t class_id = reader->ReadClassIDValue();
 
     // Allocate class object of specified kind.
-    if (Snapshot::IsFull(kind)) {
-      cls = reader->NewClass(class_id);
+    if (class_id < kNumPredefinedCids) {
+      ASSERT((class_id >= kInstanceCid) && (class_id <= kMirrorReferenceCid));
+      cls = reader->isolate()->class_table()->At(class_id);
     } else {
-      if (class_id < kNumPredefinedCids) {
-        ASSERT((class_id >= kInstanceCid) && (class_id <= kMirrorReferenceCid));
-        cls = reader->isolate()->class_table()->At(class_id);
-      } else {
-        cls = Class::NewInstanceClass();
-      }
+      cls = Class::NewInstanceClass();
     }
     reader->AddBackRef(object_id, &cls, kIsDeserialized);
 
@@ -85,7 +70,7 @@
                        cls.raw()->to_snapshot(kind),
                        kAsReference);
     cls.StorePointer(&cls.raw_ptr()->dependent_code_, Array::null());
-    ASSERT(!cls.IsInFullSnapshot() || (Snapshot::IsFull(kind)));
+    ASSERT(!cls.IsInFullSnapshot());
   } else {
     cls ^= reader->ReadClassId(object_id);
     ASSERT((kind == Snapshot::kMessage) || cls.IsInFullSnapshot());
@@ -113,8 +98,7 @@
   // to be interpreted.
   writer->Write<bool>(is_in_fullsnapshot);
 
-  if (Snapshot::IsFull(kind) ||
-      (kind == Snapshot::kScript && !is_in_fullsnapshot)) {
+  if ((kind == Snapshot::kScript) && !is_in_fullsnapshot) {
     // Write out all the non object pointer fields.
     // NOTE: cpp_vtable_ is not written.
     classid_t class_id = ptr()->id_;
@@ -160,7 +144,7 @@
 
   // Allocate unresolved class object.
   UnresolvedClass& unresolved_class = UnresolvedClass::ZoneHandle(
-      reader->zone(), NEW_OBJECT(UnresolvedClass));
+      reader->zone(), UnresolvedClass::New());
   reader->AddBackRef(object_id, &unresolved_class, kIsDeserialized);
 
   // Set all non object fields.
@@ -228,10 +212,11 @@
   bool typeclass_is_in_fullsnapshot = reader->Read<bool>();
 
   // Allocate type object.
-  Type& type = Type::ZoneHandle(reader->zone(), NEW_OBJECT(Type));
+  Type& type = Type::ZoneHandle(reader->zone(), Type::New());
   bool is_canonical = RawObject::IsCanonical(tags);
   bool defer_canonicalization = is_canonical &&
-      (!Snapshot::IsFull(kind) && typeclass_is_in_fullsnapshot);
+      ((kind == Snapshot::kMessage) ||
+       (!Snapshot::IsFull(kind) && typeclass_is_in_fullsnapshot));
   reader->AddBackRef(object_id, &type, kIsDeserialized, defer_canonicalization);
 
   // Set all non object fields.
@@ -309,7 +294,7 @@
 
   // Allocate type ref object.
   TypeRef& type_ref = TypeRef::ZoneHandle(
-      reader->zone(), NEW_OBJECT(TypeRef));
+      reader->zone(), TypeRef::New());
   reader->AddBackRef(object_id, &type_ref, kIsDeserialized);
 
   // Set all the object fields.
@@ -349,7 +334,7 @@
 
   // Allocate type parameter object.
   TypeParameter& type_parameter = TypeParameter::ZoneHandle(
-      reader->zone(), NEW_OBJECT(TypeParameter));
+      reader->zone(), TypeParameter::New());
   reader->AddBackRef(object_id, &type_parameter, kIsDeserialized);
 
   // Set all non object fields.
@@ -413,7 +398,7 @@
 
   // Allocate bounded type object.
   BoundedType& bounded_type = BoundedType::ZoneHandle(
-      reader->zone(), NEW_OBJECT(BoundedType));
+      reader->zone(), BoundedType::New());
   reader->AddBackRef(object_id, &bounded_type, kIsDeserialized);
 
   // Set all the object fields.
@@ -473,7 +458,7 @@
   intptr_t len = reader->ReadSmiValue();
 
   TypeArguments& type_arguments = TypeArguments::ZoneHandle(
-      reader->zone(), NEW_OBJECT_WITH_LEN_SPACE(TypeArguments, len, kind));
+      reader->zone(), TypeArguments::New(len, HEAP_SPACE(kind)));
   bool is_canonical = RawObject::IsCanonical(tags);
   bool defer_canonicalization = is_canonical && (!Snapshot::IsFull(kind));
   reader->AddBackRef(object_id,
@@ -482,12 +467,7 @@
                      defer_canonicalization);
 
   // Set the instantiations field, which is only read from a full snapshot.
-  if (Snapshot::IsFull(kind)) {
-    *(reader->ArrayHandle()) ^= reader->ReadObjectImpl(kAsInlinedObject);
-    type_arguments.set_instantiations(*(reader->ArrayHandle()));
-  } else {
-    type_arguments.set_instantiations(Object::zero_array());
-  }
+  type_arguments.set_instantiations(Object::zero_array());
 
   // Now set all the type fields.
   intptr_t offset = type_arguments.TypeAddr(0) -
@@ -523,11 +503,6 @@
   // Write out the length field.
   writer->Write<RawObject*>(ptr()->length_);
 
-  // Write out the instantiations field, but only in a full snapshot.
-  if (Snapshot::IsFull(kind)) {
-    writer->WriteObjectImpl(ptr()->instantiations_, kAsInlinedObject);
-  }
-
   // Write out the individual types.
   intptr_t len = Smi::Value(ptr()->length_);
   for (intptr_t i = 0; i < len; i++) {
@@ -542,16 +517,16 @@
                                     Snapshot::Kind kind,
                                     bool as_reference) {
   ASSERT(reader != NULL);
+  ASSERT(kind == Snapshot::kScript);
 
   // Allocate function object.
   PatchClass& cls = PatchClass::ZoneHandle(reader->zone(),
-                                            NEW_OBJECT(PatchClass));
+                                           PatchClass::New());
   reader->AddBackRef(object_id, &cls, kIsDeserialized);
 
   // Set all the object fields.
   READ_OBJECT_FIELDS(cls, cls.raw()->from(), cls.raw()->to(), kAsReference);
 
-  ASSERT((kind == Snapshot::kScript) || (Snapshot::IsFull(kind)));
   return cls.raw();
 }
 
@@ -561,7 +536,7 @@
                             Snapshot::Kind kind,
                             bool as_reference) {
   ASSERT(writer != NULL);
-  ASSERT((kind == Snapshot::kScript) || (Snapshot::IsFull(kind)));
+  ASSERT(kind == Snapshot::kScript);
 
   // Write out the serialization header value for this object.
   writer->WriteInlinedObjectHeader(object_id);
@@ -580,24 +555,8 @@
                               intptr_t tags,
                               Snapshot::Kind kind,
                               bool as_reference) {
-  ASSERT(reader != NULL);
-  ASSERT(Snapshot::IsFull(kind));
-
-  // Allocate closure object.
-  Closure& closure = Closure::ZoneHandle(
-      reader->zone(), NEW_OBJECT(Closure));
-  reader->AddBackRef(object_id, &closure, kIsDeserialized);
-
-  // Set all the object fields.
-  READ_OBJECT_FIELDS(closure,
-                     closure.raw()->from(), closure.raw()->to(),
-                     kAsReference);
-
-  // Set the canonical bit.
-  if (RawObject::IsCanonical(tags)) {
-    closure.SetCanonical();
-  }
-  return closure.raw();
+  UNREACHABLE();
+  return Closure::null();
 }
 
 
@@ -606,27 +565,18 @@
                          Snapshot::Kind kind,
                          bool as_reference) {
   ASSERT(writer != NULL);
-  if ((kind == Snapshot::kMessage) || (kind == Snapshot::kScript)) {
-    // Check if closure is serializable, throw an exception otherwise.
-    RawFunction* func = writer->IsSerializableClosure(this);
-    if (func != Function::null()) {
-      writer->WriteStaticImplicitClosure(object_id,
-                                         func,
-                                         writer->GetObjectTags(this));
-      return;
-    }
+  ASSERT((kind == Snapshot::kMessage) || (kind == Snapshot::kScript));
+
+  // Check if closure is serializable, throw an exception otherwise.
+  RawFunction* func = writer->IsSerializableClosure(this);
+  if (func != Function::null()) {
+    writer->WriteStaticImplicitClosure(object_id,
+                                       func,
+                                       writer->GetObjectTags(this));
+    return;
   }
 
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kClosureCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out all the object pointer fields.
-  SnapshotWriterVisitor visitor(writer, kAsReference);
-  visitor.VisitPointers(from(), to());
+  UNREACHABLE();
 }
 
 
@@ -636,11 +586,11 @@
                                       Snapshot::Kind kind,
                                       bool as_reference) {
   ASSERT(reader != NULL);
-  ASSERT((kind == Snapshot::kScript) || (Snapshot::IsFull(kind)));
+  ASSERT(kind == Snapshot::kScript);
 
   // Allocate closure data object.
-  ClosureData& data = ClosureData::ZoneHandle(
-      reader->zone(), NEW_OBJECT(ClosureData));
+  ClosureData& data = ClosureData::ZoneHandle(reader->zone(),
+                                              ClosureData::New());
   reader->AddBackRef(object_id, &data, kIsDeserialized);
 
   // Set all the object fields.
@@ -657,7 +607,7 @@
                              Snapshot::Kind kind,
                              bool as_reference) {
   ASSERT(writer != NULL);
-  ASSERT((kind == Snapshot::kScript) || (Snapshot::IsFull(kind)));
+  ASSERT(kind == Snapshot::kScript);
 
   // Write out the serialization header value for this object.
   writer->WriteInlinedObjectHeader(object_id);
@@ -669,8 +619,7 @@
   // Context scope.
   if (ptr()->context_scope_ == Object::empty_context_scope().raw()) {
     writer->WriteVMIsolateObject(kEmptyContextScopeObject);
-  } else if (ptr()->context_scope_->ptr()->is_implicit_ ||
-             (kind == Snapshot::kAppWithJIT)) {
+  } else if (ptr()->context_scope_->ptr()->is_implicit_) {
     writer->WriteObjectImpl(ptr()->context_scope_, kAsInlinedObject);
   } else {
     // We don't write non implicit context scopes in the snapshot.
@@ -694,11 +643,11 @@
                                               Snapshot::Kind kind,
                                               bool as_reference) {
   ASSERT(reader != NULL);
-  ASSERT((kind == Snapshot::kScript) || (Snapshot::IsFull(kind)));
+  ASSERT(kind == Snapshot::kScript);
 
   // Allocate redirection data object.
-  RedirectionData& data = RedirectionData::ZoneHandle(
-      reader->zone(), NEW_OBJECT(RedirectionData));
+  RedirectionData& data = RedirectionData::ZoneHandle(reader->zone(),
+                                                      RedirectionData::New());
   reader->AddBackRef(object_id, &data, kIsDeserialized);
 
   // Set all the object fields.
@@ -715,7 +664,7 @@
                                  Snapshot::Kind kind,
                                  bool as_reference) {
   ASSERT(writer != NULL);
-  ASSERT((kind == Snapshot::kScript) || (Snapshot::IsFull(kind)));
+  ASSERT(kind == Snapshot::kScript);
 
   // Write out the serialization header value for this object.
   writer->WriteInlinedObjectHeader(object_id);
@@ -736,13 +685,13 @@
                                 Snapshot::Kind kind,
                                 bool as_reference) {
   ASSERT(reader != NULL);
-  ASSERT((kind == Snapshot::kScript) || (Snapshot::IsFull(kind)));
+  ASSERT(kind == Snapshot::kScript);
 
   bool is_in_fullsnapshot = reader->Read<bool>();
-  if ((Snapshot::IsFull(kind)) || !is_in_fullsnapshot) {
+  if (!is_in_fullsnapshot) {
     // Allocate function object.
-    Function& func = Function::ZoneHandle(
-        reader->zone(), NEW_OBJECT(Function));
+    Function& func = Function::ZoneHandle(reader->zone(),
+                                          Function::New());
     reader->AddBackRef(object_id, &func, kIsDeserialized);
 
     // Set all the non object fields. Read the token positions now but
@@ -754,17 +703,10 @@
     func.set_kind_tag(reader->Read<uint32_t>());
     func.set_token_pos(TokenPosition::SnapshotDecode(token_pos));
     func.set_end_token_pos(TokenPosition::SnapshotDecode(end_token_pos));
-    if (kind == Snapshot::kAppNoJIT) {
-      func.set_usage_counter(0);
-      func.set_deoptimization_counter(0);
-      func.set_optimized_instruction_count(0);
-      func.set_optimized_call_site_count(0);
-    } else {
-      func.set_usage_counter(reader->Read<int32_t>());
-      func.set_deoptimization_counter(reader->Read<int8_t>());
-      func.set_optimized_instruction_count(reader->Read<uint16_t>());
-      func.set_optimized_call_site_count(reader->Read<uint16_t>());
-    }
+    func.set_usage_counter(reader->Read<int32_t>());
+    func.set_deoptimization_counter(reader->Read<int8_t>());
+    func.set_optimized_instruction_count(reader->Read<uint16_t>());
+    func.set_optimized_call_site_count(reader->Read<uint16_t>());
     func.set_was_compiled(false);
 
     // Set all the object fields.
@@ -772,34 +714,15 @@
                        func.raw()->from(), func.raw()->to_snapshot(),
                        kAsReference);
     // Initialize all fields that are not part of the snapshot.
-    if (kind == Snapshot::kAppNoJIT) {
-      // Read the code object and fixup entry point.
-      func.ClearICDataArray();
-      func.ClearCode();
-      (*reader->CodeHandle()) ^= reader->ReadObjectImpl(kAsInlinedObject);
-      func.SetInstructions(*reader->CodeHandle());
-    } else if (kind == Snapshot::kAppWithJIT) {
+    bool is_optimized = func.usage_counter() != 0;
+    if (is_optimized) {
+      // Read the ic data array as the function is an optimized one.
       (*reader->ArrayHandle()) ^= reader->ReadObjectImpl(kAsReference);
       func.set_ic_data_array(*reader->ArrayHandle());
-      (*reader->CodeHandle()) ^= reader->ReadObjectImpl(kAsInlinedObject);
-      func.set_unoptimized_code(*reader->CodeHandle());
-      if (!reader->CodeHandle()->IsNull()) {
-        func.SetInstructions(*reader->CodeHandle());
-        func.set_was_compiled(true);
-      } else {
-        func.ClearCode();
-      }
     } else {
-      bool is_optimized = func.usage_counter() != 0;
-      if (is_optimized) {
-        // Read the ic data array as the function is an optimized one.
-        (*reader->ArrayHandle()) ^= reader->ReadObjectImpl(kAsReference);
-        func.set_ic_data_array(*reader->ArrayHandle());
-      } else {
-        func.ClearICDataArray();
-      }
-      func.ClearCode();
+      func.ClearICDataArray();
     }
+    func.ClearCode();
     return func.raw();
   } else {
     return reader->ReadFunctionId(object_id);
@@ -812,7 +735,7 @@
                           Snapshot::Kind kind,
                           bool as_reference) {
   ASSERT(writer != NULL);
-  ASSERT((kind == Snapshot::kScript) || (Snapshot::IsFull(kind)));
+  ASSERT(kind == Snapshot::kScript);
   bool is_in_fullsnapshot = false;
   bool owner_is_class = false;
   if ((kind == Snapshot::kScript) && !Function::IsSignatureFunction(this)) {
@@ -837,7 +760,7 @@
   // to be interpreted.
   writer->Write<bool>(is_in_fullsnapshot);
 
-  if (Snapshot::IsFull(kind) || !is_in_fullsnapshot) {
+  if (!is_in_fullsnapshot) {
     bool is_optimized = Code::IsOptimized(ptr()->code_);
 
     // Write out all the non object fields.
@@ -846,31 +769,19 @@
     writer->Write<int16_t>(ptr()->num_fixed_parameters_);
     writer->Write<int16_t>(ptr()->num_optional_parameters_);
     writer->Write<uint32_t>(ptr()->kind_tag_);
-    if (kind == Snapshot::kAppNoJIT) {
-      // Omit fields used to support de/reoptimization.
+    if (is_optimized) {
+      writer->Write<int32_t>(FLAG_optimization_counter_threshold);
     } else {
-      if (is_optimized) {
-        writer->Write<int32_t>(FLAG_optimization_counter_threshold);
-      } else {
-        writer->Write<int32_t>(0);
-      }
-      writer->Write<int8_t>(ptr()->deoptimization_counter_);
-      writer->Write<uint16_t>(ptr()->optimized_instruction_count_);
-      writer->Write<uint16_t>(ptr()->optimized_call_site_count_);
+      writer->Write<int32_t>(0);
     }
+    writer->Write<int8_t>(ptr()->deoptimization_counter_);
+    writer->Write<uint16_t>(ptr()->optimized_instruction_count_);
+    writer->Write<uint16_t>(ptr()->optimized_call_site_count_);
 
     // Write out all the object pointer fields.
     SnapshotWriterVisitor visitor(writer, kAsReference);
     visitor.VisitPointers(from(), to_snapshot());
-    if (kind == Snapshot::kAppNoJIT) {
-      ASSERT(ptr()->ic_data_array_ == Array::null());
-      ASSERT((ptr()->code_ == ptr()->unoptimized_code_) ||
-             (ptr()->unoptimized_code_ == Code::null()));
-      writer->WriteObjectImpl(ptr()->code_, kAsInlinedObject);
-    } else if (kind == Snapshot::kAppWithJIT) {
-      writer->WriteObjectImpl(ptr()->ic_data_array_, kAsReference);
-      writer->WriteObjectImpl(ptr()->unoptimized_code_, kAsInlinedObject);
-    } else if (is_optimized) {
+    if (is_optimized) {
       // Write out the ic data array as the function is optimized.
       writer->WriteObjectImpl(ptr()->ic_data_array_, kAsReference);
     }
@@ -886,22 +797,17 @@
                           Snapshot::Kind kind,
                           bool as_reference) {
   ASSERT(reader != NULL);
-  ASSERT((kind == Snapshot::kScript) || (Snapshot::IsFull(kind)));
+  ASSERT(kind == Snapshot::kScript);
 
   // Allocate field object.
-  Field& field = Field::ZoneHandle(reader->zone(), NEW_OBJECT(Field));
+  Field& field = Field::ZoneHandle(reader->zone(), Field::New());
   reader->AddBackRef(object_id, &field, kIsDeserialized);
 
   // Set all non object fields.
-  if (kind == Snapshot::kAppNoJIT) {
-    field.set_token_pos(TokenPosition::kNoSource);
-    ASSERT(!FLAG_use_field_guards);
-  } else {
-    field.set_token_pos(
-        TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
-    field.set_guarded_cid(reader->Read<int32_t>());
-    field.set_is_nullable(reader->Read<int32_t>());
-  }
+  field.set_token_pos(
+      TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
+  field.set_guarded_cid(reader->Read<int32_t>());
+  field.set_is_nullable(reader->Read<int32_t>());
   field.set_kind_bits(reader->Read<uint8_t>());
 
   // Set all the object fields.
@@ -929,7 +835,7 @@
                        Snapshot::Kind kind,
                        bool as_reference) {
   ASSERT(writer != NULL);
-  ASSERT((kind == Snapshot::kScript) || (Snapshot::IsFull(kind)));
+  ASSERT(kind == Snapshot::kScript);
 
   // Write out the serialization header value for this object.
   writer->WriteInlinedObjectHeader(object_id);
@@ -939,11 +845,9 @@
   writer->WriteTags(writer->GetObjectTags(this));
 
   // Write out all the non object fields.
-  if (kind != Snapshot::kAppNoJIT) {
-    writer->Write<int32_t>(ptr()->token_pos_.SnapshotEncode());
-    writer->Write<int32_t>(ptr()->guarded_cid_);
-    writer->Write<int32_t>(ptr()->is_nullable_);
-  }
+  writer->Write<int32_t>(ptr()->token_pos_.SnapshotEncode());
+  writer->Write<int32_t>(ptr()->guarded_cid_);
+  writer->Write<int32_t>(ptr()->is_nullable_);
   writer->Write<uint8_t>(ptr()->kind_bits_);
 
   // Write out the name.
@@ -954,11 +858,7 @@
   writer->WriteObjectImpl(ptr()->type_, kAsReference);
   // Write out the initial static value or field offset.
   if (Field::StaticBit::decode(ptr()->kind_bits_)) {
-    if (kind == Snapshot::kAppNoJIT) {
-      // For precompiled static fields, the value was already reset and
-      // initializer_ now contains a Function.
-      writer->WriteObjectImpl(ptr()->value_.static_value_, kAsReference);
-    } else if (Field::ConstBit::decode(ptr()->kind_bits_)) {
+    if (Field::ConstBit::decode(ptr()->kind_bits_)) {
       // Do not reset const fields.
       writer->WriteObjectImpl(ptr()->value_.static_value_, kAsReference);
     } else {
@@ -969,15 +869,9 @@
     writer->WriteObjectImpl(ptr()->value_.offset_, kAsReference);
   }
   // Write out the initializer function or saved initial value.
-  if (kind == Snapshot::kAppNoJIT) {
-    writer->WriteObjectImpl(ptr()->initializer_.precompiled_, kAsReference);
-  } else {
-    writer->WriteObjectImpl(ptr()->initializer_.saved_value_, kAsReference);
-  }
-  if (kind != Snapshot::kAppNoJIT) {
-    // Write out the guarded list length.
-    writer->WriteObjectImpl(ptr()->guarded_list_length_, kAsReference);
-  }
+  writer->WriteObjectImpl(ptr()->initializer_.saved_value_, kAsReference);
+  // Write out the guarded list length.
+  writer->WriteObjectImpl(ptr()->guarded_list_length_, kAsReference);
 }
 
 
@@ -990,8 +884,8 @@
   ASSERT(kind != Snapshot::kMessage);
 
   // Create the literal token object.
-  LiteralToken& literal_token = LiteralToken::ZoneHandle(
-      reader->zone(), NEW_OBJECT(LiteralToken));
+  LiteralToken& literal_token = LiteralToken::ZoneHandle(reader->zone(),
+                                                         LiteralToken::New());
   reader->AddBackRef(object_id, &literal_token, kIsDeserialized);
 
   // Read the token attributes.
@@ -1036,14 +930,14 @@
                                       Snapshot::Kind kind,
                                       bool as_reference) {
   ASSERT(reader != NULL);
-  ASSERT((kind == Snapshot::kScript) || (Snapshot::IsFull(kind)));
+  ASSERT(kind == Snapshot::kScript);
 
   // Read the length so that we can determine number of tokens to read.
   intptr_t len = reader->ReadSmiValue();
 
   // Create the token stream object.
-  TokenStream& token_stream = TokenStream::ZoneHandle(
-      reader->zone(), NEW_OBJECT_WITH_LEN(TokenStream, len));
+  TokenStream& token_stream = TokenStream::ZoneHandle(reader->zone(),
+                                                      TokenStream::New(len));
   reader->AddBackRef(object_id, &token_stream, kIsDeserialized);
 
   // Read the stream of tokens into the TokenStream object for script
@@ -1070,7 +964,7 @@
                              Snapshot::Kind kind,
                              bool as_reference) {
   ASSERT(writer != NULL);
-  ASSERT((kind == Snapshot::kScript) || (Snapshot::IsFull(kind)));
+  ASSERT(kind == Snapshot::kScript);
 
   // Write out the serialization header value for this object.
   writer->WriteInlinedObjectHeader(object_id);
@@ -1098,10 +992,10 @@
                             Snapshot::Kind kind,
                             bool as_reference) {
   ASSERT(reader != NULL);
-  ASSERT((kind == Snapshot::kScript) || (Snapshot::IsFull(kind)));
+  ASSERT(kind == Snapshot::kScript);
 
   // Allocate script object.
-  Script& script = Script::ZoneHandle(reader->zone(), NEW_OBJECT(Script));
+  Script& script = Script::ZoneHandle(reader->zone(), Script::New());
   reader->AddBackRef(object_id, &script, kIsDeserialized);
 
   script.StoreNonPointer(&script.raw_ptr()->line_offset_,
@@ -1139,7 +1033,7 @@
                         bool as_reference) {
   ASSERT(writer != NULL);
   ASSERT(tokens_ != TokenStream::null());
-  ASSERT((kind == Snapshot::kScript) || (Snapshot::IsFull(kind)));
+  ASSERT(kind == Snapshot::kScript);
 
   // Write out the serialization header value for this object.
   writer->WriteInlinedObjectHeader(object_id);
@@ -1178,7 +1072,7 @@
     ASSERT(library.is_in_fullsnapshot());
   } else {
     // Allocate library object.
-    library = NEW_OBJECT(Library);
+    library = Library::New();
 
     // Set all non object fields.
     library.StoreNonPointer(&library.raw_ptr()->index_,
@@ -1193,9 +1087,6 @@
                             reader->Read<bool>());
     library.StoreNonPointer(&library.raw_ptr()->debuggable_,
                             reader->Read<bool>());
-    if (Snapshot::IsFull(kind)) {
-      is_in_fullsnapshot = true;
-    }
     library.StoreNonPointer(&library.raw_ptr()->is_in_fullsnapshot_,
                             is_in_fullsnapshot);
     // The native resolver and symbolizer are not serialized.
@@ -1213,13 +1104,9 @@
     }
     // Initialize cache of resolved names.
     const intptr_t kInitialNameCacheSize = 64;
-    if (!Snapshot::IsFull(kind)) {
-      // The cache of resolved names in library scope is not serialized.
-      library.InitResolvedNamesCache(kInitialNameCacheSize);
-      library.Register(reader->thread());
-    } else {
-      library.InitResolvedNamesCache(kInitialNameCacheSize, reader);
-    }
+    // The cache of resolved names in library scope is not serialized.
+    library.InitResolvedNamesCache(kInitialNameCacheSize);
+    library.Register(reader->thread());
     library.StorePointer(&library.raw_ptr()->exported_names_, Array::null());
     // Initialize cache of loaded scripts.
     library.StorePointer(&library.raw_ptr()->loaded_scripts_, Array::null());
@@ -1251,7 +1138,7 @@
     // Write out library URL so that it can be looked up when reading.
     writer->WriteObjectImpl(ptr()->url_, kAsInlinedObject);
   } else {
-    ASSERT((Snapshot::IsFull(kind)) || !ptr()->is_in_fullsnapshot_);
+    ASSERT(!ptr()->is_in_fullsnapshot_);
     // Write out all non object fields.
     ASSERT(ptr()->index_ != static_cast<classid_t>(-1));
     writer->WriteClassIDValue(ptr()->index_);
@@ -1279,11 +1166,11 @@
                                           Snapshot::Kind kind,
                                           bool as_reference) {
   ASSERT(reader != NULL);
-  ASSERT((kind == Snapshot::kScript) || (Snapshot::IsFull(kind)));
+  ASSERT(kind == Snapshot::kScript);
 
   // Allocate library prefix object.
-  LibraryPrefix& prefix = LibraryPrefix::ZoneHandle(
-      reader->zone(), NEW_OBJECT(LibraryPrefix));
+  LibraryPrefix& prefix = LibraryPrefix::ZoneHandle(reader->zone(),
+                                                    LibraryPrefix::New());
   reader->AddBackRef(object_id, &prefix, kIsDeserialized);
 
   // Set all non object fields.
@@ -1298,10 +1185,6 @@
                      prefix.raw()->from(),
                      prefix.raw()->to_snapshot(kind),
                      kAsReference);
-  if (kind == Snapshot::kAppNoJIT) {
-    prefix.StorePointer(&prefix.raw_ptr()->imports_,
-                        Object::empty_array().raw());
-  }
   prefix.StorePointer(&prefix.raw_ptr()->dependent_code_,
                       Array::null());
 
@@ -1314,7 +1197,7 @@
                                Snapshot::Kind kind,
                                bool as_reference) {
   ASSERT(writer != NULL);
-  ASSERT((kind == Snapshot::kScript) || (Snapshot::IsFull(kind)));
+  ASSERT(kind == Snapshot::kScript);
 
   // Write out the serialization header value for this object.
   writer->WriteInlinedObjectHeader(object_id);
@@ -1340,11 +1223,10 @@
                                   Snapshot::Kind kind,
                                   bool as_reference) {
   ASSERT(reader != NULL);
-  ASSERT((kind == Snapshot::kScript) || (Snapshot::IsFull(kind)));
+  ASSERT(kind == Snapshot::kScript);
 
   // Allocate Namespace object.
-  Namespace& ns = Namespace::ZoneHandle(
-      reader->zone(), NEW_OBJECT(Namespace));
+  Namespace& ns = Namespace::ZoneHandle(reader->zone(), Namespace::New());
   reader->AddBackRef(object_id, &ns, kIsDeserialized);
 
   // Set all the object fields.
@@ -1359,7 +1241,7 @@
                            Snapshot::Kind kind,
                            bool as_reference) {
   ASSERT(writer != NULL);
-  ASSERT((kind == Snapshot::kScript) || (Snapshot::IsFull(kind)));
+  ASSERT(kind == Snapshot::kScript);
 
   // Write out the serialization header value for this object.
   writer->WriteInlinedObjectHeader(object_id);
@@ -1532,7 +1414,7 @@
   if (num_vars == 0) {
     context ^= reader->object_store()->empty_context();
   } else {
-    context ^= NEW_OBJECT_WITH_LEN(Context, num_vars);
+    context ^= Context::New(num_vars);
 
     // Set all the object fields.
     // TODO(5411462): Need to assert No GC can happen here, even though
@@ -1583,12 +1465,7 @@
   bool is_implicit = reader->Read<bool>();
   if (is_implicit) {
     ContextScope& context_scope = ContextScope::ZoneHandle(reader->zone());
-    if (Snapshot::IsFull(kind)) {
-      context_scope = reader->NewContextScope(1);
-      context_scope.set_is_implicit(true);
-    } else {
-      context_scope = ContextScope::New(1, true);
-    }
+    context_scope = ContextScope::New(1, true);
     reader->AddBackRef(object_id, &context_scope, kIsDeserialized);
 
     *reader->TypeHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
@@ -1602,19 +1479,6 @@
     context_scope.SetContextIndexAt(0, 0);
     context_scope.SetContextLevelAt(0, 0);
     return context_scope.raw();
-  } else if (kind == Snapshot::kAppWithJIT) {
-    int32_t num_vars = reader->Read<int32_t>();
-
-    ContextScope& context_scope = ContextScope::ZoneHandle(reader->zone());
-    context_scope = reader->NewContextScope(num_vars);
-    context_scope.set_is_implicit(false);
-    reader->AddBackRef(object_id, &context_scope, kIsDeserialized);
-
-    READ_OBJECT_FIELDS(context_scope,
-                       context_scope.raw()->from(),
-                       context_scope.raw()->to(num_vars),
-                       kAsInlinedObject);
-    return context_scope.raw();
   }
   UNREACHABLE();
   return NULL;
@@ -1645,23 +1509,6 @@
     writer->WriteObjectImpl(var->type, kAsInlinedObject);
 
     return;
-  } else if (kind == Snapshot::kAppWithJIT) {
-    // Write out the serialization header value for this object.
-    writer->WriteInlinedObjectHeader(object_id);
-
-    // Write out the class and tags information.
-    writer->WriteVMIsolateObject(kContextScopeCid);
-    writer->WriteTags(writer->GetObjectTags(this));
-
-    // Write out is_implicit flag for the context scope.
-    writer->Write<bool>(false);
-    int32_t num_vars = ptr()->num_variables_;
-    writer->Write<int32_t>(num_vars);
-
-    SnapshotWriterVisitor visitor(writer, kAsInlinedObject);
-    visitor.VisitPointers(from(), to(num_vars));
-
-    return;
   }
   UNREACHABLE();
 }
@@ -1672,9 +1519,9 @@
                             intptr_t tags,
                             Snapshot::Kind kind,
                             bool as_reference) {
-  ASSERT((kind == Snapshot::kScript) || (Snapshot::IsFull(kind)));
+  ASSERT(kind == Snapshot::kScript);
 
-  ICData& result = ICData::ZoneHandle(reader->zone(), NEW_OBJECT(ICData));
+  ICData& result = ICData::ZoneHandle(reader->zone(), ICData::New());
   reader->AddBackRef(object_id, &result, kIsDeserialized);
 
   result.set_deopt_id(reader->Read<int32_t>());
@@ -1688,9 +1535,6 @@
                      result.raw()->from(),
                      result.raw()->to_snapshot(kind),
                      kAsReference);
-  if (kind == Snapshot::kAppNoJIT) {
-    result.set_owner(Function::Handle(reader->zone()));
-  }
 
   return result.raw();
 }
@@ -1700,7 +1544,7 @@
                         intptr_t object_id,
                         Snapshot::Kind kind,
                         bool as_reference) {
-  ASSERT((kind == Snapshot::kScript) || (Snapshot::IsFull(kind)));
+  ASSERT(kind == Snapshot::kScript);
 
   // Write out the serialization header value for this object.
   writer->WriteInlinedObjectHeader(object_id);
@@ -1787,7 +1631,7 @@
 
   // Allocate ApiError object.
   ApiError& api_error =
-      ApiError::ZoneHandle(reader->zone(), NEW_OBJECT(ApiError));
+      ApiError::ZoneHandle(reader->zone(), ApiError::New());
   reader->AddBackRef(object_id, &api_error, kIsDeserialized);
 
   // Set all the object fields.
@@ -1827,7 +1671,7 @@
 
   // Allocate LanguageError object.
   LanguageError& language_error =
-      LanguageError::ZoneHandle(reader->zone(), NEW_OBJECT(LanguageError));
+      LanguageError::ZoneHandle(reader->zone(), LanguageError::New());
   reader->AddBackRef(object_id, &language_error, kIsDeserialized);
 
   // Set all non object fields.
@@ -1875,7 +1719,7 @@
                                                     Snapshot::Kind kind,
                                                     bool as_reference) {
   UnhandledException& result = UnhandledException::ZoneHandle(
-      reader->zone(), NEW_OBJECT(UnhandledException));
+      reader->zone(), UnhandledException::New());
   reader->AddBackRef(object_id, &result, kIsDeserialized);
 
   // Set all the object fields.
@@ -1931,19 +1775,11 @@
   // Create an Instance object or get canonical one if it is a canonical
   // constant.
   Instance& obj = Instance::ZoneHandle(reader->zone(), Instance::null());
-  if (Snapshot::IsFull(kind)) {
-    obj = reader->NewInstance();
-    // Set the canonical bit.
-    if (RawObject::IsCanonical(tags)) {
-      obj.SetCanonical();
-    }
-  } else {
-    obj ^= Object::Allocate(kInstanceCid,
-                            Instance::InstanceSize(),
-                            HEAP_SPACE(kind));
-    if (RawObject::IsCanonical(tags)) {
-      obj = obj.CheckAndCanonicalize(reader->thread(), NULL);
-    }
+  obj ^= Object::Allocate(kInstanceCid,
+                          Instance::InstanceSize(),
+                          HEAP_SPACE(kind));
+  if (RawObject::IsCanonical(tags)) {
+    obj = obj.CheckAndCanonicalize(reader->thread(), NULL);
   }
   reader->AddBackRef(object_id, &obj, kIsDeserialized);
 
@@ -1987,24 +1823,16 @@
 
   // Create a Mint object or get canonical one if it is a canonical constant.
   Mint& mint = Mint::ZoneHandle(reader->zone(), Mint::null());
-  if (Snapshot::IsFull(kind)) {
-    mint = reader->NewMint(value);
-    // Set the canonical bit.
-    if (RawObject::IsCanonical(tags)) {
-      mint.SetCanonical();
-    }
+  // When reading a script snapshot we need to canonicalize only those object
+  // references that are objects from the core library (loaded from a
+  // full snapshot). Objects that are only in the script need not be
+  // canonicalized as they are already canonical.
+  // When reading a message snapshot we always have to canonicalize.
+  if (RawObject::IsCanonical(tags)) {
+    mint = Mint::NewCanonical(value);
+    ASSERT(mint.IsCanonical());
   } else {
-    // When reading a script snapshot we need to canonicalize only those object
-    // references that are objects from the core library (loaded from a
-    // full snapshot). Objects that are only in the script need not be
-    // canonicalized as they are already canonical.
-    // When reading a message snapshot we always have to canonicalize.
-    if (RawObject::IsCanonical(tags)) {
-      mint = Mint::NewCanonical(value);
-      ASSERT(mint.IsCanonical());
-    } else {
-      mint = Mint::New(value, HEAP_SPACE(kind));
-    }
+    mint = Mint::New(value, HEAP_SPACE(kind));
   }
   reader->AddBackRef(object_id, &mint, kIsDeserialized);
   return mint.raw();
@@ -2037,7 +1865,7 @@
   ASSERT(reader != NULL);
 
   // Allocate bigint object.
-  Bigint& obj = Bigint::ZoneHandle(reader->zone(), NEW_OBJECT(Bigint));
+  Bigint& obj = Bigint::ZoneHandle(reader->zone(), Bigint::New());
   reader->AddBackRef(object_id, &obj, kIsDeserialized);
 
   // Set all the object fields.
@@ -2049,14 +1877,9 @@
   // When reading a script snapshot or a message snapshot we always have
   // to canonicalize the object.
   if (RawObject::IsCanonical(tags)) {
-    if (Snapshot::IsFull(kind)) {
-      // Set the canonical bit.
-      obj.SetCanonical();
-    } else {
-      obj ^= obj.CheckAndCanonicalize(reader->thread(), NULL);
-      ASSERT(!obj.IsNull());
-      ASSERT(obj.IsCanonical());
-    }
+    obj ^= obj.CheckAndCanonicalize(reader->thread(), NULL);
+    ASSERT(!obj.IsNull());
+    ASSERT(obj.IsCanonical());
   }
   return obj.raw();
 }
@@ -2093,23 +1916,15 @@
 
   // Create a Double object or get canonical one if it is a canonical constant.
   Double& dbl = Double::ZoneHandle(reader->zone(), Double::null());
-  if (Snapshot::IsFull(kind)) {
-    dbl = reader->NewDouble(value);
-    // Set the canonical bit.
-    if (RawObject::IsCanonical(tags)) {
-      dbl.SetCanonical();
-    }
+  // When reading a script snapshot we need to canonicalize only those object
+  // references that are objects from the core library (loaded from a
+  // full snapshot). Objects that are only in the script need not be
+  // canonicalized as they are already canonical.
+  if (RawObject::IsCanonical(tags)) {
+    dbl = Double::NewCanonical(value);
+    ASSERT(dbl.IsCanonical());
   } else {
-    // When reading a script snapshot we need to canonicalize only those object
-    // references that are objects from the core library (loaded from a
-    // full snapshot). Objects that are only in the script need not be
-    // canonicalized as they are already canonical.
-    if (RawObject::IsCanonical(tags)) {
-      dbl = Double::NewCanonical(value);
-      ASSERT(dbl.IsCanonical());
-    } else {
-      dbl = Double::New(value, HEAP_SPACE(kind));
-    }
+    dbl = Double::New(value, HEAP_SPACE(kind));
   }
   reader->AddBackRef(object_id, &dbl, kIsDeserialized);
   return dbl.raw();
@@ -2193,28 +2008,10 @@
   // Read the length so that we can determine instance size to allocate.
   ASSERT(reader != NULL);
   intptr_t len = reader->ReadSmiValue();
-  intptr_t hash = reader->ReadSmiValue();
   String& str_obj = String::ZoneHandle(reader->zone(), String::null());
 
-  if (Snapshot::IsFull(kind)) {
-    // We currently only expect the Dart mutator to read snapshots.
-    reader->isolate()->AssertCurrentThreadIsMutator();
-    ASSERT(Thread::Current()->no_safepoint_scope_depth() != 0);
-    RawOneByteString* obj = reader->NewOneByteString(len);
-    str_obj = obj;
-    if (RawObject::IsCanonical(tags)) {
-      str_obj.SetCanonical();
-    }
-    str_obj.SetHash(hash);
-    if (len > 0) {
-      uint8_t* raw_ptr = CharAddr(str_obj, 0);
-      reader->ReadBytes(raw_ptr, len);
-    }
-    ASSERT((hash == 0) || (String::Hash(str_obj, 0, str_obj.Length()) == hash));
-  } else {
-    String::ReadFromImpl<OneByteString, uint8_t>(
-        reader, &str_obj, len, tags, Symbols::FromLatin1, kind);
-  }
+  String::ReadFromImpl<OneByteString, uint8_t>(
+      reader, &str_obj, len, tags, Symbols::FromLatin1, kind);
   reader->AddBackRef(object_id, &str_obj, kIsDeserialized);
   return raw(str_obj);
 }
@@ -2228,28 +2025,10 @@
   // Read the length so that we can determine instance size to allocate.
   ASSERT(reader != NULL);
   intptr_t len = reader->ReadSmiValue();
-  intptr_t hash = reader->ReadSmiValue();
   String& str_obj = String::ZoneHandle(reader->zone(), String::null());
 
-  if (Snapshot::IsFull(kind)) {
-    RawTwoByteString* obj = reader->NewTwoByteString(len);
-    str_obj = obj;
-    if (RawObject::IsCanonical(tags)) {
-      str_obj.SetCanonical();
-    }
-    str_obj.SetHash(hash);
-    NoSafepointScope no_safepoint;
-    uint16_t* raw_ptr = (len > 0)? CharAddr(str_obj, 0) : NULL;
-    for (intptr_t i = 0; i < len; i++) {
-      ASSERT(CharAddr(str_obj, i) == raw_ptr);  // Will trigger assertions.
-      *raw_ptr = reader->Read<uint16_t>();
-      raw_ptr += 1;
-    }
-    ASSERT(String::Hash(str_obj, 0, str_obj.Length()) == hash);
-  } else {
-    String::ReadFromImpl<TwoByteString, uint16_t>(
-        reader, &str_obj, len, tags, Symbols::FromUTF16, kind);
-  }
+  String::ReadFromImpl<TwoByteString, uint16_t>(
+      reader, &str_obj, len, tags, Symbols::FromUTF16, kind);
   reader->AddBackRef(object_id, &str_obj, kIsDeserialized);
   return raw(str_obj);
 }
@@ -2262,7 +2041,6 @@
                           intptr_t class_id,
                           intptr_t tags,
                           RawSmi* length,
-                          RawSmi* hash,
                           T* data) {
   ASSERT(writer != NULL);
   intptr_t len = Smi::Value(length);
@@ -2277,9 +2055,6 @@
   // Write out the length field.
   writer->Write<RawObject*>(length);
 
-  // Write out the hash field.
-  writer->Write<RawObject*>(hash);
-
   // Write out the string.
   if (len > 0) {
     if (class_id == kOneByteStringCid) {
@@ -2303,7 +2078,6 @@
                 kOneByteStringCid,
                 writer->GetObjectTags(this),
                 ptr()->length_,
-                ptr()->hash_,
                 ptr()->data());
 }
 
@@ -2318,7 +2092,6 @@
                 kTwoByteStringCid,
                 writer->GetObjectTags(this),
                 ptr()->length_,
-                ptr()->hash_,
                 ptr()->data());
 }
 
@@ -2356,7 +2129,6 @@
                 kOneByteStringCid,
                 writer->GetObjectTags(this),
                 ptr()->length_,
-                ptr()->hash_,
                 ptr()->external_data_->data());
 }
 
@@ -2372,7 +2144,6 @@
                 kTwoByteStringCid,
                 writer->GetObjectTags(this),
                 ptr()->length_,
-                ptr()->hash_,
                 ptr()->external_data_->data());
 }
 
@@ -2414,7 +2185,7 @@
   }
   if (array == NULL) {
     array = &(Array::ZoneHandle(reader->zone(),
-                                NEW_OBJECT_WITH_LEN_SPACE(Array, len, kind)));
+                                Array::New(len, HEAP_SPACE(kind))));
     reader->AddBackRef(object_id, array, state);
   }
   if (!as_reference) {
@@ -2446,18 +2217,14 @@
   if (array == NULL) {
     array = &(Array::ZoneHandle(
         reader->zone(),
-        NEW_OBJECT_WITH_LEN_SPACE(ImmutableArray, len, kind)));
+        ImmutableArray::New(len, HEAP_SPACE(kind))));
     reader->AddBackRef(object_id, array, state);
   }
   if (!as_reference) {
     // Read all the individual elements for inlined objects.
     reader->ArrayReadFrom(object_id, *array, len, tags);
     if (RawObject::IsCanonical(tags)) {
-      if (Snapshot::IsFull(kind)) {
-        array->SetCanonical();
-      } else {
-        *array ^= array->CheckAndCanonicalize(reader->thread(), NULL);
-      }
+      *array ^= array->CheckAndCanonicalize(reader->thread(), NULL);
     }
   }
   return raw(*array);
@@ -2503,11 +2270,7 @@
   // Read the length so that we can determine instance size to allocate.
   GrowableObjectArray& array = GrowableObjectArray::ZoneHandle(
       reader->zone(), GrowableObjectArray::null());
-  if (Snapshot::IsFull(kind)) {
-    array = reader->NewGrowableObjectArray();
-  } else {
-    array = GrowableObjectArray::New(0, HEAP_SPACE(kind));
-  }
+  array = GrowableObjectArray::New(0, HEAP_SPACE(kind));
   reader->AddBackRef(object_id, &array, kIsDeserialized);
 
   // Read type arguments of growable array object.
@@ -2562,17 +2325,13 @@
 
   LinkedHashMap& map = LinkedHashMap::ZoneHandle(
       reader->zone(), LinkedHashMap::null());
-  if (Snapshot::IsFull(kind) || kind == Snapshot::kScript) {
+  if (kind == Snapshot::kScript) {
     // The immutable maps that seed map literals are not yet VM-internal, so
     // we don't reach this.
     UNREACHABLE();
   } else {
     // Since the map might contain itself as a key or value, allocate first.
-    if (Snapshot::IsFull(kind)) {
-      map = reader->NewLinkedHashMap();
-    } else {
-      map = LinkedHashMap::NewUninitialized(HEAP_SPACE(kind));
-    }
+    map = LinkedHashMap::NewUninitialized(HEAP_SPACE(kind));
   }
   reader->AddBackRef(object_id, &map, kIsDeserialized);
 
@@ -2593,9 +2352,7 @@
       Utils::RoundUpToPowerOfTwo(used_data),
       static_cast<uintptr_t>(LinkedHashMap::kInitialIndexSize));
   Array& data = Array::ZoneHandle(reader->zone(),
-                                  NEW_OBJECT_WITH_LEN_SPACE(Array,
-                                                            data_size,
-                                                            kind));
+                                  Array::New(data_size, HEAP_SPACE(kind)));
   map.SetData(data);
   map.SetDeletedKeys(0);
 
@@ -2620,7 +2377,7 @@
                                intptr_t object_id,
                                Snapshot::Kind kind,
                                bool as_reference) {
-  if (Snapshot::IsFull(kind) || kind == Snapshot::kScript) {
+  if (kind == Snapshot::kScript) {
     // The immutable maps that seed map literals are not yet VM-internal, so
     // we don't reach this.
   }
@@ -2682,11 +2439,7 @@
   // Create a Float32x4 object.
   Float32x4& simd = Float32x4::ZoneHandle(reader->zone(),
                                           Float32x4::null());
-  if (Snapshot::IsFull(kind)) {
-    simd = reader->NewFloat32x4(value0, value1, value2, value3);
-  } else {
-    simd = Float32x4::New(value0, value1, value2, value3, HEAP_SPACE(kind));
-  }
+  simd = Float32x4::New(value0, value1, value2, value3, HEAP_SPACE(kind));
   reader->AddBackRef(object_id, &simd, kIsDeserialized);
   return simd.raw();
 }
@@ -2727,12 +2480,7 @@
 
   // Create a Float32x4 object.
   Int32x4& simd = Int32x4::ZoneHandle(reader->zone(), Int32x4::null());
-
-  if (Snapshot::IsFull(kind)) {
-    simd = reader->NewInt32x4(value0, value1, value2, value3);
-  } else {
-    simd = Int32x4::New(value0, value1, value2, value3, HEAP_SPACE(kind));
-  }
+  simd = Int32x4::New(value0, value1, value2, value3, HEAP_SPACE(kind));
   reader->AddBackRef(object_id, &simd, kIsDeserialized);
   return simd.raw();
 }
@@ -2772,11 +2520,7 @@
   // Create a Float64x2 object.
   Float64x2& simd = Float64x2::ZoneHandle(reader->zone(),
                                           Float64x2::null());
-  if (Snapshot::IsFull(kind)) {
-    simd = reader->NewFloat64x2(value0, value1);
-  } else {
-    simd = Float64x2::New(value0, value1, HEAP_SPACE(kind));
-  }
+  simd = Float64x2::New(value0, value1, HEAP_SPACE(kind));
   reader->AddBackRef(object_id, &simd, kIsDeserialized);
   return simd.raw();
 }
@@ -2816,9 +2560,8 @@
 
   intptr_t cid = RawObject::ClassIdTag::decode(tags);
   intptr_t len = reader->ReadSmiValue();
-  TypedData& result = TypedData::ZoneHandle(reader->zone(),
-      (Snapshot::IsFull(kind)) ? reader->NewTypedData(cid, len)
-                                : TypedData::New(cid, len, HEAP_SPACE(kind)));
+  TypedData& result = TypedData::ZoneHandle(
+      reader->zone(), TypedData::New(cid, len, HEAP_SPACE(kind)));
   reader->AddBackRef(object_id, &result, kIsDeserialized);
 
   // Setup the array elements.
@@ -2866,14 +2609,9 @@
   // When reading a script snapshot or a message snapshot we always have
   // to canonicalize the object.
   if (RawObject::IsCanonical(tags)) {
-    if (Snapshot::IsFull(kind)) {
-      // Set the canonical bit.
-      result.SetCanonical();
-    } else {
-      result ^= result.CheckAndCanonicalize(reader->thread(), NULL);
-      ASSERT(!result.IsNull());
-      ASSERT(result.IsCanonical());
-    }
+    result ^= result.CheckAndCanonicalize(reader->thread(), NULL);
+    ASSERT(!result.IsNull());
+    ASSERT(result.IsCanonical());
   }
   return result.raw();
 }
@@ -3129,21 +2867,6 @@
                                     intptr_t tags,
                                     Snapshot::Kind kind,
                                     bool as_reference) {
-  if (Snapshot::IsFull(kind)) {
-    Stacktrace& result = Stacktrace::ZoneHandle(reader->zone(),
-                                                reader->NewStacktrace());
-    reader->AddBackRef(object_id, &result, kIsDeserialized);
-
-    bool expand_inlined = reader->Read<bool>();
-    result.set_expand_inlined(expand_inlined);
-
-    // Set all the object fields.
-    READ_OBJECT_FIELDS(result,
-                       result.raw()->from(), result.raw()->to(),
-                       kAsReference);
-
-    return result.raw();
-  }
   UNREACHABLE();  // Stacktraces are not sent in a snapshot.
   return Stacktrace::null();
 }
@@ -3153,29 +2876,10 @@
                             intptr_t object_id,
                             Snapshot::Kind kind,
                             bool as_reference) {
-  if (Snapshot::IsFull(kind)) {
-    ASSERT(writer != NULL);
-    ASSERT(this == Isolate::Current()->object_store()->
-           preallocated_stack_trace());
-
-    // Write out the serialization header value for this object.
-    writer->WriteInlinedObjectHeader(object_id);
-
-    // Write out the class and tags information.
-    writer->WriteIndexedObject(kStacktraceCid);
-    writer->WriteTags(writer->GetObjectTags(this));
-
-    writer->Write(ptr()->expand_inlined_);
-
-    // Write out all the object pointer fields.
-    SnapshotWriterVisitor visitor(writer, kAsReference);
-    visitor.VisitPointers(from(), to());
-  } else {
-    // Stacktraces are not allowed in other snapshot forms.
-    writer->SetWriteException(Exceptions::kArgument,
-                              "Illegal argument in isolate message"
-                              " : (object is a stacktrace)");
-  }
+  ASSERT(kind == Snapshot::kMessage);
+  writer->SetWriteException(Exceptions::kArgument,
+                            "Illegal argument in isolate message"
+                            " : (object is a stacktrace)");
 }
 
 
@@ -3187,7 +2891,7 @@
   ASSERT(reader != NULL);
 
   // Allocate RegExp object.
-  RegExp& regex = RegExp::ZoneHandle(reader->zone(), NEW_OBJECT(RegExp));
+  RegExp& regex = RegExp::ZoneHandle(reader->zone(), RegExp::New());
   reader->AddBackRef(object_id, &regex, kIsDeserialized);
 
   // Read and Set all the other fields.
@@ -3244,8 +2948,8 @@
   ASSERT(reader != NULL);
 
   // Allocate the weak property object.
-  WeakProperty& weak_property = WeakProperty::ZoneHandle(
-      reader->zone(), NEW_OBJECT(WeakProperty));
+  WeakProperty& weak_property = WeakProperty::ZoneHandle(reader->zone(),
+                                                         WeakProperty::New());
   reader->AddBackRef(object_id, &weak_property, kIsDeserialized);
 
   // Set all the object fields.
diff --git a/runtime/vm/runtime_entry_list.h b/runtime/vm/runtime_entry_list.h
index 60e46a0..a63f9bb 100644
--- a/runtime/vm/runtime_entry_list.h
+++ b/runtime/vm/runtime_entry_list.h
@@ -33,6 +33,7 @@
   V(OptimizeInvokedFunction)                                                   \
   V(TraceICCall)                                                               \
   V(PatchStaticCall)                                                           \
+  V(RangeError)                                                                \
   V(ReThrow)                                                                   \
   V(StackOverflow)                                                             \
   V(Throw)                                                                     \
diff --git a/runtime/vm/safepoint.cc b/runtime/vm/safepoint.cc
index 6cbd0f7..7f5d92d 100644
--- a/runtime/vm/safepoint.cc
+++ b/runtime/vm/safepoint.cc
@@ -41,12 +41,14 @@
     : isolate_(isolate),
       safepoint_lock_(new Monitor()),
       number_threads_not_at_safepoint_(0),
-      safepoint_in_progress_(false) {
+      safepoint_operation_count_(0),
+      owner_(NULL) {
 }
 
 
 SafepointHandler::~SafepointHandler() {
-  ASSERT(safepoint_in_progress_ == false);
+  ASSERT(owner_ == NULL);
+  ASSERT(safepoint_operation_count_ == 0);
   delete safepoint_lock_;
   safepoint_lock_ = NULL;
   isolate_ = NULL;
@@ -63,12 +65,19 @@
 
     // Now check to see if a safepoint operation is already in progress
     // for this isolate, block if an operation is in progress.
-    while (safepoint_in_progress()) {
+    while (SafepointInProgress()) {
+      // If we are recursively invoking a Safepoint operation then we
+      // just increment the count and return, otherwise we wait for the
+      // safepoint operation to be done.
+      if (owner_ == T) {
+        increment_safepoint_operation_count();
+        return;
+      }
       sl.WaitWithSafepointCheck(T);
     }
 
-    // Set safepoint in progress by this thread.
-    set_safepoint_in_progress(true);
+    // Set safepoint in progress state by this thread.
+    SetSafepointInProgress(T);
 
     // Go over the active thread list and ensure that all threads active
     // in the isolate reach a safepoint.
@@ -101,9 +110,13 @@
       Monitor::WaitResult retval = sl.Wait(1000);
       if (retval == Monitor::kTimedOut) {
         num_attempts += 1;
-        OS::Print("Attempt:%" Pd " waiting for %d threads to check in\n",
-                  num_attempts,
-                  number_threads_not_at_safepoint_);
+        if (num_attempts > 10) {
+          // We have been waiting too long, start logging this as we might
+          // have an issue where a thread is not checking in for a safepoint.
+          OS::Print("Attempt:%" Pd " waiting for %d threads to check in\n",
+                    num_attempts,
+                    number_threads_not_at_safepoint_);
+        }
       }
     }
   }
@@ -114,6 +127,14 @@
   // First resume all the threads which are blocked for the safepoint
   // operation.
   MonitorLocker sl(threads_lock());
+
+  // First check if we are in a recursive safepoint operation, in that case
+  // we just decrement safepoint_operation_count and return.
+  ASSERT(SafepointInProgress());
+  if (safepoint_operation_count() > 1) {
+    decrement_safepoint_operation_count();
+    return;
+  }
   Thread* current = isolate()->thread_registry()->active_list();
   while (current != NULL) {
     MonitorLocker tl(current->thread_lock());
@@ -127,10 +148,10 @@
     }
     current = current->next();
   }
-  // Now set the safepoint_in_progress_ flag to false and notify all threads
+  // Now reset the safepoint_in_progress_ state and notify all threads
   // that are waiting to enter the isolate or waiting to start another
   // safepoint operation.
-  set_safepoint_in_progress(false);
+  ResetSafepointInProgress(T);
   sl.NotifyAll();
 }
 
diff --git a/runtime/vm/safepoint.h b/runtime/vm/safepoint.h
index 58afb49..15c2c98 100644
--- a/runtime/vm/safepoint.h
+++ b/runtime/vm/safepoint.h
@@ -33,21 +33,45 @@
   void EnterSafepointUsingLock(Thread* T);
   void ExitSafepointUsingLock(Thread* T);
 
-  void SafepointThreads(Thread* T);
-  void ResumeThreads(Thread* T);
-
   void BlockForSafepoint(Thread* T);
 
  private:
+  void SafepointThreads(Thread* T);
+  void ResumeThreads(Thread* T);
+
   Isolate* isolate() const { return isolate_; }
   Monitor* threads_lock() const { return isolate_->threads_lock(); }
-  bool safepoint_in_progress() const {
+  bool SafepointInProgress() const {
     ASSERT(threads_lock()->IsOwnedByCurrentThread());
-    return safepoint_in_progress_;
+    return ((safepoint_operation_count_ > 0) && (owner_ != NULL));
   }
-  void set_safepoint_in_progress(bool value) {
+  void SetSafepointInProgress(Thread* T) {
     ASSERT(threads_lock()->IsOwnedByCurrentThread());
-    safepoint_in_progress_ = value;
+    ASSERT(owner_ == NULL);
+    ASSERT(safepoint_operation_count_ == 0);
+    safepoint_operation_count_ = 1;
+    owner_ = T;
+  }
+  void ResetSafepointInProgress(Thread* T) {
+    ASSERT(threads_lock()->IsOwnedByCurrentThread());
+    ASSERT(owner_ == T);
+    ASSERT(safepoint_operation_count_ == 1);
+    safepoint_operation_count_ = 0;
+    owner_ = NULL;
+  }
+  int32_t safepoint_operation_count() const {
+    ASSERT(threads_lock()->IsOwnedByCurrentThread());
+    return safepoint_operation_count_;
+  }
+  void increment_safepoint_operation_count() {
+    ASSERT(threads_lock()->IsOwnedByCurrentThread());
+    ASSERT(safepoint_operation_count_ < kMaxInt32);
+    safepoint_operation_count_ += 1;
+  }
+  void decrement_safepoint_operation_count() {
+    ASSERT(threads_lock()->IsOwnedByCurrentThread());
+    ASSERT(safepoint_operation_count_ > 0);
+    safepoint_operation_count_ -= 1;
   }
 
   Isolate* isolate_;
@@ -57,8 +81,14 @@
   Monitor* safepoint_lock_;
   int32_t number_threads_not_at_safepoint_;
 
-  // Flag to indicate if a safepoint operation is currently in progress.
-  bool safepoint_in_progress_;
+  // Count that indicates if a safepoint operation is currently in progress
+  // and also tracks the number of recursive safepoint operations on the
+  // same thread.
+  int32_t safepoint_operation_count_;
+
+  // If a safepoint operation is currently in progress, this field contains
+  // the thread that initiated the safepoint operation, otherwise it is NULL.
+  Thread* owner_;
 
   friend class Isolate;
   friend class SafepointOperationScope;
diff --git a/runtime/vm/scavenger.cc b/runtime/vm/scavenger.cc
index d1bfd3f..cb028ce 100644
--- a/runtime/vm/scavenger.cc
+++ b/runtime/vm/scavenger.cc
@@ -124,14 +124,14 @@
       new_addr = ForwardedAddr(header);
     } else {
       intptr_t size = raw_obj->Size();
-      intptr_t cid = raw_obj->GetClassId();
-      ClassTable* class_table = isolate()->class_table();
+      NOT_IN_PRODUCT(intptr_t cid = raw_obj->GetClassId());
+      NOT_IN_PRODUCT(ClassTable* class_table = isolate()->class_table());
       // Check whether object should be promoted.
       if (scavenger_->survivor_end_ <= raw_addr) {
         // Not a survivor of a previous scavenge. Just copy the object into the
         // to space.
         new_addr = scavenger_->TryAllocate(size);
-        class_table->UpdateLiveNew(cid, size);
+        NOT_IN_PRODUCT(class_table->UpdateLiveNew(cid, size));
       } else {
         // TODO(iposva): Experiment with less aggressive promotion. For example
         // a coin toss determines if an object is promoted or whether it should
@@ -146,11 +146,11 @@
           // be traversed later.
           scavenger_->PushToPromotedStack(new_addr);
           bytes_promoted_ += size;
-          class_table->UpdateAllocatedOld(cid, size);
+          NOT_IN_PRODUCT(class_table->UpdateAllocatedOld(cid, size));
         } else {
           // Promotion did not succeed. Copy into the to space instead.
           new_addr = scavenger_->TryAllocate(size);
-          class_table->UpdateLiveNew(cid, size);
+          NOT_IN_PRODUCT(class_table->UpdateLiveNew(cid, size));
         }
       }
       // During a scavenge we always succeed to at least copy all of the
@@ -487,6 +487,7 @@
 
 void Scavenger::IterateObjectIdTable(Isolate* isolate,
                                      ScavengerVisitor* visitor) {
+#ifndef PRODUCT
   if (!FLAG_support_service) {
     return;
   }
@@ -497,6 +498,7 @@
     return;
   }
   ring->VisitPointers(visitor);
+#endif  // !PRODUCT
 }
 
 
@@ -858,6 +860,7 @@
 }
 
 
+#ifndef PRODUCT
 void Scavenger::PrintToJSONObject(JSONObject* object) const {
   if (!FLAG_support_service) {
     return;
@@ -885,6 +888,7 @@
   space.AddProperty64("external", ExternalInWords() * kWordSize);
   space.AddProperty("time", MicrosecondsToSeconds(gc_time_micros()));
 }
+#endif  // !PRODUCT
 
 
 void Scavenger::AllocateExternal(intptr_t size) {
diff --git a/runtime/vm/scavenger.h b/runtime/vm/scavenger.h
index 5e7dcb1..8fce1a4 100644
--- a/runtime/vm/scavenger.h
+++ b/runtime/vm/scavenger.h
@@ -204,7 +204,9 @@
     return collections_;
   }
 
+#ifndef PRODUCT
   void PrintToJSONObject(JSONObject* object) const;
+#endif  // !PRODUCT
 
   void AllocateExternal(intptr_t size);
   void FreeExternal(intptr_t size);
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index e209d3b..ccc5309 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -1339,12 +1339,13 @@
 
 
 static bool GetStack(Thread* thread, JSONStream* js) {
-  if (!thread->isolate()->compilation_allowed()) {
+  Isolate* isolate = thread->isolate();
+  if (isolate->debugger() == NULL) {
     js->PrintError(kFeatureDisabled,
-        "Cannot get stack when running a precompiled program.");
+                   "Cannot get stack when debugger disabled.");
     return true;
   }
-  Isolate* isolate = thread->isolate();
+  ASSERT(isolate->compilation_allowed());
   DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
   // Do we want the complete script object and complete local variable objects?
   // This is true for dump requests.
diff --git a/runtime/vm/service_event.cc b/runtime/vm/service_event.cc
index 94af480..3ff1e1b 100644
--- a/runtime/vm/service_event.cc
+++ b/runtime/vm/service_event.cc
@@ -23,6 +23,8 @@
       extension_rpc_(NULL),
       exception_(NULL),
       reload_error_(NULL),
+      spawn_token_(NULL),
+      spawn_error_(NULL),
       at_async_jump_(false),
       inspectee_(NULL),
       gc_stats_(NULL),
@@ -69,6 +71,8 @@
       return "ServiceExtensionAdded";
     case kIsolateReload:
       return "IsolateReload";
+    case kIsolateSpawn:
+      return "IsolateSpawn";
     case kPauseStart:
       return "PauseStart";
     case kPauseExit:
@@ -122,6 +126,7 @@
     case kIsolateExit:
     case kIsolateUpdate:
     case kIsolateReload:
+    case kIsolateSpawn:
     case kServiceExtensionAdded:
       return &Service::isolate_stream;
 
@@ -183,6 +188,16 @@
       jsobj.AddProperty("reloadError", *(reload_error()));
     }
   }
+  if (kind() == kIsolateSpawn) {
+    ASSERT(spawn_token() != NULL);
+    jsobj.AddPropertyStr("spawnToken", *(spawn_token()));
+    if (spawn_error_ == NULL) {
+      jsobj.AddProperty("status", "success");
+    } else {
+      jsobj.AddProperty("status", "failure");
+      jsobj.AddPropertyStr("spawnError", *(spawn_error()));
+    }
+  }
   if (kind() == kServiceExtensionAdded) {
     ASSERT(extension_rpc_ != NULL);
     jsobj.AddProperty("extensionRPC", extension_rpc_->ToCString());
diff --git a/runtime/vm/service_event.h b/runtime/vm/service_event.h
index d6bc92e..cd48844 100644
--- a/runtime/vm/service_event.h
+++ b/runtime/vm/service_event.h
@@ -29,6 +29,7 @@
     kIsolateExit,            // Isolate has exited
     kIsolateUpdate,          // Isolate identity information has changed
     kIsolateReload,          // Result of a reload request
+    kIsolateSpawn,           // Result of an isolate spawn request
     kServiceExtensionAdded,  // A service extension was registered
 
     kPauseStart,         // --pause-isolates-on-start
@@ -158,6 +159,24 @@
     reload_error_ = error;
   }
 
+  const String* spawn_token() const {
+    ASSERT(kind_ == kIsolateSpawn);
+    return spawn_token_;
+  }
+  void set_spawn_token(const String* error) {
+    ASSERT(kind_ == kIsolateSpawn);
+    spawn_token_ = error;
+  }
+
+  const String* spawn_error() const {
+    ASSERT(kind_ == kIsolateSpawn);
+    return spawn_error_;
+  }
+  void set_spawn_error(const String* error) {
+    ASSERT(kind_ == kIsolateSpawn);
+    spawn_error_ = error;
+  }
+
   bool at_async_jump() const {
     return at_async_jump_;
   }
@@ -232,6 +251,8 @@
   const String* extension_rpc_;
   const Object* exception_;
   const Error* reload_error_;
+  const String* spawn_token_;
+  const String* spawn_error_;
   bool at_async_jump_;
   const Object* inspectee_;
   const Heap::GCStats* gc_stats_;
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index e85a5c0..19ccf68 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -23,8 +23,6 @@
 
 namespace dart {
 
-DECLARE_FLAG(bool, shutdown);
-
 #define Z (T->zone())
 
 
@@ -462,9 +460,6 @@
 
 
 void ServiceIsolate::KillServiceIsolate() {
-  if (!FLAG_shutdown) {
-    return;
-  }
   {
     MonitorLocker ml(monitor_);
     shutting_down_ = true;
diff --git a/runtime/vm/signal_handler_android.cc b/runtime/vm/signal_handler_android.cc
index 64670de..8812c63 100644
--- a/runtime/vm/signal_handler_android.cc
+++ b/runtime/vm/signal_handler_android.cc
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include "vm/globals.h"
+#include "vm/instructions.h"
 #include "vm/simulator.h"
 #include "vm/signal_handler.h"
 #if defined(TARGET_OS_ANDROID)
@@ -65,20 +66,11 @@
 
 
 uintptr_t SignalHandler::GetDartStackPointer(const mcontext_t& mcontext) {
-  uintptr_t sp = 0;
-
-#if defined(HOST_ARCH_IA32)
-  sp = static_cast<uintptr_t>(mcontext.gregs[REG_ESP]);
-#elif defined(HOST_ARCH_X64)
-  sp = static_cast<uintptr_t>(mcontext.gregs[REG_RSP]);
-#elif defined(HOST_ARCH_ARM)
-  sp = static_cast<uintptr_t>(mcontext.arm_sp);
-#elif defined(HOST_ARCH_ARM64)
-  sp = static_cast<uintptr_t>(mcontext.regs[19]);
+#if defined(TARGET_ARCH_ARM64) && !defined(USING_SIMULATOR)
+  return static_cast<uintptr_t>(mcontext.regs[SPREG]);
 #else
-#error Unsupported architecture.
-#endif  // HOST_ARCH_...
-  return sp;
+  return GetCStackPointer(mcontext);
+#endif
 }
 
 
diff --git a/runtime/vm/signal_handler_linux.cc b/runtime/vm/signal_handler_linux.cc
index 1df46f0..b867c00 100644
--- a/runtime/vm/signal_handler_linux.cc
+++ b/runtime/vm/signal_handler_linux.cc
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include "vm/globals.h"
+#include "vm/instructions.h"
 #include "vm/simulator.h"
 #include "vm/signal_handler.h"
 #if defined(TARGET_OS_LINUX)
@@ -72,7 +73,7 @@
 
 uintptr_t SignalHandler::GetDartStackPointer(const mcontext_t& mcontext) {
 #if defined(TARGET_ARCH_ARM64) && !defined(USING_SIMULATOR)
-  return static_cast<uintptr_t>(mcontext.regs[19]);
+  return static_cast<uintptr_t>(mcontext.regs[SPREG]);
 #else
   return GetCStackPointer(mcontext);
 #endif
diff --git a/runtime/vm/signal_handler_macos.cc b/runtime/vm/signal_handler_macos.cc
index bfcc42c..75c9c09 100644
--- a/runtime/vm/signal_handler_macos.cc
+++ b/runtime/vm/signal_handler_macos.cc
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include "vm/globals.h"
+#include "vm/instructions.h"
 #include "vm/simulator.h"
 #include "vm/signal_handler.h"
 #if defined(TARGET_OS_MACOS)
@@ -68,7 +69,7 @@
 
 uintptr_t SignalHandler::GetDartStackPointer(const mcontext_t& mcontext) {
 #if defined(TARGET_ARCH_ARM64) && !defined(USING_SIMULATOR)
-  return static_cast<uintptr_t>(mcontext->__ss.__x[19]);
+  return static_cast<uintptr_t>(mcontext->__ss.__x[SPREG]);
 #else
   return GetCStackPointer(mcontext);
 #endif
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index b1c648d..416dda5 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -1374,7 +1374,7 @@
   }
 
   {
-    BYTECODE(StaticCall, A_D);
+    BYTECODE(IndirectStaticCall, A_D);
 
     // Check if single stepping.
     if (thread->isolate()->single_step()) {
@@ -1386,6 +1386,12 @@
     // Invoke target function.
     {
       const uint16_t argc = rA;
+      // Lookup the funciton in the ICData.
+      RawObject* ic_data_obj = SP[0];
+      RawICData* ic_data = RAW_CAST(ICData, ic_data_obj);
+      RawArray* cache = ic_data->ptr()->ic_data_->ptr();
+      SP[0] = cache->data()[ICData::TargetIndexFor(
+          ic_data->ptr()->state_bits_ & 0x3)];
       RawObject** call_base = SP - argc;
       RawObject** call_top = SP;  // *SP contains function
       argdesc = static_cast<RawArray*>(LOAD_CONSTANT(rD));
@@ -1396,6 +1402,16 @@
   }
 
   {
+    BYTECODE(StaticCall, A_D);
+    const uint16_t argc = rA;
+    RawObject** call_base = SP - argc;
+    RawObject** call_top = SP;  // *SP contains function
+    argdesc = static_cast<RawArray*>(LOAD_CONSTANT(rD));
+    Invoke(thread, call_base, call_top, &pp, &pc, &FP, &SP);
+    DISPATCH();
+  }
+
+  {
     BYTECODE(InstanceCall1, A_D);
 
     // Check if single stepping.
@@ -1694,6 +1710,316 @@
     DISPATCH();
   }
 
+  {
+    BYTECODE(ShrImm, A_B_C);
+    const uint8_t shift = rC;
+    const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]) >> kSmiTagSize;
+    *reinterpret_cast<intptr_t*>(&FP[rA]) = (lhs >> shift) << kSmiTagSize;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(Min, A_B_C);
+    const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
+    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]);
+    FP[rA] = reinterpret_cast<RawObject*>((lhs < rhs) ? lhs : rhs);
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(Max, A_B_C);
+    const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
+    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]);
+    FP[rA] = reinterpret_cast<RawObject*>((lhs > rhs) ? lhs : rhs);
+    DISPATCH();
+  }
+
+#if defined(ARCH_IS_64_BIT)
+  {
+    BYTECODE(WriteIntoDouble, A_D);
+    const double value = bit_cast<double, RawObject*>(FP[rD]);
+    RawDouble* box = RAW_CAST(Double, *SP--);
+    box->ptr()->value_ = value;
+    FP[rA] = box;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(UnboxDouble, A_D);
+    const RawDouble* box = RAW_CAST(Double, FP[rD]);
+    FP[rA] = bit_cast<RawObject*, double>(box->ptr()->value_);
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(CheckedUnboxDouble, A_D);
+    const intptr_t box_cid = SimulatorHelpers::GetClassId(FP[rD]);
+    if (box_cid == kSmiCid) {
+      const intptr_t value = reinterpret_cast<intptr_t>(FP[rD]) >> kSmiTagSize;
+      const double result = static_cast<double>(value);
+      FP[rA] = bit_cast<RawObject*, double>(result);
+      pc++;
+    } else if (box_cid == kDoubleCid) {
+      const RawDouble* box = RAW_CAST(Double, FP[rD]);
+      FP[rA] = bit_cast<RawObject*, double>(box->ptr()->value_);
+      pc++;
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DoubleToSmi, A_D);
+    const double value = bit_cast<double, RawObject*>(FP[rD]);
+    if (!isnan(value)) {
+      const intptr_t result = static_cast<intptr_t>(value);
+      if ((result <= Smi::kMaxValue) && (result >= Smi::kMinValue)) {
+        FP[rA] = reinterpret_cast<RawObject*>(result << kSmiTagSize);
+        pc++;
+      }
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(SmiToDouble, A_D);
+    const intptr_t value = reinterpret_cast<intptr_t>(FP[rD]) >> kSmiTagSize;
+    const double result = static_cast<double>(value);
+    FP[rA] = bit_cast<RawObject*, double>(result);
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DAdd, A_B_C);
+    const double lhs = bit_cast<double, RawObject*>(FP[rB]);
+    const double rhs = bit_cast<double, RawObject*>(FP[rC]);
+    FP[rA] = bit_cast<RawObject*, double>(lhs + rhs);
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DSub, A_B_C);
+    const double lhs = bit_cast<double, RawObject*>(FP[rB]);
+    const double rhs = bit_cast<double, RawObject*>(FP[rC]);
+    FP[rA] = bit_cast<RawObject*, double>(lhs - rhs);
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DMul, A_B_C);
+    const double lhs = bit_cast<double, RawObject*>(FP[rB]);
+    const double rhs = bit_cast<double, RawObject*>(FP[rC]);
+    FP[rA] = bit_cast<RawObject*, double>(lhs * rhs);
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DDiv, A_B_C);
+    const double lhs = bit_cast<double, RawObject*>(FP[rB]);
+    const double rhs = bit_cast<double, RawObject*>(FP[rC]);
+    const double result = lhs / rhs;
+    FP[rA] = bit_cast<RawObject*, double>(result);
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DNeg, A_D);
+    const double value = bit_cast<double, RawObject*>(FP[rD]);
+    FP[rA] = bit_cast<RawObject*, double>(-value);
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DSqrt, A_D);
+    const double value = bit_cast<double, RawObject*>(FP[rD]);
+    FP[rA] = bit_cast<RawObject*, double>(sqrt(value));
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DSin, A_D);
+    const double value = bit_cast<double, RawObject*>(FP[rD]);
+    FP[rA] = bit_cast<RawObject*, double>(sin(value));
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DCos, A_D);
+    const double value = bit_cast<double, RawObject*>(FP[rD]);
+    FP[rA] = bit_cast<RawObject*, double>(cos(value));
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DPow, A_B_C);
+    const double lhs = bit_cast<double, RawObject*>(FP[rB]);
+    const double rhs = bit_cast<double, RawObject*>(FP[rC]);
+    const double result = pow(lhs, rhs);
+    FP[rA] = bit_cast<RawObject*, double>(result);
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DMod, A_B_C);
+    const double lhs = bit_cast<double, RawObject*>(FP[rB]);
+    const double rhs = bit_cast<double, RawObject*>(FP[rC]);
+    const double result = DartModulo(lhs, rhs);
+    FP[rA] = bit_cast<RawObject*, double>(result);
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DMin, A_B_C);
+    const double lhs = bit_cast<double, RawObject*>(FP[rB]);
+    const double rhs = bit_cast<double, RawObject*>(FP[rC]);
+    FP[rA] = bit_cast<RawObject*, double>(fmin(lhs, rhs));
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DMax, A_B_C);
+    const double lhs = bit_cast<double, RawObject*>(FP[rB]);
+    const double rhs = bit_cast<double, RawObject*>(FP[rC]);
+    FP[rA] = bit_cast<RawObject*, double>(fmax(lhs, rhs));
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(LoadFloat64Indexed, A_B_C);
+    ASSERT(RawObject::IsTypedDataClassId(FP[rB]->GetClassId()));
+    RawTypedData* array = reinterpret_cast<RawTypedData*>(FP[rB]);
+    RawSmi* index = RAW_CAST(Smi, FP[rC]);
+    ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
+    double* data = reinterpret_cast<double*>(array->ptr()->data());
+    FP[rA] = bit_cast<RawObject*, double>(data[Smi::Value(index)]);
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(StoreFloat64Indexed, A_B_C);
+    ASSERT(RawObject::IsTypedDataClassId(FP[rA]->GetClassId()));
+    RawTypedData* array = reinterpret_cast<RawTypedData*>(FP[rA]);
+    RawSmi* index = RAW_CAST(Smi, FP[rB]);
+    ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
+    double* data = reinterpret_cast<double*>(array->ptr()->data());
+    data[Smi::Value(index)] = bit_cast<double, RawObject*>(FP[rC]);
+    DISPATCH();
+  }
+#else  // defined(ARCH_IS_64_BIT)
+  {
+    BYTECODE(WriteIntoDouble, A_D);
+    UNIMPLEMENTED();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(UnboxDouble, A_D);
+    UNIMPLEMENTED();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(CheckedUnboxDouble, A_D);
+    UNIMPLEMENTED();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DoubleToSmi, A_D);
+    UNREACHABLE();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(SmiToDouble, A_D);
+    UNIMPLEMENTED();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DAdd, A_B_C);
+    UNIMPLEMENTED();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DSub, A_B_C);
+    UNIMPLEMENTED();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DMul, A_B_C);
+    UNIMPLEMENTED();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DDiv, A_B_C);
+    UNIMPLEMENTED();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DNeg, A_D);
+    UNIMPLEMENTED();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DSqrt, A_D);
+    UNREACHABLE();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DSin, A_D);
+    UNREACHABLE();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DCos, A_D);
+    UNREACHABLE();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DPow, A_B_C);
+    UNREACHABLE();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DMod, A_B_C);
+    UNREACHABLE();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DMin, A_B_C);
+    UNREACHABLE();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DMax, A_B_C);
+    UNREACHABLE();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(LoadFloat64Indexed, A_B_C);
+    UNREACHABLE();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(StoreFloat64Indexed, A_B_C);
+    UNREACHABLE();
+    DISPATCH();
+  }
+#endif  // defined(ARCH_IS_64_BIT)
+
   // Return and return like instructions (Instrinsic).
   {
     RawObject* result;  // result to return to the caller.
@@ -2058,6 +2384,27 @@
   }
 
   {
+    BYTECODE(TestCids, A_D);
+    const intptr_t cid = SimulatorHelpers::GetClassId(FP[rA]);
+    const intptr_t num_cases = rD;
+    for (intptr_t i = 0; i < num_cases; i++) {
+      ASSERT(Bytecode::DecodeOpcode(pc[i]) == Bytecode::kNop);
+      intptr_t test_target = Bytecode::DecodeA(pc[i]);
+      intptr_t test_cid = Bytecode::DecodeD(pc[i]);
+      if (cid == test_cid) {
+        if (test_target != 0) {
+          pc += 1;  // Match true.
+        } else {
+          pc += 2;  // Match false.
+        }
+        break;
+      }
+    }
+    pc += num_cases;
+    DISPATCH();
+  }
+
+  {
     BYTECODE(CheckSmi, 0);
     intptr_t obj = reinterpret_cast<intptr_t>(FP[rA]);
     if ((obj & kSmiTagMask) == kSmiTag) {
@@ -2067,8 +2414,20 @@
   }
 
   {
+    BYTECODE(CheckEitherNonSmi, A_D);
+    const intptr_t obj1 = reinterpret_cast<intptr_t>(FP[rA]);
+    const intptr_t obj2 = reinterpret_cast<intptr_t>(FP[rD]);
+    const intptr_t tag = (obj1 | obj2) & kSmiTagMask;
+    if (tag != kSmiTag) {
+      pc++;
+    }
+    DISPATCH();
+  }
+
+  {
     BYTECODE(CheckClassId, A_D);
-    const intptr_t actual_cid = SimulatorHelpers::GetClassId(FP[rA]);
+    const intptr_t actual_cid =
+        reinterpret_cast<intptr_t>(FP[rA]) >> kSmiTagSize;
     const intptr_t desired_cid = rD;
     pc += (actual_cid == desired_cid) ? 1 : 0;
     DISPATCH();
@@ -2194,6 +2553,172 @@
   }
 
   {
+    BYTECODE(IfLe, A_D);
+    const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rA]);
+    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rD]);
+    if (lhs > rhs) {
+      pc++;
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(IfLt, A_D);
+    const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rA]);
+    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rD]);
+    if (lhs >= rhs) {
+      pc++;
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(IfGe, A_D);
+    const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rA]);
+    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rD]);
+    if (lhs < rhs) {
+      pc++;
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(IfGt, A_D);
+    const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rA]);
+    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rD]);
+    if (lhs <= rhs) {
+      pc++;
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(IfULe, A_D);
+    const uintptr_t lhs = reinterpret_cast<uintptr_t>(FP[rA]);
+    const uintptr_t rhs = reinterpret_cast<uintptr_t>(FP[rD]);
+    if (lhs > rhs) {
+      pc++;
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(IfULt, A_D);
+    const uintptr_t lhs = reinterpret_cast<uintptr_t>(FP[rA]);
+    const uintptr_t rhs = reinterpret_cast<uintptr_t>(FP[rD]);
+    if (lhs >= rhs) {
+      pc++;
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(IfUGe, A_D);
+    const uintptr_t lhs = reinterpret_cast<uintptr_t>(FP[rA]);
+    const uintptr_t rhs = reinterpret_cast<uintptr_t>(FP[rD]);
+    if (lhs < rhs) {
+      pc++;
+    }
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(IfUGt, A_D);
+    const uintptr_t lhs = reinterpret_cast<uintptr_t>(FP[rA]);
+    const uintptr_t rhs = reinterpret_cast<uintptr_t>(FP[rD]);
+    if (lhs <= rhs) {
+      pc++;
+    }
+    DISPATCH();
+  }
+
+#if defined(ARCH_IS_64_BIT)
+  {
+    BYTECODE(IfDEq, A_D);
+    const double lhs = bit_cast<double, RawObject*>(FP[rA]);
+    const double rhs = bit_cast<double, RawObject*>(FP[rD]);
+    pc += (lhs == rhs) ? 0 : 1;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(IfDNe, A_D);
+    const double lhs = bit_cast<double, RawObject*>(FP[rA]);
+    const double rhs = bit_cast<double, RawObject*>(FP[rD]);
+    pc += (lhs != rhs) ? 0 : 1;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(IfDLe, A_D);
+    const double lhs = bit_cast<double, RawObject*>(FP[rA]);
+    const double rhs = bit_cast<double, RawObject*>(FP[rD]);
+    pc += (lhs <= rhs) ? 0 : 1;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(IfDLt, A_D);
+    const double lhs = bit_cast<double, RawObject*>(FP[rA]);
+    const double rhs = bit_cast<double, RawObject*>(FP[rD]);
+    pc += (lhs < rhs) ? 0 : 1;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(IfDGe, A_D);
+    const double lhs = bit_cast<double, RawObject*>(FP[rA]);
+    const double rhs = bit_cast<double, RawObject*>(FP[rD]);
+    pc += (lhs >= rhs) ? 0 : 1;
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(IfDGt, A_D);
+    const double lhs = bit_cast<double, RawObject*>(FP[rA]);
+    const double rhs = bit_cast<double, RawObject*>(FP[rD]);
+    pc += (lhs > rhs) ? 0 : 1;
+    DISPATCH();
+  }
+#else  // defined(ARCH_IS_64_BIT)
+  {
+    BYTECODE(IfDEq, A_D);
+    UNREACHABLE();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(IfDNe, A_D);
+    UNREACHABLE();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(IfDLe, A_D);
+    UNREACHABLE();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(IfDLt, A_D);
+    UNREACHABLE();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(IfDGe, A_D);
+    UNREACHABLE();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(IfDGt, A_D);
+    UNREACHABLE();
+    DISPATCH();
+  }
+#endif  // defined(ARCH_IS_64_BIT)
+
+  {
     BYTECODE(IfEqStrictNum, A_D);
     RawObject* lhs = FP[rA];
     RawObject* rhs = FP[rD];
@@ -2254,11 +2779,9 @@
   {
     BYTECODE(StoreIndexedTOS, 0);
     SP -= 3;
-    RawArray* array = static_cast<RawArray*>(SP[1]);
-    RawSmi* index = static_cast<RawSmi*>(SP[2]);
+    RawArray* array = RAW_CAST(Array, SP[1]);
+    RawSmi* index = RAW_CAST(Smi, SP[2]);
     RawObject* value = SP[3];
-    ASSERT(array->GetClassId() == kArrayCid);
-    ASSERT(!index->IsHeapObject());
     ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
     array->StorePointer(array->ptr()->data() + Smi::Value(index), value);
     DISPATCH();
@@ -2266,17 +2789,42 @@
 
   {
     BYTECODE(StoreIndexed, A_B_C);
-    RawArray* array = static_cast<RawArray*>(FP[rA]);
-    RawSmi* index = static_cast<RawSmi*>(FP[rB]);
+    RawArray* array = RAW_CAST(Array, FP[rA]);
+    RawSmi* index = RAW_CAST(Smi, FP[rB]);
     RawObject* value = FP[rC];
-    ASSERT(array->GetClassId() == kArrayCid);
-    ASSERT(!index->IsHeapObject());
     ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
     array->StorePointer(array->ptr()->data() + Smi::Value(index), value);
     DISPATCH();
   }
 
   {
+    BYTECODE(LoadIndexed, A_B_C);
+    RawArray* array = RAW_CAST(Array, FP[rB]);
+    RawSmi* index = RAW_CAST(Smi, FP[rC]);
+    ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
+    FP[rA] = array->ptr()->data()[Smi::Value(index)];
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(LoadOneByteStringIndexed, A_B_C);
+    RawOneByteString* array = RAW_CAST(OneByteString, FP[rB]);
+    RawSmi* index = RAW_CAST(Smi, FP[rC]);
+    ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
+    FP[rA] = Smi::New(array->ptr()->data()[Smi::Value(index)]);
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(LoadTwoByteStringIndexed, A_B_C);
+    RawTwoByteString* array = RAW_CAST(TwoByteString, FP[rB]);
+    RawSmi* index = RAW_CAST(Smi, FP[rC]);
+    ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
+    FP[rA] = Smi::New(array->ptr()->data()[Smi::Value(index)]);
+    DISPATCH();
+  }
+
+  {
     BYTECODE(Deopt, A_D);
     const bool is_lazy = rD == 0;
 
@@ -2422,6 +2970,7 @@
   return 0;
 }
 
+
 void Simulator::Longjmp(uword pc,
                         uword sp,
                         uword fp,
@@ -2459,5 +3008,4 @@
 
 }  // namespace dart
 
-
 #endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index 4195995..6a4371f 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -166,14 +166,10 @@
 SnapshotReader::SnapshotReader(
     const uint8_t* buffer,
     intptr_t size,
-    const uint8_t* instructions_buffer,
-    const uint8_t* data_buffer,
     Snapshot::Kind kind,
     ZoneGrowableArray<BackRefNode>* backward_refs,
     Thread* thread)
     : BaseReader(buffer, size),
-      instructions_buffer_(instructions_buffer),
-      data_buffer_(data_buffer),
       kind_(kind),
       thread_(thread),
       zone_(thread->zone()),
@@ -192,19 +188,12 @@
       stream_(TokenStream::Handle(zone_)),
       data_(ExternalTypedData::Handle(zone_)),
       typed_data_(TypedData::Handle(zone_)),
-      code_(Code::Handle(zone_)),
       function_(Function::Handle(zone_)),
-      megamorphic_cache_(MegamorphicCache::Handle(zone_)),
       error_(UnhandledException::Handle(zone_)),
       max_vm_isolate_object_id_(
           (Snapshot::IsFull(kind)) ?
               Object::vm_isolate_snapshot_object_table().Length() : 0),
-      backward_references_(backward_refs),
-      instructions_reader_(NULL) {
-  if (instructions_buffer != NULL) {
-    instructions_reader_ =
-        new InstructionsReader(instructions_buffer, data_buffer);
-  }
+      backward_references_(backward_refs) {
 }
 
 
@@ -220,9 +209,7 @@
         (*backward_references_)[i].set_state(kIsDeserialized);
       }
     }
-    if (!Snapshot::IsFull(kind())) {
-      ProcessDeferredCanonicalizations();
-    }
+    ProcessDeferredCanonicalizations();
     return obj.raw();
   } else {
     // An error occurred while reading, return the error object.
@@ -480,11 +467,7 @@
     instance_size = cls_.instance_size();
     ASSERT(instance_size > 0);
     // Allocate the instance and read in all the fields for the object.
-    if (Snapshot::IsFull(kind_)) {
-      *result ^= AllocateUninitialized(cls_.id(), instance_size);
-    } else {
-      *result ^= Object::Allocate(cls_.id(), instance_size, HEAP_SPACE(kind_));
-    }
+    *result ^= Object::Allocate(cls_.id(), instance_size, HEAP_SPACE(kind_));
   } else {
     cls_ ^= ReadObjectImpl(kAsInlinedObject);
     ASSERT(!cls_.IsNull());
@@ -522,21 +505,9 @@
       // snapshot (kFull, kScript) with asserts.
       offset += kWordSize;
     }
-    if (Snapshot::IsFull(kind_)) {
-      // We create an uninitialized object in the case of full snapshots, so
-      // we need to initialize any remaining padding area with the Null object.
-      while (offset < instance_size) {
-        result->SetFieldAtOffset(offset, Object::null_object());
-        offset += kWordSize;
-      }
-    }
     if (RawObject::IsCanonical(tags)) {
-      if (Snapshot::IsFull(kind_)) {
-        result->SetCanonical();
-      } else {
-        *result = result->CheckAndCanonicalize(thread(), NULL);
-        ASSERT(!result->IsNull());
-      }
+      *result = result->CheckAndCanonicalize(thread(), NULL);
+      ASSERT(!result->IsNull());
     }
   }
   return result->raw();
@@ -681,418 +652,16 @@
 }
 
 
-#define ALLOC_NEW_OBJECT_WITH_LEN(type, length)                                \
-  ASSERT(Snapshot::IsFull(kind_));                                            \
-  ASSERT_NO_SAFEPOINT_SCOPE();                                                 \
-  Raw##type* obj = reinterpret_cast<Raw##type*>(                               \
-      AllocateUninitialized(k##type##Cid, type::InstanceSize(length)));        \
-  obj->StoreSmi(&(obj->ptr()->length_), Smi::New(length));                     \
-  return obj;                                                                  \
-
-
-RawArray* SnapshotReader::NewArray(intptr_t len) {
-  ALLOC_NEW_OBJECT_WITH_LEN(Array, len);
-}
-
-
-RawImmutableArray* SnapshotReader::NewImmutableArray(intptr_t len) {
-  ALLOC_NEW_OBJECT_WITH_LEN(ImmutableArray, len);
-}
-
-
-RawOneByteString* SnapshotReader::NewOneByteString(intptr_t len) {
-  ALLOC_NEW_OBJECT_WITH_LEN(OneByteString, len);
-}
-
-
-RawTwoByteString* SnapshotReader::NewTwoByteString(intptr_t len) {
-  ALLOC_NEW_OBJECT_WITH_LEN(TwoByteString, len);
-}
-
-
-RawTypeArguments* SnapshotReader::NewTypeArguments(intptr_t len) {
-  ALLOC_NEW_OBJECT_WITH_LEN(TypeArguments, len);
-}
-
-
-RawObjectPool* SnapshotReader::NewObjectPool(intptr_t len) {
-  ASSERT(Snapshot::IsFull(kind_));
-  ASSERT_NO_SAFEPOINT_SCOPE();
-  RawObjectPool* obj = reinterpret_cast<RawObjectPool*>(
-      AllocateUninitialized(kObjectPoolCid, ObjectPool::InstanceSize(len)));
-  obj->ptr()->length_ = len;
-  return obj;
-}
-
-
-RawLocalVarDescriptors* SnapshotReader::NewLocalVarDescriptors(
-    intptr_t num_entries) {
-  ASSERT(Snapshot::IsFull(kind_));
-  ASSERT_NO_SAFEPOINT_SCOPE();
-  RawLocalVarDescriptors* obj = reinterpret_cast<RawLocalVarDescriptors*>(
-      AllocateUninitialized(kLocalVarDescriptorsCid,
-                            LocalVarDescriptors::InstanceSize(num_entries)));
-  obj->ptr()->num_entries_ = num_entries;
-  return obj;
-}
-
-
-RawExceptionHandlers* SnapshotReader::NewExceptionHandlers(
-    intptr_t num_entries) {
-  ASSERT(Snapshot::IsFull(kind_));
-  ASSERT_NO_SAFEPOINT_SCOPE();
-  RawExceptionHandlers* obj = reinterpret_cast<RawExceptionHandlers*>(
-      AllocateUninitialized(kExceptionHandlersCid,
-                            ExceptionHandlers::InstanceSize(num_entries)));
-  obj->ptr()->num_entries_ = num_entries;
-  return obj;
-}
-
-
-RawPcDescriptors* SnapshotReader::NewPcDescriptors(intptr_t len) {
-  ASSERT(Snapshot::IsFull(kind_));
-  ASSERT_NO_SAFEPOINT_SCOPE();
-  RawPcDescriptors* obj = reinterpret_cast<RawPcDescriptors*>(
-      AllocateUninitialized(kPcDescriptorsCid,
-                            PcDescriptors::InstanceSize(len)));
-  obj->ptr()->length_ = len;
-  return obj;
-}
-
-
-RawCodeSourceMap* SnapshotReader::NewCodeSourceMap(intptr_t len) {
-  ASSERT(Snapshot::IsFull(kind_));
-  ASSERT_NO_SAFEPOINT_SCOPE();
-  RawCodeSourceMap* obj = reinterpret_cast<RawCodeSourceMap*>(
-      AllocateUninitialized(kCodeSourceMapCid,
-                            CodeSourceMap::InstanceSize(len)));
-  obj->ptr()->length_ = len;
-  return obj;
-}
-
-
-RawStackmap* SnapshotReader::NewStackmap(intptr_t len) {
-  ASSERT(Snapshot::IsFull(kind_));
-  ASSERT_NO_SAFEPOINT_SCOPE();
-  RawStackmap* obj = reinterpret_cast<RawStackmap*>(
-      AllocateUninitialized(kStackmapCid, Stackmap::InstanceSize(len)));
-  obj->ptr()->length_ = len;
-  return obj;
-}
-
-
-RawContextScope* SnapshotReader::NewContextScope(intptr_t num_variables) {
-  ASSERT(Snapshot::IsFull(kind_));
-  ASSERT_NO_SAFEPOINT_SCOPE();
-  RawContextScope* obj = reinterpret_cast<RawContextScope*>(
-      AllocateUninitialized(kContextScopeCid,
-                            ContextScope::InstanceSize(num_variables)));
-  obj->ptr()->num_variables_ = num_variables;
-  return obj;
-}
-
-
-RawCode* SnapshotReader::NewCode(intptr_t pointer_offsets_length) {
-  ASSERT(pointer_offsets_length == 0);
-  ASSERT(Snapshot::IsFull(kind_));
-  ASSERT_NO_SAFEPOINT_SCOPE();
-  RawCode* obj = reinterpret_cast<RawCode*>(
-      AllocateUninitialized(kCodeCid, Code::InstanceSize(0)));
-  return obj;
-}
-
-
-RawTokenStream* SnapshotReader::NewTokenStream(intptr_t len) {
-  ASSERT(Snapshot::IsFull(kind_));
-  ASSERT_NO_SAFEPOINT_SCOPE();
-  stream_ = reinterpret_cast<RawTokenStream*>(
-      AllocateUninitialized(kTokenStreamCid, TokenStream::InstanceSize()));
-  uint8_t* array = const_cast<uint8_t*>(CurrentBufferAddress());
-  ASSERT(array != NULL);
-  Advance(len);
-  data_ = reinterpret_cast<RawExternalTypedData*>(
-      AllocateUninitialized(kExternalTypedDataUint8ArrayCid,
-                            ExternalTypedData::InstanceSize()));
-  data_.SetData(array);
-  data_.SetLength(len);
-  stream_.SetStream(data_);
-  return stream_.raw();
-}
-
-
-RawContext* SnapshotReader::NewContext(intptr_t num_variables) {
-  ASSERT(Snapshot::IsFull(kind_));
-  ASSERT_NO_SAFEPOINT_SCOPE();
-  RawContext* obj = reinterpret_cast<RawContext*>(
-      AllocateUninitialized(kContextCid, Context::InstanceSize(num_variables)));
-  obj->ptr()->num_variables_ = num_variables;
-  return obj;
-}
-
-
-RawClass* SnapshotReader::NewClass(intptr_t class_id) {
-  ASSERT(Snapshot::IsFull(kind_));
-  ASSERT_NO_SAFEPOINT_SCOPE();
-  if (class_id < kNumPredefinedCids) {
-    ASSERT((class_id >= kInstanceCid) &&
-           (class_id <= kNullCid));
-    return isolate()->class_table()->At(class_id);
-  }
-  RawClass* obj = reinterpret_cast<RawClass*>(
-      AllocateUninitialized(kClassCid, Class::InstanceSize()));
-  Instance fake;
-  obj->ptr()->handle_vtable_ = fake.vtable();
-  cls_ = obj;
-  cls_.set_id(class_id);
-  isolate()->RegisterClassAt(class_id, cls_);
-  return cls_.raw();
-}
-
-
-RawInstance* SnapshotReader::NewInstance() {
-  ASSERT(Snapshot::IsFull(kind_));
-  ASSERT_NO_SAFEPOINT_SCOPE();
-  RawInstance* obj = reinterpret_cast<RawInstance*>(
-      AllocateUninitialized(kInstanceCid, Instance::InstanceSize()));
-  return obj;
-}
-
-
-RawMint* SnapshotReader::NewMint(int64_t value) {
-  ASSERT(Snapshot::IsFull(kind_));
-  ASSERT_NO_SAFEPOINT_SCOPE();
-  RawMint* obj = reinterpret_cast<RawMint*>(
-      AllocateUninitialized(kMintCid, Mint::InstanceSize()));
-  obj->ptr()->value_ = value;
-  return obj;
-}
-
-
-RawDouble* SnapshotReader::NewDouble(double value) {
-  ASSERT(Snapshot::IsFull(kind_));
-  ASSERT_NO_SAFEPOINT_SCOPE();
-  RawDouble* obj = reinterpret_cast<RawDouble*>(
-      AllocateUninitialized(kDoubleCid, Double::InstanceSize()));
-  obj->ptr()->value_ = value;
-  return obj;
-}
-
-
-RawTypedData* SnapshotReader::NewTypedData(intptr_t class_id, intptr_t len) {
-  ASSERT(Snapshot::IsFull(kind_));
-  ASSERT_NO_SAFEPOINT_SCOPE();
-  const intptr_t lengthInBytes = len * TypedData::ElementSizeInBytes(class_id);
-  RawTypedData* obj = reinterpret_cast<RawTypedData*>(
-      AllocateUninitialized(class_id, TypedData::InstanceSize(lengthInBytes)));
-  obj->StoreSmi(&(obj->ptr()->length_), Smi::New(len));
-  return obj;
-}
-
-
-#define ALLOC_NEW_OBJECT(type)                                                 \
-  ASSERT(Snapshot::IsFull(kind_));                                            \
-  ASSERT_NO_SAFEPOINT_SCOPE();                                                 \
-  return reinterpret_cast<Raw##type*>(                                         \
-      AllocateUninitialized(k##type##Cid, type::InstanceSize()));              \
-
-
-RawBigint* SnapshotReader::NewBigint() {
-  ALLOC_NEW_OBJECT(Bigint);
-}
-
-
-RawUnresolvedClass* SnapshotReader::NewUnresolvedClass() {
-  ALLOC_NEW_OBJECT(UnresolvedClass);
-}
-
-
-RawType* SnapshotReader::NewType() {
-  ALLOC_NEW_OBJECT(Type);
-}
-
-
-RawTypeRef* SnapshotReader::NewTypeRef() {
-  ALLOC_NEW_OBJECT(TypeRef);
-}
-
-
-RawTypeParameter* SnapshotReader::NewTypeParameter() {
-  ALLOC_NEW_OBJECT(TypeParameter);
-}
-
-
-RawBoundedType* SnapshotReader::NewBoundedType() {
-  ALLOC_NEW_OBJECT(BoundedType);
-}
-
-
-RawMixinAppType* SnapshotReader::NewMixinAppType() {
-  ALLOC_NEW_OBJECT(MixinAppType);
-}
-
-
-RawPatchClass* SnapshotReader::NewPatchClass() {
-  ALLOC_NEW_OBJECT(PatchClass);
-}
-
-
-RawClosure* SnapshotReader::NewClosure() {
-  ALLOC_NEW_OBJECT(Closure);
-}
-
-
-RawClosureData* SnapshotReader::NewClosureData() {
-  ALLOC_NEW_OBJECT(ClosureData);
-}
-
-
-RawRedirectionData* SnapshotReader::NewRedirectionData() {
-  ALLOC_NEW_OBJECT(RedirectionData);
-}
-
-
-RawFunction* SnapshotReader::NewFunction() {
-  ALLOC_NEW_OBJECT(Function);
-}
-
-
-RawICData* SnapshotReader::NewICData() {
-  ALLOC_NEW_OBJECT(ICData);
-}
-
-
-RawLinkedHashMap* SnapshotReader::NewLinkedHashMap() {
-  ALLOC_NEW_OBJECT(LinkedHashMap);
-}
-
-
-RawMegamorphicCache* SnapshotReader::NewMegamorphicCache() {
-  ALLOC_NEW_OBJECT(MegamorphicCache);
-}
-
-
-RawSubtypeTestCache* SnapshotReader::NewSubtypeTestCache() {
-  ALLOC_NEW_OBJECT(SubtypeTestCache);
-}
-
-
-RawField* SnapshotReader::NewField() {
-  ALLOC_NEW_OBJECT(Field);
-}
-
-
-RawLibrary* SnapshotReader::NewLibrary() {
-  ALLOC_NEW_OBJECT(Library);
-}
-
-
-RawLibraryPrefix* SnapshotReader::NewLibraryPrefix() {
-  ALLOC_NEW_OBJECT(LibraryPrefix);
-}
-
-
-RawNamespace* SnapshotReader::NewNamespace() {
-  ALLOC_NEW_OBJECT(Namespace);
-}
-
-
-RawScript* SnapshotReader::NewScript() {
-  ALLOC_NEW_OBJECT(Script);
-}
-
-
-RawLiteralToken* SnapshotReader::NewLiteralToken() {
-  ALLOC_NEW_OBJECT(LiteralToken);
-}
-
-
-RawGrowableObjectArray* SnapshotReader::NewGrowableObjectArray() {
-  ALLOC_NEW_OBJECT(GrowableObjectArray);
-}
-
-
-RawWeakProperty* SnapshotReader::NewWeakProperty() {
-  ALLOC_NEW_OBJECT(WeakProperty);
-}
-
-
-RawRegExp* SnapshotReader::NewRegExp() {
-  ALLOC_NEW_OBJECT(RegExp);
-}
-
-
-RawFloat32x4* SnapshotReader::NewFloat32x4(float v0, float v1, float v2,
-                                           float v3) {
-  ASSERT(Snapshot::IsFull(kind_));
-  ASSERT_NO_SAFEPOINT_SCOPE();
-  RawFloat32x4* obj = reinterpret_cast<RawFloat32x4*>(
-      AllocateUninitialized(kFloat32x4Cid, Float32x4::InstanceSize()));
-  obj->ptr()->value_[0] = v0;
-  obj->ptr()->value_[1] = v1;
-  obj->ptr()->value_[2] = v2;
-  obj->ptr()->value_[3] = v3;
-  return obj;
-}
-
-
-RawInt32x4* SnapshotReader::NewInt32x4(uint32_t v0, uint32_t v1, uint32_t v2,
-                                       uint32_t v3) {
-  ASSERT(Snapshot::IsFull(kind_));
-  ASSERT_NO_SAFEPOINT_SCOPE();
-  RawInt32x4* obj = reinterpret_cast<RawInt32x4*>(
-      AllocateUninitialized(kInt32x4Cid, Int32x4::InstanceSize()));
-  obj->ptr()->value_[0] = v0;
-  obj->ptr()->value_[1] = v1;
-  obj->ptr()->value_[2] = v2;
-  obj->ptr()->value_[3] = v3;
-  return obj;
-}
-
-
-RawFloat64x2* SnapshotReader::NewFloat64x2(double v0, double v1) {
-  ASSERT(Snapshot::IsFull(kind_));
-  ASSERT_NO_SAFEPOINT_SCOPE();
-  RawFloat64x2* obj = reinterpret_cast<RawFloat64x2*>(
-      AllocateUninitialized(kFloat64x2Cid, Float64x2::InstanceSize()));
-  obj->ptr()->value_[0] = v0;
-  obj->ptr()->value_[1] = v1;
-  return obj;
-}
-
-
-RawApiError* SnapshotReader::NewApiError() {
-  ALLOC_NEW_OBJECT(ApiError);
-}
-
-
-RawLanguageError* SnapshotReader::NewLanguageError() {
-  ALLOC_NEW_OBJECT(LanguageError);
-}
-
-
-RawUnhandledException* SnapshotReader::NewUnhandledException() {
-  ALLOC_NEW_OBJECT(UnhandledException);
-}
-
-
 RawObject* SnapshotReader::NewInteger(int64_t value) {
   ASSERT((value & kSmiTagMask) == kSmiTag);
   value = value >> kSmiTagShift;
   if (Smi::IsValid(value)) {
     return Smi::New(static_cast<intptr_t>(value));
   }
-  if (Snapshot::IsFull(kind_)) {
-    return NewMint(value);
-  }
   return Mint::NewCanonical(value);
 }
 
 
-RawStacktrace* SnapshotReader::NewStacktrace() {
-  ALLOC_NEW_OBJECT(Stacktrace);
-}
-
-
 int32_t InstructionsWriter::GetOffsetFor(RawInstructions* instructions,
                                          RawCode* code) {
 #if defined(PRODUCT)
@@ -1422,34 +991,6 @@
 }
 
 
-RawObject* SnapshotReader::AllocateUninitialized(intptr_t class_id,
-                                                 intptr_t size) {
-  ASSERT_NO_SAFEPOINT_SCOPE();
-  ASSERT(Utils::IsAligned(size, kObjectAlignment));
-
-  uword address =
-      old_space()->TryAllocateDataBumpLocked(size, PageSpace::kForceGrowth);
-  if (address == 0) {
-    // Use the preallocated out of memory exception to avoid calling
-    // into dart code or allocating any code.
-    // We do a longjmp at this point to unwind out of the entire
-    // read part and return the error object back.
-    const UnhandledException& error = UnhandledException::Handle(
-        object_store()->preallocated_unhandled_exception());
-    thread()->long_jump_base()->Jump(1, error);
-  }
-
-  RawObject* raw_obj = reinterpret_cast<RawObject*>(address + kHeapObjectTag);
-  uword tags = 0;
-  ASSERT(class_id != kIllegalCid);
-  tags = RawObject::ClassIdTag::update(class_id, tags);
-  tags = RawObject::SizeTag::update(size, tags);
-  tags = RawObject::VMHeapObjectTag::update(is_vm_isolate(), tags);
-  raw_obj->ptr()->tags_ = tags;
-  return raw_obj;
-}
-
-
 #define READ_VM_SINGLETON_OBJ(id, obj)                                         \
   if (object_id == id) {                                                       \
     return obj;                                                                \
@@ -1520,10 +1061,8 @@
   if (IsObjectStoreClassId(class_id)) {
     return isolate()->class_table()->At(class_id);  // get singleton class.
   }
-  if (!Snapshot::IsFull(kind_)) {
-    if (IsObjectStoreTypeId(object_id)) {
-      return GetType(object_store(), object_id);  // return type obj.
-    }
+  if (IsObjectStoreTypeId(object_id)) {
+    return GetType(object_store(), object_id);  // return type obj.
   }
   ASSERT(object_id >= kMaxPredefinedObjectIds);
   intptr_t index = (object_id - kMaxPredefinedObjectIds);
@@ -1538,7 +1077,7 @@
 void SnapshotReader::AddPatchRecord(intptr_t object_id,
                                     intptr_t patch_object_id,
                                     intptr_t patch_offset) {
-  if (patch_object_id != kInvalidPatchIndex && !Snapshot::IsFull(kind())) {
+  if (patch_object_id != kInvalidPatchIndex) {
     ASSERT(object_id >= kMaxPredefinedObjectIds);
     intptr_t index = (object_id - kMaxPredefinedObjectIds);
     ASSERT(index >= max_vm_isolate_object_id_);
@@ -1623,8 +1162,6 @@
                                            Thread* thread)
     : SnapshotReader(buffer,
                      size,
-                     NULL, /* instructions_buffer */
-                     NULL, /* data_buffer */
                      Snapshot::kScript,
                      new ZoneGrowableArray<BackRefNode>(kNumInitialReferences),
                      thread) {
@@ -1641,8 +1178,6 @@
                                              Thread* thread)
     : SnapshotReader(buffer,
                      size,
-                     NULL, /* instructions_buffer */
-                     NULL, /* data_buffer */
                      Snapshot::kMessage,
                      new ZoneGrowableArray<BackRefNode>(kNumInitialReferences),
                      thread) {
@@ -1660,21 +1195,16 @@
                                ReAlloc alloc,
                                intptr_t initial_size,
                                ForwardList* forward_list,
-                               InstructionsWriter* instructions_writer,
-                               bool can_send_any_object,
-                               bool writing_vm_isolate)
+                               bool can_send_any_object)
     : BaseWriter(buffer, alloc, initial_size),
       thread_(thread),
       kind_(kind),
       object_store_(isolate()->object_store()),
       class_table_(isolate()->class_table()),
       forward_list_(forward_list),
-      instructions_writer_(instructions_writer),
       exception_type_(Exceptions::kNone),
       exception_msg_(NULL),
-      unmarked_objects_(false),
-      can_send_any_object_(can_send_any_object),
-      writing_vm_isolate_(writing_vm_isolate) {
+      can_send_any_object_(can_send_any_object) {
   ASSERT(forward_list_ != NULL);
 }
 
@@ -1766,47 +1296,25 @@
     }
   }
 
-  if (writing_vm_isolate_) {
-    // When we are writing the VM isolate snapshot, write out the object
-    // itself instead of a VM object id.
-    return false;
-  }
-
-  if (Snapshot::IsFull(kind())) {
-    // Check it is a predefined symbol in the VM isolate.
-    id = Symbols::LookupPredefinedSymbol(rawobj);
-    if (id != kInvalidIndex) {
-      WriteVMIsolateObject(id);
-      return true;
-    }
-
-    // Check if it is an object from the vm isolate snapshot object table.
-    id = FindVmSnapshotObject(rawobj);
-    if (id != kInvalidIndex) {
-      WriteIndexedObject(id);
-      return true;
-    }
+  // In the case of script snapshots or for messages we do not use
+  // the index into the vm isolate snapshot object table, instead we
+  // explicitly write the object out.
+  intptr_t object_id = forward_list_->FindObject(rawobj);
+  if (object_id != -1) {
+    WriteIndexedObject(object_id);
+    return true;
   } else {
-    // In the case of script snapshots or for messages we do not use
-    // the index into the vm isolate snapshot object table, instead we
-    // explicitly write the object out.
-    intptr_t object_id = forward_list_->FindObject(rawobj);
-    if (object_id != -1) {
-      WriteIndexedObject(object_id);
-      return true;
-    } else {
-      switch (id) {
-        VM_OBJECT_CLASS_LIST(VM_OBJECT_WRITE)
-        case kTypedDataUint32ArrayCid: {
-          object_id = forward_list_->AddObject(zone(), rawobj, kIsSerialized);
-          RawTypedData* raw_obj = reinterpret_cast<RawTypedData*>(rawobj);
-          raw_obj->WriteTo(this, object_id, kind(), false);
-          return true;
-        }
-        default:
-          OS::Print("class id = %" Pd "\n", id);
-          break;
+    switch (id) {
+      VM_OBJECT_CLASS_LIST(VM_OBJECT_WRITE)
+      case kTypedDataUint32ArrayCid: {
+        object_id = forward_list_->AddObject(zone(), rawobj, kIsSerialized);
+        RawTypedData* raw_obj = reinterpret_cast<RawTypedData*>(rawobj);
+        raw_obj->WriteTo(this, object_id, kind(), false);
+        return true;
       }
+      default:
+        OS::Print("class id = %" Pd "\n", id);
+        break;
     }
   }
 
@@ -1930,34 +1438,32 @@
 
   // Check if it is a code object in that case just write a Null object
   // as we do not want code objects in the snapshot.
-  if (cid == kCodeCid && !Snapshot::IncludesCode(kind_)) {
+  if (cid == kCodeCid) {
     WriteVMIsolateObject(kNullObject);
     return true;
   }
 
   // Check if classes are not being serialized and it is preinitialized type
   // or a predefined internal VM class in the object store.
-  if (!Snapshot::IsFull(kind_)) {
-    // Check if it is an internal VM class which is in the object store.
-    if (cid == kClassCid) {
-      RawClass* raw_class = reinterpret_cast<RawClass*>(rawobj);
-      intptr_t class_id = raw_class->ptr()->id_;
-      if (IsObjectStoreClassId(class_id)) {
-        intptr_t object_id = ObjectIdFromClassId(class_id);
-        WriteIndexedObject(object_id);
-        return true;
-      }
-    }
-
-    // Now check it is a preinitialized type object.
-    RawType* raw_type = reinterpret_cast<RawType*>(rawobj);
-    intptr_t index = GetTypeIndex(object_store(), raw_type);
-    if (index != kInvalidIndex) {
-      WriteIndexedObject(index);
+  // Check if it is an internal VM class which is in the object store.
+  if (cid == kClassCid) {
+    RawClass* raw_class = reinterpret_cast<RawClass*>(rawobj);
+    intptr_t class_id = raw_class->ptr()->id_;
+    if (IsObjectStoreClassId(class_id)) {
+      intptr_t object_id = ObjectIdFromClassId(class_id);
+      WriteIndexedObject(object_id);
       return true;
     }
   }
 
+  // Now check it is a preinitialized type object.
+  RawType* raw_type = reinterpret_cast<RawType*>(rawobj);
+  intptr_t index = GetTypeIndex(object_store(), raw_type);
+  if (index != kInvalidIndex) {
+    WriteIndexedObject(index);
+    return true;
+  }
+
   return false;
 }
 
@@ -2358,9 +1864,7 @@
                      alloc,
                      kInitialSize,
                      &forward_list_,
-                     NULL, /* instructions_writer */
-                     true, /* can_send_any_object */
-                     false /* writing_vm_isolate */),
+                     true /* can_send_any_object */),
       forward_list_(thread(), kMaxPredefinedObjectIds) {
   ASSERT(buffer != NULL);
   ASSERT(alloc != NULL);
@@ -2414,9 +1918,7 @@
                      alloc,
                      kInitialSize,
                      &forward_list_,
-                     NULL, /* instructions_writer */
-                     can_send_any_object,
-                     false /* writing_vm_isolate */),
+                     can_send_any_object),
       forward_list_(thread(), kMaxPredefinedObjectIds) {
   ASSERT(buffer != NULL);
   ASSERT(alloc != NULL);
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 1d8f585..a2f8197 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -412,9 +412,7 @@
   TokenStream* StreamHandle() { return &stream_; }
   ExternalTypedData* DataHandle() { return &data_; }
   TypedData* TypedDataHandle() { return &typed_data_; }
-  Code* CodeHandle() { return &code_; }
   Function* FunctionHandle() { return &function_; }
-  MegamorphicCache* MegamorphicCacheHandle() { return &megamorphic_cache_; }
   Snapshot::Kind kind() const { return kind_; }
 
   // Reads an object.
@@ -435,79 +433,11 @@
   // Read version number of snapshot and verify.
   RawApiError* VerifyVersionAndFeatures();
 
-  // Helper functions for creating uninitialized versions
-  // of various object types. These are used when reading a
-  // full snapshot.
-  RawArray* NewArray(intptr_t len);
-  RawImmutableArray* NewImmutableArray(intptr_t len);
-  RawOneByteString* NewOneByteString(intptr_t len);
-  RawTwoByteString* NewTwoByteString(intptr_t len);
-  RawTypeArguments* NewTypeArguments(intptr_t len);
-  RawTokenStream* NewTokenStream(intptr_t len);
-  RawContext* NewContext(intptr_t num_variables);
-  RawClass* NewClass(intptr_t class_id);
-  RawInstance* NewInstance();
-  RawMint* NewMint(int64_t value);
-  RawBigint* NewBigint();
-  RawTypedData* NewTypedData(intptr_t class_id, intptr_t len);
-  RawDouble* NewDouble(double value);
-  RawUnresolvedClass* NewUnresolvedClass();
-  RawType* NewType();
-  RawTypeRef* NewTypeRef();
-  RawTypeParameter* NewTypeParameter();
-  RawBoundedType* NewBoundedType();
-  RawMixinAppType* NewMixinAppType();
-  RawPatchClass* NewPatchClass();
-  RawClosure* NewClosure();
-  RawClosureData* NewClosureData();
-  RawRedirectionData* NewRedirectionData();
-  RawFunction* NewFunction();
-  RawCode* NewCode(intptr_t pointer_offsets_length);
-  RawObjectPool* NewObjectPool(intptr_t length);
-  RawPcDescriptors* NewPcDescriptors(intptr_t length);
-  RawCodeSourceMap* NewCodeSourceMap(intptr_t length);
-  RawLocalVarDescriptors* NewLocalVarDescriptors(intptr_t num_entries);
-  RawExceptionHandlers* NewExceptionHandlers(intptr_t num_entries);
-  RawStackmap* NewStackmap(intptr_t length);
-  RawContextScope* NewContextScope(intptr_t num_variables);
-  RawICData* NewICData();
-  RawMegamorphicCache* NewMegamorphicCache();
-  RawSubtypeTestCache* NewSubtypeTestCache();
-  RawLinkedHashMap* NewLinkedHashMap();
-  RawField* NewField();
-  RawLibrary* NewLibrary();
-  RawLibraryPrefix* NewLibraryPrefix();
-  RawNamespace* NewNamespace();
-  RawScript* NewScript();
-  RawLiteralToken* NewLiteralToken();
-  RawGrowableObjectArray* NewGrowableObjectArray();
-  RawFloat32x4* NewFloat32x4(float v0, float v1, float v2, float v3);
-  RawInt32x4* NewInt32x4(uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3);
-  RawFloat64x2* NewFloat64x2(double v0, double v1);
-  RawApiError* NewApiError();
-  RawLanguageError* NewLanguageError();
-  RawUnhandledException* NewUnhandledException();
   RawObject* NewInteger(int64_t value);
-  RawStacktrace* NewStacktrace();
-  RawWeakProperty* NewWeakProperty();
-  RawRegExp* NewRegExp();
-
-  uword GetInstructionsAt(int32_t offset) {
-    return instructions_reader_->GetInstructionsAt(offset);
-  }
-
-  RawObject* GetObjectAt(int32_t offset) {
-    return instructions_reader_->GetObjectAt(offset);
-  }
-
-  const uint8_t* instructions_buffer_;
-  const uint8_t* data_buffer_;
 
  protected:
   SnapshotReader(const uint8_t* buffer,
                  intptr_t size,
-                 const uint8_t* instructions_buffer,
-                 const uint8_t* data_buffer,
                  Snapshot::Kind kind,
                  ZoneGrowableArray<BackRefNode>* backward_references,
                  Thread* thread);
@@ -520,9 +450,6 @@
   PageSpace* old_space() const { return old_space_; }
 
  private:
-  // Allocate uninitialized objects, this is used when reading a full snapshot.
-  RawObject* AllocateUninitialized(intptr_t class_id, intptr_t size);
-
   RawClass* ReadClassId(intptr_t object_id);
   RawFunction* ReadFunctionId(intptr_t object_id);
   RawObject* ReadStaticImplicitClosure(intptr_t object_id, intptr_t cls_header);
@@ -593,13 +520,10 @@
   TokenStream& stream_;  // Temporary token stream handle.
   ExternalTypedData& data_;  // Temporary stream data handle.
   TypedData& typed_data_;  // Temporary typed data handle.
-  Code& code_;  // Temporary code handle.
   Function& function_;  // Temporary function handle.
-  MegamorphicCache& megamorphic_cache_;  // Temporary megamorphic cache handle.
   UnhandledException& error_;  // Error handle.
   intptr_t max_vm_isolate_object_id_;
   ZoneGrowableArray<BackRefNode>* backward_references_;
-  InstructionsReader* instructions_reader_;
 
   friend class ApiError;
   friend class Array;
@@ -608,7 +532,6 @@
   friend class Class;
   friend class Closure;
   friend class ClosureData;
-  friend class Code;
   friend class Context;
   friend class ContextScope;
   friend class ExceptionHandlers;
@@ -617,23 +540,18 @@
   friend class GrowableObjectArray;
   friend class ICData;
   friend class ImmutableArray;
-  friend class Instructions;
   friend class RegExp;
   friend class LanguageError;
   friend class Library;
   friend class LibraryPrefix;
   friend class LinkedHashMap;
   friend class LiteralToken;
-  friend class LocalVarDescriptors;
-  friend class MegamorphicCache;
   friend class MirrorReference;
   friend class MixinAppType;
   friend class Namespace;
-  friend class ObjectPool;
   friend class PatchClass;
   friend class RedirectionData;
   friend class Script;
-  friend class Stacktrace;
   friend class SubtypeTestCache;
   friend class TokenStream;
   friend class Type;
@@ -945,9 +863,7 @@
                  ReAlloc alloc,
                  intptr_t initial_size,
                  ForwardList* forward_list,
-                 InstructionsWriter* instructions_writer,
-                 bool can_send_any_object,
-                 bool writing_vm_isolate = false);
+                 bool can_send_any_object);
 
  public:
   // Snapshot kind.
@@ -973,20 +889,11 @@
     exception_msg_ = msg;
   }
   bool can_send_any_object() const { return can_send_any_object_; }
-  bool writing_vm_isolate() const { return writing_vm_isolate_; }
   void ThrowException(Exceptions::ExceptionType type, const char* msg);
 
   // Write a version string for the snapshot.
   void WriteVersionAndFeatures();
 
-  int32_t GetInstructionsId(RawInstructions* instructions, RawCode* code) {
-    return instructions_writer_->GetOffsetFor(instructions, code);
-  }
-
-  int32_t GetObjectId(RawObject* raw) {
-    return instructions_writer_->GetObjectOffsetFor(raw);
-  }
-
   void WriteFunctionId(RawFunction* func, bool owner_is_class);
 
   RawFunction* IsSerializableClosure(RawClosure* closure);
@@ -1032,12 +939,9 @@
   ObjectStore* object_store_;  // Object store for common classes.
   ClassTable* class_table_;  // Class table for the class index to class lookup.
   ForwardList* forward_list_;
-  InstructionsWriter* instructions_writer_;
   Exceptions::ExceptionType exception_type_;  // Exception type.
   const char* exception_msg_;  // Message associated with exception.
-  bool unmarked_objects_;  // True if marked objects have been unmarked.
   bool can_send_any_object_;  // True if any Dart instance can be sent.
-  bool writing_vm_isolate_;
 
   friend class RawArray;
   friend class RawClass;
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index c5862e4..bcd69f7 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -833,7 +833,6 @@
                        alloc,
                        kInitialSize,
                        &forward_list_,
-                       NULL, /* test_writer */
                        true /* can_send_any_object */),
         forward_list_(thread(), kMaxPredefinedObjectIds) {
     ASSERT(buffer != NULL);
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index 827407d..d9bd0fa 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -489,6 +489,7 @@
 InlinedFunctionsIterator::InlinedFunctionsIterator(const Code& code, uword pc)
   : index_(0),
     num_materializations_(0),
+    dest_frame_size_(0),
     code_(Code::Handle(code.raw())),
     deopt_info_(TypedData::Handle()),
     function_(Function::Handle()),
@@ -512,6 +513,7 @@
     ASSERT(!deopt_table.IsNull());
     DeoptInfo::Unpack(deopt_table, deopt_info_, &deopt_instructions_);
     num_materializations_ = DeoptInfo::NumMaterializations(deopt_instructions_);
+    dest_frame_size_ = DeoptInfo::FrameSize(deopt_info_);
     object_table_ = code_.GetObjectPool();
     Advance();
   }
@@ -550,7 +552,14 @@
        index++) {
     DeoptInstr* deopt_instr = deopt_instructions_[index];
     if (deopt_instr->kind() == DeoptInstr::kCallerFp) {
+#if defined(TARGET_ARCH_DBC)
+      // Stack on DBC is growing upwards but we record deopt commands
+      // in the same order we record them on other architectures as if
+      // the stack was growing downwards.
+      return dest_frame_size_ - index;
+#else
       return (index - num_materializations_);
+#endif
     }
   }
   UNREACHABLE();
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index dac3e5f..268ca4a 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -336,6 +336,7 @@
 
   intptr_t index_;
   intptr_t num_materializations_;
+  intptr_t dest_frame_size_;
   Code& code_;
   TypedData& deopt_info_;
   Function& function_;
@@ -346,9 +347,11 @@
   DISALLOW_COPY_AND_ASSIGN(InlinedFunctionsIterator);
 };
 
+
 #if !defined(TARGET_ARCH_DBC)
-DART_FORCE_INLINE static uword LocalVarAddress(uword fp, intptr_t index) {
-  return fp + (index * kWordSize);
+DART_FORCE_INLINE static intptr_t LocalVarIndex(intptr_t fp_offset,
+                                                intptr_t var_index) {
+  return fp_offset + var_index;
 }
 
 
@@ -367,6 +370,12 @@
 static const uword kInterruptStackLimit = ~static_cast<uword>(0);
 #endif
 
+
+DART_FORCE_INLINE static uword LocalVarAddress(uword fp, intptr_t index) {
+  return fp + LocalVarIndex(0, index) * kWordSize;
+}
+
+
 }  // namespace dart
 
 #endif  // VM_STACK_FRAME_H_
diff --git a/runtime/vm/stack_frame_dbc.h b/runtime/vm/stack_frame_dbc.h
index a59a417..5d5ee78 100644
--- a/runtime/vm/stack_frame_dbc.h
+++ b/runtime/vm/stack_frame_dbc.h
@@ -10,7 +10,7 @@
 /* DBC Frame Layout
 
 IMPORTANT: On DBC stack is growing upwards which is different from all other
-architectures. This enables effecient addressing for locals via unsigned index.
+architectures. This enables efficient addressing for locals via unsigned index.
 
                |                    | <- TOS
 Callee frame   | ...                |
@@ -56,15 +56,17 @@
 static const int kFirstLocalSlotFromFp = -1;
 
 
-DART_FORCE_INLINE static uword LocalVarAddress(uword fp, intptr_t index) {
-  ASSERT(index != 0);
-  if (index > 0) {
-     return fp - index * kWordSize;
+DART_FORCE_INLINE static intptr_t LocalVarIndex(intptr_t fp_offset,
+                                                intptr_t var_index) {
+  ASSERT(var_index != 0);
+  if (var_index > 0) {
+    return fp_offset - var_index;
   } else {
-     return fp - (index + 1) * kWordSize;
+    return fp_offset - (var_index + 1);
   }
 }
 
+
 DART_FORCE_INLINE static uword ParamAddress(uword fp, intptr_t reverse_index) {
   return fp - (kDartFrameFixedSize + reverse_index) * kWordSize;
 }
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index a6992bf..53a06cb 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -183,20 +183,20 @@
         isolate->heap()->CollectAllGarbage();
       }
     }
+#ifndef PRODUCT
     if (FLAG_support_disassembler && FLAG_disassemble_stubs) {
       LogBlock lb;
       THR_Print("Code for allocation stub '%s': {\n", name);
-#ifndef PRODUCT
       DisassembleToStdout formatter;
       stub.Disassemble(&formatter);
-#endif
       THR_Print("}\n");
       const ObjectPool& object_pool = ObjectPool::Handle(stub.object_pool());
       object_pool.DebugPrint();
     }
+#endif  // !PRODUCT
   }
   return stub.raw();
-#endif
+#endif  // !DBC
   UNIMPLEMENTED();
   return Code::null();
 }
@@ -229,6 +229,7 @@
   GenerateStub(&assembler);
   const Code& code = Code::Handle(
       Code::FinalizeCode(name, &assembler, false /* optimized */));
+#ifndef PRODUCT
   if (FLAG_support_disassembler && FLAG_disassemble_stubs) {
     LogBlock lb;
     THR_Print("Code for stub '%s': {\n", name);
@@ -238,6 +239,7 @@
     const ObjectPool& object_pool = ObjectPool::Handle(code.object_pool());
     object_pool.DebugPrint();
   }
+#endif  // !PRODUCT
   return code.raw();
 }
 
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index cecec5d..d5103e6 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -54,8 +54,6 @@
   V(SmiAddInlineCache)                                                         \
   V(SmiSubInlineCache)                                                         \
   V(SmiEqualInlineCache)                                                       \
-  V(UnaryRangeCollectingInlineCache)                                           \
-  V(BinaryRangeCollectingInlineCache)                                          \
   V(OneArgOptimizedCheckInlineCache)                                           \
   V(TwoArgsOptimizedCheckInlineCache)                                          \
   V(ZeroArgsUnoptimizedStaticCall)                                             \
@@ -155,8 +153,6 @@
 
   static const intptr_t kNoInstantiator = 0;
 
-  static void EmitMegamorphicLookup(Assembler* assembler);
-
  private:
   friend class MegamorphicCacheTable;
 
@@ -172,11 +168,6 @@
   VM_STUB_CODE_LIST(STUB_CODE_ENTRY);
 #undef STUB_CODE_ENTRY
 
-  enum RangeCollectionMode {
-    kCollectRanges,
-    kIgnoreRanges
-  };
-
   // Generate the stub and finalize the generated code into the stub
   // code executable area.
   static RawCode* Generate(const char* name,
@@ -190,7 +181,6 @@
       intptr_t num_args,
       const RuntimeEntry& handle_ic_miss,
       Token::Kind kind,
-      RangeCollectionMode range_collection_mode,
       bool optimized = false);
   static void GenerateUsageCounterIncrement(Assembler* assembler,
                                             Register temp_reg);
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 9a7429b..370711b 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -1324,7 +1324,6 @@
     intptr_t num_args,
     const RuntimeEntry& handle_ic_miss,
     Token::Kind kind,
-    RangeCollectionMode range_collection_mode,
     bool optimized) {
   __ CheckCodePointer();
   ASSERT(num_args > 0);
@@ -1352,18 +1351,7 @@
     __ Bind(&done_stepping);
   }
 
-  __ Comment("Range feedback collection");
   Label not_smi_or_overflow;
-  if (range_collection_mode == kCollectRanges) {
-    ASSERT((num_args == 1) || (num_args == 2));
-    if (num_args == 2) {
-      __ ldr(R0, Address(SP, 1 * kWordSize));
-      __ UpdateRangeFeedback(R0, 0, R9, R1, R4, &not_smi_or_overflow);
-    }
-
-    __ ldr(R0, Address(SP, 0 * kWordSize));
-    __ UpdateRangeFeedback(R0, num_args - 1, R9, R1, R4, &not_smi_or_overflow);
-  }
   if (kind != Token::kILLEGAL) {
     EmitFastSmiOp(assembler, kind, num_args, &not_smi_or_overflow);
   }
@@ -1478,31 +1466,8 @@
   __ Bind(&call_target_function);
   // R0: target function.
   __ ldr(R2, FieldAddress(R0, Function::entry_point_offset()));
-  if (range_collection_mode == kCollectRanges) {
-    __ ldr(R1, Address(SP, 0 * kWordSize));
-    if (num_args == 2) {
-      __ ldr(R3, Address(SP, 1 * kWordSize));
-    }
-    __ EnterStubFrame();
-    if (num_args == 2) {
-      __ PushList((1 << R1) | (1 << R3) | (1 << R9));
-    } else {
-      __ PushList((1 << R1) | (1 << R9));
-    }
-    __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
-    __ blx(R2);
-
-    Label done;
-    __ ldr(R9, Address(FP, kFirstLocalSlotFromFp * kWordSize));
-    __ UpdateRangeFeedback(R0, 2, R9, R1, R4, &done);
-    __ Bind(&done);
-    __ RestoreCodePointer();
-    __ LeaveStubFrame();
-    __ Ret();
-  } else {
-    __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
-    __ bx(R2);
-  }
+  __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
+  __ bx(R2);
 
   if (FLAG_support_debugger && !optimized) {
     __ Bind(&stepping);
@@ -1532,8 +1497,7 @@
   GenerateNArgsCheckInlineCacheStub(assembler,
       1,
       kInlineCacheMissHandlerOneArgRuntimeEntry,
-      Token::kILLEGAL,
-      kIgnoreRanges);
+      Token::kILLEGAL);
 }
 
 
@@ -1542,8 +1506,7 @@
   GenerateNArgsCheckInlineCacheStub(assembler,
       2,
       kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-      Token::kILLEGAL,
-      kIgnoreRanges);
+      Token::kILLEGAL);
 }
 
 
@@ -1552,44 +1515,21 @@
   GenerateNArgsCheckInlineCacheStub(assembler,
       2,
       kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-      Token::kADD,
-      kCollectRanges);
+      Token::kADD);
 }
 
 
 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R8);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
-      kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB,
-      kCollectRanges);
+      kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB);
 }
 
 
 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R8);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
-      kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ,
-      kIgnoreRanges);
-}
-
-
-void StubCode::GenerateUnaryRangeCollectingInlineCacheStub(
-    Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, R8);
-  GenerateNArgsCheckInlineCacheStub(assembler, 1,
-      kInlineCacheMissHandlerOneArgRuntimeEntry,
-      Token::kILLEGAL,
-      kCollectRanges);
-}
-
-
-void StubCode::GenerateBinaryRangeCollectingInlineCacheStub(
-    Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, R8);
-  GenerateNArgsCheckInlineCacheStub(assembler, 2,
-      kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-      Token::kILLEGAL,
-      kCollectRanges);
+      kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ);
 }
 
 
@@ -1598,7 +1538,7 @@
   GenerateOptimizedUsageCounterIncrement(assembler);
   GenerateNArgsCheckInlineCacheStub(assembler, 1,
       kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
-      kIgnoreRanges, true /* optimized */);
+      true /* optimized */);
 }
 
 
@@ -1607,7 +1547,7 @@
   GenerateOptimizedUsageCounterIncrement(assembler);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
       kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
-      kIgnoreRanges, true /* optimized */);
+      true /* optimized */);
 }
 
 
@@ -1681,16 +1621,14 @@
 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R8);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
-      kIgnoreRanges);
+      assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
 }
 
 
 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R8);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
-      kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
-      kIgnoreRanges);
+      kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
 }
 
 
@@ -2048,48 +1986,6 @@
 }
 
 
-void StubCode::EmitMegamorphicLookup(Assembler* assembler) {
-  __ LoadTaggedClassIdMayBeSmi(R0, R0);
-  // R0: receiver cid as Smi.
-  __ ldr(R4, FieldAddress(R9, MegamorphicCache::arguments_descriptor_offset()));
-  __ ldr(R2, FieldAddress(R9, MegamorphicCache::buckets_offset()));
-  __ ldr(R1, FieldAddress(R9, MegamorphicCache::mask_offset()));
-  // R2: cache buckets array.
-  // R1: mask.
-  __ LoadImmediate(IP, MegamorphicCache::kSpreadFactor);
-  __ mul(R3, R0, IP);
-  // R3: probe.
-
-  Label loop, update, load_target_function;
-  __ b(&loop);
-
-  __ Bind(&update);
-  __ add(R3, R3, Operand(Smi::RawValue(1)));
-  __ Bind(&loop);
-  __ and_(R3, R3, Operand(R1));
-  const intptr_t base = Array::data_offset();
-  // R3 is smi tagged, but table entries are two words, so LSL 2.
-  __ add(IP, R2, Operand(R3, LSL, 2));
-  __ ldr(R6, FieldAddress(IP, base));
-
-  ASSERT(kIllegalCid == 0);
-  __ tst(R6, Operand(R6));
-  __ b(&load_target_function, EQ);
-  __ cmp(R6, Operand(R0));
-  __ b(&update, NE);
-
-  __ Bind(&load_target_function);
-  // Call the target found in the cache.  For a class id match, this is a
-  // proper target for the given name and arguments descriptor.  If the
-  // illegal class id was found, the target is a cache miss handler that can
-  // be invoked as a normal Dart function.
-  __ add(IP, R2, Operand(R3, LSL, 2));
-  __ ldr(R0, FieldAddress(IP, base + kWordSize));
-  __ ldr(R1, FieldAddress(R0, Function::entry_point_offset()));
-  __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
-}
-
-
 // Called from megamorphic calls.
 //  R0: receiver
 //  R9: MegamorphicCache (preserved)
@@ -2098,8 +1994,51 @@
 //  CODE_REG: target Code
 //  R4: arguments descriptor
 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) {
-  EmitMegamorphicLookup(assembler);
+  __ LoadTaggedClassIdMayBeSmi(R0, R0);
+  // R0: receiver cid as Smi.
+  __ ldr(R2, FieldAddress(R9, MegamorphicCache::buckets_offset()));
+  __ ldr(R1, FieldAddress(R9, MegamorphicCache::mask_offset()));
+  // R2: cache buckets array.
+  // R1: mask.
+
+  // Compute the table index.
+  ASSERT(MegamorphicCache::kSpreadFactor == 7);
+  // Use reverse substract to multiply with 7 == 8 - 1.
+  __ rsb(R3, R0, Operand(R0, LSL, 3));
+  // R3: probe.
+  Label loop;
+  __ Bind(&loop);
+  __ and_(R3, R3, Operand(R1));
+
+  const intptr_t base = Array::data_offset();
+  // R3 is smi tagged, but table entries are two words, so LSL 2.
+  Label probe_failed;
+  __ add(IP, R2, Operand(R3, LSL, 2));
+  __ ldr(R6, FieldAddress(IP, base));
+  __ cmp(R6, Operand(R0));
+  __ b(&probe_failed, NE);
+
+  Label load_target;
+  __ Bind(&load_target);
+  // Call the target found in the cache.  For a class id match, this is a
+  // proper target for the given name and arguments descriptor.  If the
+  // illegal class id was found, the target is a cache miss handler that can
+  // be invoked as a normal Dart function.
+  __ ldr(R0, FieldAddress(IP, base + kWordSize));
+  __ ldr(R4, FieldAddress(R9, MegamorphicCache::arguments_descriptor_offset()));
+  __ ldr(R1, FieldAddress(R0, Function::entry_point_offset()));
+  __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
   __ Ret();
+
+  // Probe failed, check if it is a miss.
+  __ Bind(&probe_failed);
+  ASSERT(kIllegalCid == 0);
+  __ tst(R6, Operand(R6));
+  __ b(&load_target, EQ);  // branch if miss.
+
+  // Try next extry in the table.
+  __ AddImmediate(R3, Smi::RawValue(1));
+  __ b(&loop);
 }
 
 
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index 04dd0f4..9034730 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -1293,8 +1293,7 @@
 static void EmitFastSmiOp(Assembler* assembler,
                           Token::Kind kind,
                           intptr_t num_args,
-                          Label* not_smi_or_overflow,
-                          bool should_update_result_range) {
+                          Label* not_smi_or_overflow) {
   __ Comment("Fast Smi op");
   __ ldr(R0, Address(SP, + 0 * kWordSize));  // Right.
   __ ldr(R1, Address(SP, + 1 * kWordSize));  // Left.
@@ -1322,12 +1321,6 @@
     default: UNIMPLEMENTED();
   }
 
-  if (should_update_result_range) {
-    Label done;
-    __ UpdateRangeFeedback(R0, 2, R5, R1, R6, &done);
-    __ Bind(&done);
-  }
-
   // R5: IC data object (preserved).
   __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset());
   // R6: ic_data_array with check entries: classes and target functions.
@@ -1376,7 +1369,6 @@
     intptr_t num_args,
     const RuntimeEntry& handle_ic_miss,
     Token::Kind kind,
-    RangeCollectionMode range_collection_mode,
     bool optimized) {
   ASSERT(num_args > 0);
 #if defined(DEBUG)
@@ -1405,24 +1397,12 @@
     __ Bind(&done_stepping);
   }
 
-  __ Comment("Range feedback collection");
   Label not_smi_or_overflow;
-  if (range_collection_mode == kCollectRanges) {
-    ASSERT((num_args == 1) || (num_args == 2));
-    if (num_args == 2) {
-      __ ldr(R0, Address(SP, 1 * kWordSize));
-      __ UpdateRangeFeedback(R0, 0, R5, R1, R4, &not_smi_or_overflow);
-    }
-
-    __ ldr(R0, Address(SP, 0 * kWordSize));
-    __ UpdateRangeFeedback(R0, num_args - 1, R5, R1, R4, &not_smi_or_overflow);
-  }
   if (kind != Token::kILLEGAL) {
     EmitFastSmiOp(assembler,
                   kind,
                   num_args,
-                  &not_smi_or_overflow,
-                  (range_collection_mode == kCollectRanges));
+                  &not_smi_or_overflow);
   }
   __ Bind(&not_smi_or_overflow);
 
@@ -1546,32 +1526,9 @@
   __ Comment("Call target");
   __ Bind(&call_target_function);
   // R0: target function.
-  if (range_collection_mode == kCollectRanges) {
-    __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset());
-    __ ldr(R1, Address(SP, 0 * kWordSize));
-    if (num_args == 2) {
-      __ ldr(R3, Address(SP, 1 * kWordSize));
-    }
-    __ EnterStubFrame();
-    __ Push(R5);
-    if (num_args == 2) {
-      __ Push(R3);
-    }
-    __ Push(R1);
-    __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset());
-    __ blr(R2);
-
-    Label done;
-    __ ldr(R5, Address(FP, kFirstLocalSlotFromFp * kWordSize));
-    __ UpdateRangeFeedback(R0, 2, R5, R1, R4, &done);
-    __ Bind(&done);
-    __ LeaveStubFrame();
-    __ ret();
-  } else {
-    __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset());
-    __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset());
-    __ br(R2);
-  }
+  __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset());
+  __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset());
+  __ br(R2);
 
   if (FLAG_support_debugger && !optimized) {
     __ Bind(&stepping);
@@ -1599,60 +1556,35 @@
 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R6);
   GenerateNArgsCheckInlineCacheStub(assembler, 1,
-      kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
-      kIgnoreRanges);
+      kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
 }
 
 
 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R6);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
-      kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
-      kIgnoreRanges);
+      kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
 }
 
 
 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R6);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
-      kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD,
-      kCollectRanges);
+      kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD);
 }
 
 
 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R6);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
-      kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB,
-      kCollectRanges);
+      kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB);
 }
 
 
 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R6);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
-      kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ,
-      kIgnoreRanges);
-}
-
-
-void StubCode::GenerateUnaryRangeCollectingInlineCacheStub(
-    Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, R6);
-  GenerateNArgsCheckInlineCacheStub(assembler, 1,
-      kInlineCacheMissHandlerOneArgRuntimeEntry,
-      Token::kILLEGAL,
-      kCollectRanges);
-}
-
-
-void StubCode::GenerateBinaryRangeCollectingInlineCacheStub(
-    Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, R6);
-  GenerateNArgsCheckInlineCacheStub(assembler, 2,
-      kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-      Token::kILLEGAL,
-      kCollectRanges);
+      kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ);
 }
 
 
@@ -1661,7 +1593,7 @@
   GenerateOptimizedUsageCounterIncrement(assembler);
   GenerateNArgsCheckInlineCacheStub(assembler, 1,
       kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
-      kIgnoreRanges, true /* optimized */);
+      true /* optimized */);
 }
 
 
@@ -1670,7 +1602,7 @@
   GenerateOptimizedUsageCounterIncrement(assembler);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
       kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
-      kIgnoreRanges, true /* optimized */);
+      true /* optimized */);
 }
 
 
@@ -1744,16 +1676,14 @@
 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R6);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
-      kIgnoreRanges);
+      assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
 }
 
 
 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R6);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
-      kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
-      kIgnoreRanges);
+      kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
 }
 
 
@@ -2098,48 +2028,6 @@
 }
 
 
-void StubCode::EmitMegamorphicLookup(Assembler* assembler) {
-  __ LoadTaggedClassIdMayBeSmi(R0, R0);
-  // R0: class ID of the receiver (smi).
-  __ ldr(R4, FieldAddress(R5, MegamorphicCache::arguments_descriptor_offset()));
-  __ ldr(R2, FieldAddress(R5, MegamorphicCache::buckets_offset()));
-  __ ldr(R1, FieldAddress(R5, MegamorphicCache::mask_offset()));
-  // R2: cache buckets array.
-  // R1: mask.
-  __ LoadImmediate(TMP, MegamorphicCache::kSpreadFactor);
-  __ mul(R3, R0, TMP);
-  // R3: probe.
-
-  Label loop, update, load_target_function;
-  __ b(&loop);
-
-  __ Bind(&update);
-  __ add(R3, R3, Operand(Smi::RawValue(1)));
-  __ Bind(&loop);
-  __ and_(R3, R3, Operand(R1));
-  const intptr_t base = Array::data_offset();
-  // R3 is smi tagged, but table entries are 16 bytes, so LSL 3.
-  __ add(TMP, R2, Operand(R3, LSL, 3));
-  __ ldr(R6, FieldAddress(TMP, base));
-
-  ASSERT(kIllegalCid == 0);
-  __ tst(R6, Operand(R6));
-  __ b(&load_target_function, EQ);
-  __ CompareRegisters(R6, R0);
-  __ b(&update, NE);
-
-  __ Bind(&load_target_function);
-  // Call the target found in the cache.  For a class id match, this is a
-  // proper target for the given name and arguments descriptor.  If the
-  // illegal class id was found, the target is a cache miss handler that can
-  // be invoked as a normal Dart function.
-  __ add(TMP, R2, Operand(R3, LSL, 3));
-  __ ldr(R0, FieldAddress(TMP, base + kWordSize));
-  __ ldr(R1, FieldAddress(R0, Function::entry_point_offset()));
-  __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
-}
-
-
 // Called from megamorphic calls.
 //  R0: receiver
 //  R5: MegamorphicCache (preserved)
@@ -2148,8 +2036,69 @@
 //  CODE_REG: target Code
 //  R4: arguments descriptor
 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) {
-  EmitMegamorphicLookup(assembler);
+  // Jump if receiver is a smi.
+  Label smi_case;
+  __ TestImmediate(R0, kSmiTagMask);
+  __ b(&smi_case, EQ);
+
+  // Loads the cid of the object.
+  __ LoadClassId(R0, R0);
+
+  Label cid_loaded;
+  __ Bind(&cid_loaded);
+  __ ldr(R2, FieldAddress(R5, MegamorphicCache::buckets_offset()));
+  __ ldr(R1, FieldAddress(R5, MegamorphicCache::mask_offset()));
+  // R2: cache buckets array.
+  // R1: mask.
+
+  // Make the cid into a smi.
+  __ SmiTag(R0);
+  // R0: class ID of the receiver (smi).
+
+  // Compute the table index.
+  ASSERT(MegamorphicCache::kSpreadFactor == 7);
+  // Use lsl and sub to multiply with 7 == 8 - 1.
+  __ LslImmediate(R3, R0, 3);
+  __ sub(R3, R3, Operand(R0));
+  // R3: probe.
+  Label loop;
+  __ Bind(&loop);
+  __ and_(R3, R3, Operand(R1));
+
+  const intptr_t base = Array::data_offset();
+  // R3 is smi tagged, but table entries are 16 bytes, so LSL 3.
+  __ add(TMP, R2, Operand(R3, LSL, 3));
+  __ ldr(R6, FieldAddress(TMP, base));
+  Label probe_failed;
+  __ CompareRegisters(R6, R0);
+  __ b(&probe_failed, NE);
+
+  Label load_target;
+  __ Bind(&load_target);
+  // Call the target found in the cache.  For a class id match, this is a
+  // proper target for the given name and arguments descriptor.  If the
+  // illegal class id was found, the target is a cache miss handler that can
+  // be invoked as a normal Dart function.
+  __ ldr(R0, FieldAddress(TMP, base + kWordSize));
+  __ ldr(R4, FieldAddress(R5, MegamorphicCache::arguments_descriptor_offset()));
+  __ ldr(R1, FieldAddress(R0, Function::entry_point_offset()));
+  __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
   __ ret();
+
+  // Probe failed, check if it is a miss.
+  __ Bind(&probe_failed);
+  ASSERT(kIllegalCid == 0);
+  __ tst(R6, Operand(R6));
+  __ b(&load_target, EQ);  // branch if miss.
+
+  // Try next extry in the table.
+  __ AddImmediate(R3, R3, Smi::RawValue(1));
+  __ b(&loop);
+
+  // Load cid for the Smi case.
+  __ Bind(&smi_case);
+  __ LoadImmediate(R0, kSmiCid);
+  __ b(&cid_loaded);
 }
 
 
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index 139a4a2..71cf786 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -1278,7 +1278,6 @@
     intptr_t num_args,
     const RuntimeEntry& handle_ic_miss,
     Token::Kind kind,
-    RangeCollectionMode range_collection_mode,
     bool optimized) {
   ASSERT(num_args > 0);
 #if defined(DEBUG)
@@ -1303,19 +1302,7 @@
     __ j(NOT_EQUAL, &stepping);
     __ Bind(&done_stepping);
   }
-  __ Comment("Range feedback collection");
   Label not_smi_or_overflow;
-  if (range_collection_mode == kCollectRanges) {
-    ASSERT((num_args == 1) || (num_args == 2));
-    if (num_args == 2) {
-      __ movl(EAX, Address(ESP, + 2 * kWordSize));
-      __ UpdateRangeFeedback(EAX, 0, ECX, EBX, EDI, EDX, &not_smi_or_overflow);
-    }
-
-    __ movl(EAX, Address(ESP, + 1 * kWordSize));
-    __ UpdateRangeFeedback(EAX, (num_args - 1), ECX, EBX, EDI, EDX,
-                           &not_smi_or_overflow);
-  }
   if (kind != Token::kILLEGAL) {
     EmitFastSmiOp(assembler, kind, num_args, &not_smi_or_overflow);
   }
@@ -1434,27 +1421,7 @@
   __ Comment("Call target");
   // EAX: Target function.
   __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset()));
-  if (range_collection_mode == kCollectRanges) {
-    __ EnterStubFrame();
-    __ pushl(ECX);
-    const intptr_t arg_offset_words = num_args +
-                                      Assembler::kEnterStubFramePushedWords +
-                                      1;  // ECX
-    for (intptr_t i = 0; i < num_args; i++) {
-      __ movl(EDI, Address(ESP, arg_offset_words * kWordSize));
-      __ pushl(EDI);
-    }
-    __ call(EBX);
-
-    __ movl(ECX, Address(EBP, kFirstLocalSlotFromFp * kWordSize));
-    Label done;
-    __ UpdateRangeFeedback(EAX, 2, ECX, EBX, EDI, EDX, &done);
-    __ Bind(&done);
-    __ LeaveFrame();
-    __ ret();
-  } else {
-    __ jmp(EBX);
-  }
+  __ jmp(EBX);
 
   if (FLAG_support_debugger && !optimized) {
     __ Bind(&stepping);
@@ -1482,8 +1449,7 @@
   GenerateUsageCounterIncrement(assembler, EBX);
   GenerateNArgsCheckInlineCacheStub(assembler, 1,
       kInlineCacheMissHandlerOneArgRuntimeEntry,
-      Token::kILLEGAL,
-      kIgnoreRanges);
+      Token::kILLEGAL);
 }
 
 
@@ -1491,8 +1457,7 @@
   GenerateUsageCounterIncrement(assembler, EBX);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
       kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-      Token::kILLEGAL,
-      kIgnoreRanges);
+      Token::kILLEGAL);
 }
 
 
@@ -1500,8 +1465,7 @@
   GenerateUsageCounterIncrement(assembler, EBX);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
       kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-      Token::kADD,
-      kCollectRanges);
+      Token::kADD);
 }
 
 
@@ -1509,8 +1473,7 @@
   GenerateUsageCounterIncrement(assembler, EBX);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
       kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-      Token::kSUB,
-      kCollectRanges);
+      Token::kSUB);
 }
 
 
@@ -1518,28 +1481,7 @@
   GenerateUsageCounterIncrement(assembler, EBX);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
       kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-      Token::kEQ,
-      kIgnoreRanges);
-}
-
-
-void StubCode::GenerateUnaryRangeCollectingInlineCacheStub(
-    Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, EBX);
-  GenerateNArgsCheckInlineCacheStub(assembler, 1,
-      kInlineCacheMissHandlerOneArgRuntimeEntry,
-      Token::kILLEGAL,
-      kCollectRanges);
-}
-
-
-void StubCode::GenerateBinaryRangeCollectingInlineCacheStub(
-    Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, EBX);
-  GenerateNArgsCheckInlineCacheStub(assembler, 2,
-      kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-      Token::kILLEGAL,
-      kCollectRanges);
+      Token::kEQ);
 }
 
 
@@ -1560,7 +1502,6 @@
   GenerateNArgsCheckInlineCacheStub(assembler, 1,
       kInlineCacheMissHandlerOneArgRuntimeEntry,
       Token::kILLEGAL,
-      kIgnoreRanges,
       true /* optimized */);
 }
 
@@ -1571,7 +1512,6 @@
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
      kInlineCacheMissHandlerTwoArgsRuntimeEntry,
      Token::kILLEGAL,
-     kIgnoreRanges,
      true /* optimized */);
 }
 
@@ -1645,8 +1585,7 @@
   GenerateUsageCounterIncrement(assembler, EBX);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry,
-      Token::kILLEGAL,
-      kIgnoreRanges);
+      Token::kILLEGAL);
 }
 
 
@@ -1654,8 +1593,7 @@
   GenerateUsageCounterIncrement(assembler, EBX);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
       kStaticCallMissHandlerTwoArgsRuntimeEntry,
-      Token::kILLEGAL,
-      kIgnoreRanges);
+      Token::kILLEGAL);
 }
 
 
@@ -2021,48 +1959,6 @@
 }
 
 
-void StubCode::EmitMegamorphicLookup(Assembler* assembler) {
-  __ LoadTaggedClassIdMayBeSmi(EAX, EBX);
-  // EAX: class ID of the receiver (smi).
-  __ movl(EDI, FieldAddress(ECX, MegamorphicCache::buckets_offset()));
-  __ movl(EBX, FieldAddress(ECX, MegamorphicCache::mask_offset()));
-  // EDI: cache buckets array.
-  // EBX: mask.
-  __ pushl(ECX);  // Spill MegamorphicCache.
-  __ movl(ECX, EAX);
-  __ imull(ECX, Immediate(MegamorphicCache::kSpreadFactor));
-  // ECX: probe.
-
-  Label loop, update, load_target_function;
-  __ jmp(&loop);
-
-  __ Bind(&update);
-  __ addl(ECX, Immediate(Smi::RawValue(1)));
-  __ Bind(&loop);
-  __ andl(ECX, EBX);
-  const intptr_t base = Array::data_offset();
-  // ECX is smi tagged, but table entries are two words, so TIMES_4.
-  __ movl(EDX, FieldAddress(EDI, ECX, TIMES_4, base));
-
-  ASSERT(kIllegalCid == 0);
-  __ testl(EDX, EDX);
-  __ j(ZERO, &load_target_function, Assembler::kNearJump);
-  __ cmpl(EDX, EAX);
-  __ j(NOT_EQUAL, &update, Assembler::kNearJump);
-
-  __ Bind(&load_target_function);
-  // Call the target found in the cache.  For a class id match, this is a
-  // proper target for the given name and arguments descriptor.  If the
-  // illegal class id was found, the target is a cache miss handler that can
-  // be invoked as a normal Dart function.
-  __ movl(EAX, FieldAddress(EDI, ECX, TIMES_4, base + kWordSize));
-  __ popl(ECX);  // Restore MegamorphicCache.
-  __ movl(EDX,
-          FieldAddress(ECX, MegamorphicCache::arguments_descriptor_offset()));
-  __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset()));
-}
-
-
 // Called from megamorphic calls.
 //  EBX: receiver
 //  ECX: MegamorphicCache (preserved)
@@ -2070,10 +1966,68 @@
 //  EBX: target entry point
 //  EDX: argument descriptor
 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) {
-  EmitMegamorphicLookup(assembler);
-  __ ret();
-}
+  // Jump if receiver is a smi.
+  Label smi_case;
+  // Check if object (in tmp) is a Smi.
+  __ testl(EBX, Immediate(kSmiTagMask));
+  // Jump out of line for smi case.
+  __ j(ZERO, &smi_case, Assembler::kNearJump);
 
+  // Loads the cid of the instance.
+  __ LoadClassId(EAX, EBX);
+
+  Label cid_loaded;
+  __ Bind(&cid_loaded);
+  __ movl(EBX, FieldAddress(ECX, MegamorphicCache::mask_offset()));
+  __ movl(EDI, FieldAddress(ECX, MegamorphicCache::buckets_offset()));
+  // EDI: cache buckets array.
+  // EBX: mask.
+
+  // Tag cid as a smi.
+  __ addl(EAX, EAX);
+
+  // Compute the table index.
+  ASSERT(MegamorphicCache::kSpreadFactor == 7);
+  // Use leal and subl multiply with 7 == 8 - 1.
+  __ leal(EDX, Address(EAX, TIMES_8, 0));
+  __ subl(EDX, EAX);
+
+  Label loop;
+  __ Bind(&loop);
+  __ andl(EDX, EBX);
+
+  const intptr_t base = Array::data_offset();
+  Label probe_failed;
+  // EDX is smi tagged, but table entries are two words, so TIMES_4.
+  __ cmpl(EAX, FieldAddress(EDI, EDX, TIMES_4, base));
+  __ j(NOT_EQUAL, &probe_failed, Assembler::kNearJump);
+
+  Label load_target;
+  __ Bind(&load_target);
+  // Call the target found in the cache.  For a class id match, this is a
+  // proper target for the given name and arguments descriptor.  If the
+  // illegal class id was found, the target is a cache miss handler that can
+  // be invoked as a normal Dart function.
+  __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, base + kWordSize));
+  __ movl(EDX,
+          FieldAddress(ECX, MegamorphicCache::arguments_descriptor_offset()));
+  __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset()));
+  __ ret();
+
+  __ Bind(&probe_failed);
+  // Probe failed, check if it is a miss.
+  __ cmpl(FieldAddress(EDI, EDX, TIMES_4, base), Immediate(kIllegalCid));
+  __ j(ZERO, &load_target, Assembler::kNearJump);
+
+  // Try next extry in the table.
+  __ AddImmediate(EDX, Immediate(Smi::RawValue(1)));
+  __ jmp(&loop);
+
+  // Load cid for the Smi case.
+  __ Bind(&smi_case);
+  __ movl(EAX, Immediate(kSmiCid));
+  __ jmp(&cid_loaded);
+}
 
 // Called from switchable IC calls.
 //  EBX: receiver
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index ef36894..f40dd22 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -1403,7 +1403,6 @@
     intptr_t num_args,
     const RuntimeEntry& handle_ic_miss,
     Token::Kind kind,
-    RangeCollectionMode range_collection_mode,
     bool optimized) {
   __ Comment("NArgsCheckInlineCacheStub");
   ASSERT(num_args > 0);
@@ -1430,18 +1429,7 @@
     __ Bind(&done_stepping);
   }
 
-  __ Comment("Range feedback collection");
   Label not_smi_or_overflow;
-  if (range_collection_mode == kCollectRanges) {
-    ASSERT((num_args == 1) || (num_args == 2));
-    if (num_args == 2) {
-      __ lw(T0, Address(SP, 1 * kWordSize));
-      __ UpdateRangeFeedback(T0, 0, S5, T1, &not_smi_or_overflow);
-    }
-
-    __ lw(T0, Address(SP, 0 * kWordSize));
-    __ UpdateRangeFeedback(T0, num_args - 1, S5, T1, &not_smi_or_overflow);
-  }
   if (kind != Token::kILLEGAL) {
     EmitFastSmiOp(assembler, kind, num_args, &not_smi_or_overflow);
   }
@@ -1589,35 +1577,8 @@
   __ mov(T0, T3);
   Label is_compiled;
   __ lw(T4, FieldAddress(T0, Function::entry_point_offset()));
-  if (range_collection_mode == kCollectRanges) {
-    const intptr_t frame_size = num_args + 2;
-    __ lw(T3, Address(SP, 0 * kWordSize));
-    if (num_args == 2) {
-      __ lw(T1, Address(SP, 1 * kWordSize));
-    }
-    __ EnterStubFrame();
-    __ addiu(SP, SP, Immediate(- frame_size * kWordSize));
-    __ sw(RA, Address(SP, (frame_size - 1) * kWordSize));  // Return address.
-    __ sw(S5, Address(SP, (frame_size - 2) * kWordSize));  // Preserve IC data.
-    __ sw(T3, Address(SP, 0 * kWordSize));
-    if (num_args == 2) {
-      __ sw(T1, Address(SP, 1 * kWordSize));
-    }
-    __ lw(CODE_REG, FieldAddress(T0, Function::code_offset()));
-    __ jalr(T4);
-    __ lw(S5, Address(SP, (frame_size - 2) * kWordSize));
-    __ lw(RA, Address(SP, (frame_size - 1) * kWordSize));
-    Label done;
-    __ UpdateRangeFeedback(V0, 2, S5, T1, &done);
-    __ Bind(&done);
-    __ addiu(SP, SP, Immediate(frame_size * kWordSize));
-    __ RestoreCodePointer();
-    __ LeaveStubFrame();
-    __ Ret();
-  } else {
-    __ lw(CODE_REG, FieldAddress(T0, Function::code_offset()));
-    __ jr(T4);
-  }
+  __ lw(CODE_REG, FieldAddress(T0, Function::code_offset()));
+  __ jr(T4);
 
   // Call single step callback in debugger.
   if (FLAG_support_debugger && !optimized) {
@@ -1650,60 +1611,35 @@
 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, T0);
   GenerateNArgsCheckInlineCacheStub(assembler, 1,
-      kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
-      kIgnoreRanges);
+      kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
 }
 
 
 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, T0);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
-      kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
-      kIgnoreRanges);
+      kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
 }
 
 
 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, T0);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
-      kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD,
-      kCollectRanges);
+      kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD);
 }
 
 
 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, T0);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
-      kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB,
-      kCollectRanges);
+      kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB);
 }
 
 
 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, T0);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
-      kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ,
-      kIgnoreRanges);
-}
-
-
-void StubCode::GenerateUnaryRangeCollectingInlineCacheStub(
-    Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, T0);
-  GenerateNArgsCheckInlineCacheStub(assembler, 1,
-      kInlineCacheMissHandlerOneArgRuntimeEntry,
-      Token::kILLEGAL,
-      kCollectRanges);
-}
-
-
-void StubCode::GenerateBinaryRangeCollectingInlineCacheStub(
-    Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, T0);
-  GenerateNArgsCheckInlineCacheStub(assembler, 2,
-      kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-      Token::kILLEGAL,
-      kCollectRanges);
+      kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ);
 }
 
 
@@ -1712,7 +1648,7 @@
   GenerateOptimizedUsageCounterIncrement(assembler);
   GenerateNArgsCheckInlineCacheStub(assembler, 1,
       kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
-      kIgnoreRanges, true /* optimized */);
+      true /* optimized */);
 }
 
 
@@ -1721,7 +1657,7 @@
   GenerateOptimizedUsageCounterIncrement(assembler);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
       kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
-      kIgnoreRanges, true /* optimized */);
+      true /* optimized */);
 }
 
 
@@ -1801,16 +1737,14 @@
 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, T0);
   GenerateNArgsCheckInlineCacheStub(
-      assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
-      kIgnoreRanges);
+      assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
 }
 
 
 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, T0);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
-      kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL,
-      kIgnoreRanges);
+      kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
 }
 
 
@@ -2212,7 +2146,14 @@
 }
 
 
-void StubCode::EmitMegamorphicLookup(Assembler* assembler) {
+// Called from megamorphic calls.
+//  T0: receiver
+//  S5: MegamorphicCache (preserved)
+// Result:
+//  T1: target entry point
+//  CODE_REG: target Code
+//  S4: arguments descriptor
+void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) {
   __ LoadTaggedClassIdMayBeSmi(T0, T0);
   // T0: class ID of the receiver (smi).
   __ lw(S4, FieldAddress(S5, MegamorphicCache::arguments_descriptor_offset()));
@@ -2253,18 +2194,6 @@
 
   __ lw(T1, FieldAddress(T0, Function::entry_point_offset()));
   __ lw(CODE_REG, FieldAddress(T0, Function::code_offset()));
-}
-
-
-// Called from megamorphic calls.
-//  T0: receiver
-//  S5: MegamorphicCache (preserved)
-// Result:
-//  T1: target entry point
-//  CODE_REG: target Code
-//  S4: arguments descriptor
-void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) {
-  EmitMegamorphicLookup(assembler);
   __ Ret();
 }
 
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 45edaf4..99393ac 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -783,7 +783,6 @@
   // Set up arguments for the Dart call.
   Label push_arguments;
   Label done_push_arguments;
-  __ testq(RBX, RBX);  // check if there are arguments.
   __ j(ZERO, &done_push_arguments, Assembler::kNearJump);
   __ movq(RAX, Immediate(0));
   __ Bind(&push_arguments);
@@ -1227,8 +1226,7 @@
 static void EmitFastSmiOp(Assembler* assembler,
                           Token::Kind kind,
                           intptr_t num_args,
-                          Label* not_smi_or_overflow,
-                          bool should_update_result_range) {
+                          Label* not_smi_or_overflow) {
   __ Comment("Fast Smi op");
   ASSERT(num_args == 2);
   __ movq(RCX, Address(RSP, + 1 * kWordSize));  // Right
@@ -1262,14 +1260,6 @@
     default: UNIMPLEMENTED();
   }
 
-
-  if (should_update_result_range) {
-    Label done;
-    __ movq(RSI, RAX);
-    __ UpdateRangeFeedback(RSI, 2, RBX, RCX, &done);
-    __ Bind(&done);
-  }
-
   // RBX: IC data object (preserved).
   __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset()));
   // R13: ic_data_array with check entries: classes and target functions.
@@ -1318,7 +1308,6 @@
     intptr_t num_args,
     const RuntimeEntry& handle_ic_miss,
     Token::Kind kind,
-    RangeCollectionMode range_collection_mode,
     bool optimized) {
   ASSERT(num_args > 0);
 #if defined(DEBUG)
@@ -1344,25 +1333,13 @@
     __ Bind(&done_stepping);
   }
 
-  __ Comment("Range feedback collection");
   Label not_smi_or_overflow;
-  if (range_collection_mode == kCollectRanges) {
-    ASSERT((num_args == 1) || (num_args == 2));
-    if (num_args == 2) {
-      __ movq(RAX, Address(RSP, + 2 * kWordSize));
-      __ UpdateRangeFeedback(RAX, 0, RBX, RCX, &not_smi_or_overflow);
-    }
-
-    __ movq(RAX, Address(RSP, + 1 * kWordSize));
-    __ UpdateRangeFeedback(RAX, (num_args - 1), RBX, RCX, &not_smi_or_overflow);
-  }
   if (kind != Token::kILLEGAL) {
     EmitFastSmiOp(
         assembler,
         kind,
         num_args,
-        &not_smi_or_overflow,
-        range_collection_mode == kCollectRanges);
+        &not_smi_or_overflow);
   }
   __ Bind(&not_smi_or_overflow);
 
@@ -1475,34 +1452,9 @@
   __ Bind(&call_target_function);
   // RAX: Target function.
   Label is_compiled;
-  if (range_collection_mode == kCollectRanges) {
-    __ movq(R13, FieldAddress(RAX, Function::code_offset()));
-    __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset()));
-    __ movq(R8, Address(RSP, + 1 * kWordSize));
-    if (num_args == 2) {
-      __ movq(R9, Address(RSP, + 2 * kWordSize));
-    }
-    __ EnterStubFrame();
-    __ pushq(RBX);
-    if (num_args == 2) {
-      __ pushq(R9);
-    }
-    __ pushq(R8);
-    __ movq(CODE_REG, R13);
-    __ call(RCX);
-
-    Label done;
-    __ movq(RDX, RAX);
-    __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize));
-    __ UpdateRangeFeedback(RDX, 2, RBX, RCX, &done);
-    __ Bind(&done);
-    __ LeaveStubFrame();
-    __ ret();
-  } else {
-    __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
-    __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset()));
-    __ jmp(RCX);
-  }
+  __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
+  __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset()));
+  __ jmp(RCX);
 
   if (FLAG_support_debugger && !optimized) {
     __ Bind(&stepping);
@@ -1531,8 +1483,7 @@
   GenerateUsageCounterIncrement(assembler, RCX);
   GenerateNArgsCheckInlineCacheStub(assembler, 1,
       kInlineCacheMissHandlerOneArgRuntimeEntry,
-      Token::kILLEGAL,
-      kIgnoreRanges);
+      Token::kILLEGAL);
 }
 
 
@@ -1540,8 +1491,7 @@
   GenerateUsageCounterIncrement(assembler, RCX);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
       kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-      Token::kILLEGAL,
-      kIgnoreRanges);
+      Token::kILLEGAL);
 }
 
 
@@ -1549,8 +1499,7 @@
   GenerateUsageCounterIncrement(assembler, RCX);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
       kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-      Token::kADD,
-      kCollectRanges);
+      Token::kADD);
 }
 
 
@@ -1558,8 +1507,7 @@
   GenerateUsageCounterIncrement(assembler, RCX);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
       kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-      Token::kSUB,
-      kCollectRanges);
+      Token::kSUB);
 }
 
 
@@ -1567,28 +1515,7 @@
   GenerateUsageCounterIncrement(assembler, RCX);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
       kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-      Token::kEQ,
-      kIgnoreRanges);
-}
-
-
-void StubCode::GenerateUnaryRangeCollectingInlineCacheStub(
-    Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, RCX);
-  GenerateNArgsCheckInlineCacheStub(assembler, 1,
-      kInlineCacheMissHandlerOneArgRuntimeEntry,
-      Token::kILLEGAL,
-      kCollectRanges);
-}
-
-
-void StubCode::GenerateBinaryRangeCollectingInlineCacheStub(
-    Assembler* assembler) {
-  GenerateUsageCounterIncrement(assembler, RCX);
-  GenerateNArgsCheckInlineCacheStub(assembler, 2,
-      kInlineCacheMissHandlerTwoArgsRuntimeEntry,
-      Token::kILLEGAL,
-      kCollectRanges);
+      Token::kEQ);
 }
 
 
@@ -1609,7 +1536,7 @@
   GenerateNArgsCheckInlineCacheStub(assembler, 1,
       kInlineCacheMissHandlerOneArgRuntimeEntry,
       Token::kILLEGAL,
-      kIgnoreRanges, true /* optimized */);
+      true /* optimized */);
 }
 
 
@@ -1619,7 +1546,7 @@
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
       kInlineCacheMissHandlerTwoArgsRuntimeEntry,
       Token::kILLEGAL,
-      kIgnoreRanges, true /* optimized */);
+      true /* optimized */);
 }
 
 
@@ -1702,8 +1629,7 @@
       assembler,
       1,
       kStaticCallMissHandlerOneArgRuntimeEntry,
-      Token::kILLEGAL,
-      kIgnoreRanges);
+      Token::kILLEGAL);
 }
 
 
@@ -1712,8 +1638,7 @@
   GenerateNArgsCheckInlineCacheStub(assembler,
       2,
       kStaticCallMissHandlerTwoArgsRuntimeEntry,
-      Token::kILLEGAL,
-      kIgnoreRanges);
+      Token::kILLEGAL);
 }
 
 
@@ -2083,47 +2008,6 @@
 }
 
 
-void StubCode::EmitMegamorphicLookup(Assembler* assembler) {
-  __ LoadTaggedClassIdMayBeSmi(RAX, RDI);
-  // RAX: class ID of the receiver (smi).
-  __ movq(R10,
-          FieldAddress(RBX, MegamorphicCache::arguments_descriptor_offset()));
-  __ movq(RDI, FieldAddress(RBX, MegamorphicCache::buckets_offset()));
-  __ movq(R9, FieldAddress(RBX, MegamorphicCache::mask_offset()));
-  // R10: arguments descriptor (result).
-  // RDI: cache buckets array.
-  // RBX: mask.
-  __ movq(RCX, RAX);
-  __ imulq(RCX, Immediate(MegamorphicCache::kSpreadFactor));
-
-  Label loop, update, load_target_function;
-  __ jmp(&loop);
-
-  __ Bind(&update);
-  __ AddImmediate(RCX, Immediate(Smi::RawValue(1)));
-  __ Bind(&loop);
-  __ andq(RCX, R9);
-  const intptr_t base = Array::data_offset();
-  // RCX is smi tagged, but table entries are two words, so TIMES_8.
-  __ movq(RDX, FieldAddress(RDI, RCX, TIMES_8, base));
-
-  ASSERT(kIllegalCid == 0);
-  __ testq(RDX, RDX);
-  __ j(ZERO, &load_target_function, Assembler::kNearJump);
-  __ cmpq(RDX, RAX);
-  __ j(NOT_EQUAL, &update, Assembler::kNearJump);
-
-  __ Bind(&load_target_function);
-  // Call the target found in the cache.  For a class id match, this is a
-  // proper target for the given name and arguments descriptor.  If the
-  // illegal class id was found, the target is a cache miss handler that can
-  // be invoked as a normal Dart function.
-  __ movq(RAX, FieldAddress(RDI, RCX, TIMES_8, base + kWordSize));
-  __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset()));
-  __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
-}
-
-
 // Called from megamorphic calls.
 //  RDI: receiver
 //  RBX: MegamorphicCache (preserved)
@@ -2132,8 +2016,68 @@
 //  CODE_REG: target Code
 //  R10: arguments descriptor
 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) {
-  EmitMegamorphicLookup(assembler);
+  // Jump if receiver is a smi.
+  Label smi_case;
+  __ testq(RDI, Immediate(kSmiTagMask));
+  // Jump out of line for smi case.
+  __ j(ZERO, &smi_case, Assembler::kNearJump);
+
+  // Loads the cid of the object.
+  __ LoadClassId(RAX, RDI);
+
+  Label cid_loaded;
+  __ Bind(&cid_loaded);
+  __ movq(R9, FieldAddress(RBX, MegamorphicCache::mask_offset()));
+  __ movq(RDI, FieldAddress(RBX, MegamorphicCache::buckets_offset()));
+  // R9: mask.
+  // RDI: cache buckets array.
+
+  // Tag cid as a smi.
+  __ addq(RAX, RAX);
+
+  // Compute the table index.
+  ASSERT(MegamorphicCache::kSpreadFactor == 7);
+  // Use leaq and subq multiply with 7 == 8 - 1.
+  __ leaq(RCX, Address(RAX, TIMES_8, 0));
+  __ subq(RCX, RAX);
+
+  Label loop;
+  __ Bind(&loop);
+  __ andq(RCX, R9);
+
+  const intptr_t base = Array::data_offset();
+  // RCX is smi tagged, but table entries are two words, so TIMES_8.
+  Label probe_failed;
+  __ cmpq(RAX, FieldAddress(RDI, RCX, TIMES_8, base));
+  __ j(NOT_EQUAL, &probe_failed, Assembler::kNearJump);
+
+  Label load_target;
+  __ Bind(&load_target);
+  // Call the target found in the cache.  For a class id match, this is a
+  // proper target for the given name and arguments descriptor.  If the
+  // illegal class id was found, the target is a cache miss handler that can
+  // be invoked as a normal Dart function.
+  __ movq(RAX, FieldAddress(RDI, RCX, TIMES_8, base + kWordSize));
+  __ movq(R10,
+          FieldAddress(RBX, MegamorphicCache::arguments_descriptor_offset()));
+  __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset()));
+  __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
+
   __ ret();
+
+  // Probe failed, check if it is a miss.
+  __ Bind(&probe_failed);
+  __ cmpq(FieldAddress(RDI, RCX, TIMES_8, base), Immediate(kIllegalCid));
+  __ j(ZERO, &load_target, Assembler::kNearJump);
+
+  // Try next extry in the table.
+  __ AddImmediate(RCX, Immediate(Smi::RawValue(1)));
+  __ jmp(&loop);
+
+  // Load cid for the Smi case.
+  __ Bind(&smi_case);
+  __ movq(RAX, Immediate(kSmiCid));
+  __ jmp(&cid_loaded);
 }
 
 
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 5e6a165..753594c 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -311,6 +311,9 @@
   V(TwoNewlines, "\n\n")                                                       \
   V(TwoSpaces, "  ")                                                           \
   V(_instanceOf, "_instanceOf")                                                \
+  V(_simpleInstanceOf, "_simpleInstanceOf")                                    \
+  V(_simpleInstanceOfTrue, "_simpleInstanceOfTrue")                            \
+  V(_simpleInstanceOfFalse, "_simpleInstanceOfFalse")                          \
   V(_instanceOfSmi, "_instanceOfSmi")                                          \
   V(_instanceOfNum, "_instanceOfNum")                                          \
   V(_instanceOfInt, "_instanceOfInt")                                          \
@@ -393,6 +396,7 @@
   V(_runPendingImmediateCallback, "_runPendingImmediateCallback")              \
   V(DartLibrary, "dart.library.")                                              \
   V(DartLibraryMirrors, "dart.library.mirrors")                                \
+  V(_name, "_name")                                                            \
 
 
 // Contains a list of frequently used strings in a canonicalized form. This
diff --git a/runtime/vm/tags.cc b/runtime/vm/tags.cc
index fa3cc67..ccb52ab 100644
--- a/runtime/vm/tags.cc
+++ b/runtime/vm/tags.cc
@@ -137,6 +137,7 @@
 }
 
 
+#ifndef PRODUCT
 void VMTagCounters::PrintToJSONObject(JSONObject* obj) {
   if (!FLAG_support_service) {
     return;
@@ -154,6 +155,7 @@
     }
   }
 }
+#endif  // !PRODUCT
 
 
 const char* UserTags::TagName(uword tag_id) {
diff --git a/runtime/vm/tags.h b/runtime/vm/tags.h
index 3279c82..8c6ef65 100644
--- a/runtime/vm/tags.h
+++ b/runtime/vm/tags.h
@@ -98,7 +98,9 @@
 
   int64_t count(uword tag);
 
+#ifndef PRODUCT
   void PrintToJSONObject(JSONObject* obj);
+#endif  // !PRODUCT
 
  private:
   int64_t counters_[VMTag::kNumVMTags];
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 1ce083a..d9bef66 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -105,6 +105,8 @@
     StubCode::UpdateStoreBuffer_entry()->EntryPoint(), 0)                      \
   V(uword, call_to_runtime_entry_point_,                                       \
     StubCode::CallToRuntime_entry()->EntryPoint(), 0)                          \
+  V(uword, megamorphic_lookup_entry_point_,                                    \
+    StubCode::MegamorphicLookup_entry()->EntryPoint(), 0)                      \
 
 #endif
 
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index d0deba9..dc2edac 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -405,6 +405,25 @@
 }
 
 
+// Test case for recursive safepoint operations.
+VM_TEST_CASE(RecursiveSafepointTest1) {
+  intptr_t count = 0;
+  {
+    SafepointOperationScope safepoint_scope(thread);
+    count += 1;
+    {
+      SafepointOperationScope safepoint_scope(thread);
+      count += 1;
+      {
+        SafepointOperationScope safepoint_scope(thread);
+        count += 1;
+      }
+    }
+  }
+  EXPECT(count == 3);
+}
+
+
 VM_TEST_CASE(ThreadIterator_Count) {
   intptr_t thread_count_0 = 0;
   intptr_t thread_count_1 = 0;
@@ -525,6 +544,46 @@
 }
 
 
+// Test recursive safepoint operation scopes with other threads trying
+// to also start a safepoint operation scope.
+VM_TEST_CASE(RecursiveSafepointTest2) {
+  Isolate* isolate = thread->isolate();
+  Monitor monitor;
+  intptr_t expected_count = 0;
+  intptr_t total_done = 0;
+  intptr_t exited = 0;
+  for (int i = 0; i < SafepointTestTask::kTaskCount; i++) {
+    Dart::thread_pool()->Run(new SafepointTestTask(
+        isolate, &monitor, &expected_count, &total_done, &exited));
+  }
+  bool all_helpers = false;
+  do {
+    SafepointOperationScope safepoint_scope(thread);
+    {
+      SafepointOperationScope safepoint_scope(thread);
+      MonitorLocker ml(&monitor);
+      if (expected_count == SafepointTestTask::kTaskCount) {
+        all_helpers = true;
+      }
+    }
+  } while (!all_helpers);
+  String& label = String::Handle(String::New("foo"));
+  UserTag& tag = UserTag::Handle(UserTag::New(label));
+  isolate->set_current_tag(tag);
+  bool all_exited = false;
+  do {
+    SafepointOperationScope safepoint_scope(thread);
+    {
+      SafepointOperationScope safepoint_scope(thread);
+      MonitorLocker ml(&monitor);
+      if (exited == SafepointTestTask::kTaskCount) {
+        all_exited = true;
+      }
+    }
+  } while (!all_exited);
+}
+
+
 class AllocAndGCTask : public ThreadPool::Task {
  public:
   AllocAndGCTask(Isolate* isolate,
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index b0c773e..522974e 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -269,7 +269,7 @@
 
   {
     TransitionNativeToVM transition(Thread::Current());
-    isolate->ReloadSources(/* test_mode = */ true);
+    isolate->ReloadSources(/* dont_delete_reload_context = */ true);
   }
 
   return Dart_FinalizeLoading(false);
@@ -279,9 +279,8 @@
 Dart_Handle TestCase::GetReloadErrorOrRootLibrary() {
   Isolate* isolate = Isolate::Current();
 
-  if (isolate->reload_context() != NULL) {
-    // We should only have a reload context hanging around if an error occurred.
-    ASSERT(isolate->reload_context()->has_error());
+  if (isolate->reload_context() != NULL &&
+      isolate->reload_context()->has_error()) {
     // Return a handle to the error.
     return Api::NewHandle(Thread::Current(),
                           isolate->reload_context()->error());
@@ -298,7 +297,14 @@
     return result;
   }
 
-  return GetReloadErrorOrRootLibrary();
+  result = GetReloadErrorOrRootLibrary();
+
+  Isolate* isolate = Isolate::Current();
+  if (isolate->reload_context() != NULL) {
+    isolate->DeleteReloadContext();
+  }
+
+  return result;
 }
 
 
@@ -360,6 +366,7 @@
   code_ = Code::FinalizeCode(function, assembler_);
   code_.set_owner(function);
   code_.set_exception_handlers(Object::empty_exception_handlers());
+#ifndef PRODUCT
   if (FLAG_disassemble) {
     OS::Print("Code for test '%s' {\n", name_);
     const Instructions& instructions =
@@ -368,6 +375,7 @@
     Disassembler::Disassemble(start, start + assembler_->CodeSize());
     OS::Print("}\n");
   }
+#endif  // !PRODUCT
 }
 
 
diff --git a/runtime/vm/verifier.cc b/runtime/vm/verifier.cc
index 18a7874..de125bf 100644
--- a/runtime/vm/verifier.cc
+++ b/runtime/vm/verifier.cc
@@ -82,4 +82,22 @@
   delete allocated_set;
 }
 
+
+#if defined(DEBUG)
+VerifyCanonicalVisitor::VerifyCanonicalVisitor(Thread* thread)
+    : thread_(thread),
+      instanceHandle_(Instance::Handle(thread->zone())) {
+}
+
+
+void VerifyCanonicalVisitor::VisitObject(RawObject* obj) {
+  if (obj->GetClassId() >= kInstanceCid) {
+    if (obj->IsCanonical()) {
+      instanceHandle_ ^= obj;
+      ASSERT(instanceHandle_.CheckIsCanonical(thread_));
+    }
+  }
+}
+#endif  // defined(DEBUG)
+
 }  // namespace dart
diff --git a/runtime/vm/verifier.h b/runtime/vm/verifier.h
index a34d7f6..8ae222d 100644
--- a/runtime/vm/verifier.h
+++ b/runtime/vm/verifier.h
@@ -81,6 +81,21 @@
   DISALLOW_COPY_AND_ASSIGN(VerifyWeakPointersVisitor);
 };
 
+
+#if defined(DEBUG)
+class VerifyCanonicalVisitor : public ObjectVisitor {
+ public:
+  explicit VerifyCanonicalVisitor(Thread* thread);
+  virtual void VisitObject(RawObject* obj);
+
+ private:
+  Thread* thread_;
+  Instance& instanceHandle_;
+
+  DISALLOW_COPY_AND_ASSIGN(VerifyCanonicalVisitor);
+};
+#endif  // defined(DEBUG)
+
 }  // namespace dart
 
 #endif  // VM_VERIFIER_H_
diff --git a/runtime/vm/virtual_memory.h b/runtime/vm/virtual_memory.h
index 270d3cf..6e43cb4 100644
--- a/runtime/vm/virtual_memory.h
+++ b/runtime/vm/virtual_memory.h
@@ -24,6 +24,7 @@
   // The reserved memory is unmapped on destruction.
   ~VirtualMemory();
 
+  int32_t handle() const { return handle_; }
   uword start() const { return region_.start(); }
   uword end() const { return region_.end(); }
   void* address() const { return region_.pointer(); }
@@ -82,9 +83,10 @@
 
   // This constructor is only used internally when reserving new virtual spaces.
   // It does not reserve any virtual address space on its own.
-  explicit VirtualMemory(const MemoryRegion& region) :
+  explicit VirtualMemory(const MemoryRegion& region, int32_t handle = 0) :
       region_(region.pointer(), region.size()),
       reserved_size_(region.size()),
+      handle_(handle),
       embedder_allocated_(false) { }
 
   MemoryRegion region_;
@@ -93,6 +95,8 @@
   // Its start coincides with region_, but its size might not, due to Truncate.
   intptr_t reserved_size_;
 
+  int32_t handle_;
+
   static uword page_size_;
 
   // True for a region provided by the embedder.
diff --git a/runtime/vm/virtual_memory_fuchsia.cc b/runtime/vm/virtual_memory_fuchsia.cc
index da32045..933f494 100644
--- a/runtime/vm/virtual_memory_fuchsia.cc
+++ b/runtime/vm/virtual_memory_fuchsia.cc
@@ -7,9 +7,11 @@
 
 #include "vm/virtual_memory.h"
 
+#include <magenta/syscalls.h>
 #include <unistd.h>  // NOLINT
 
 #include "platform/assert.h"
+#include "vm/memory_region.h"
 #include "vm/os.h"
 
 namespace dart {
@@ -23,13 +25,45 @@
 
 
 VirtualMemory* VirtualMemory::ReserveInternal(intptr_t size) {
-  UNIMPLEMENTED();
-  return NULL;
+  mx_handle_t vmo = mx_vm_object_create(size);
+  if (vmo <= 0) {
+    return NULL;
+  }
+
+  // TODO(zra): map with PERM_NONE, when that works, and relax with
+  // Commit and Protect when they are implemented.
+  // Issue MG-161.
+  const int prot = MX_VM_FLAG_PERM_READ |
+                   MX_VM_FLAG_PERM_WRITE |
+                   MX_VM_FLAG_PERM_EXECUTE;
+  uintptr_t addr;
+  mx_status_t status = mx_process_vm_map(0, vmo, 0, size, &addr, prot);
+  if (status != NO_ERROR) {
+    mx_handle_close(vmo);
+    FATAL("VirtualMemory::ReserveInternal FAILED");
+    return NULL;
+  }
+
+  MemoryRegion region(reinterpret_cast<void*>(addr), size);
+  return new VirtualMemory(region, vmo);
 }
 
 
 VirtualMemory::~VirtualMemory() {
-  UNIMPLEMENTED();
+  if (!embedder_allocated()) {
+    // TODO(zra): Use reserved_size_.
+    // Issue MG-162.
+    mx_status_t status = mx_process_vm_unmap(
+        0, reinterpret_cast<uintptr_t>(address()), 0 /*reserved_size_*/);
+    if (status != NO_ERROR) {
+      FATAL("VirtualMemory::~VirtualMemory: unamp FAILED");
+    }
+
+    status = mx_handle_close(handle());
+    if (status != NO_ERROR) {
+      FATAL("VirtualMemory::~VirtualMemory: handle_close FAILED");
+    }
+  }
 }
 
 
@@ -40,14 +74,15 @@
 
 
 bool VirtualMemory::Commit(uword addr, intptr_t size, bool executable) {
-  UNIMPLEMENTED();
-  return false;
+  // TODO(zra): Implement when the protections for a mapping can be changed.
+  // Issue MG-133.
+  return true;
 }
 
 
 bool VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
-  UNIMPLEMENTED();
-  return false;
+  // TODO(zra): Implement when Fuchsia has an mprotect-like call.
+  return true;
 }
 
 }  // namespace dart
diff --git a/samples-dev/swarm/UIState.dart b/samples-dev/swarm/UIState.dart
index dffb1c7..2d40843 100644
--- a/samples-dev/swarm/UIState.dart
+++ b/samples-dev/swarm/UIState.dart
@@ -60,7 +60,8 @@
     // TODO(jmesserly): [state] should be an Object, and we should pass it to
     // the state parameter instead of as a #hash URL. Right now we're working
     //  around b/4582542.
-    window.history.pushState(null, '${document.title}#$state');
+    window.history.pushState(null,
+        '${document.title}', '${document.title}#$state');
   }
 
   /**
diff --git a/samples-dev/swarm/swarm_ui_lib/touch/FxUtil.dart b/samples-dev/swarm/swarm_ui_lib/touch/FxUtil.dart
index 82d0a54..aa084e8 100644
--- a/samples-dev/swarm/swarm_ui_lib/touch/FxUtil.dart
+++ b/samples-dev/swarm/swarm_ui_lib/touch/FxUtil.dart
@@ -68,11 +68,18 @@
    */
   static Coordinate computeRelativePosition(Element element, Element target) {
     final testPoint = new Point(0, 0);
+    /*
     final pagePoint =
         window.convertPointFromNodeToPage(element, testPoint);
     final pointRelativeToTarget =
         window.convertPointFromPageToNode(target, pagePoint);
     return new Coordinate(pointRelativeToTarget.x, pointRelativeToTarget.y);
+    */
+    // TODO(sra): Test this version that avoids the nonstandard
+    // `convertPointFromPageToNode`.
+    var eRect = element.getBoundingClientRect();
+    var tRect = target.getBoundingClientRect();
+    return new Coordinate(eRect.left - tRect.left, eRect.top - tRect.top);
   }
 
   /** Clear a -webkit-transform from an element. */
diff --git a/samples-dev/swarm/swarm_ui_lib/touch/Scrollbar.dart b/samples-dev/swarm/swarm_ui_lib/touch/Scrollbar.dart
index 1c2a6f2..1ac758c 100644
--- a/samples-dev/swarm/swarm_ui_lib/touch/Scrollbar.dart
+++ b/samples-dev/swarm/swarm_ui_lib/touch/Scrollbar.dart
@@ -155,7 +155,7 @@
     }
   }
 
-  void _onStart(UIEvent e) {
+  void _onStart(/*MouseEvent | Touch*/ e) {
     Element elementOver = e.target;
     if (elementOver == _verticalElement ||
         elementOver == _horizontalElement) {
@@ -196,7 +196,7 @@
     }
   }
 
-  void _onMove(UIEvent e) {
+  void _onMove(/*MouseEvent | Touch*/ e) {
     if (!_scrollBarDragInProgress) {
       return;
     }
diff --git a/samples-dev/swarm/swarm_ui_lib/touch/TouchUtil.dart b/samples-dev/swarm/swarm_ui_lib/touch/TouchUtil.dart
index d7992f7..8b82181 100644
--- a/samples-dev/swarm/swarm_ui_lib/touch/TouchUtil.dart
+++ b/samples-dev/swarm/swarm_ui_lib/touch/TouchUtil.dart
@@ -271,4 +271,5 @@
   Point get page { throw new UnimplementedError(); }
   List get path { throw new UnimplementedError(); }
   Point get screen { throw new UnimplementedError(); }
+  /*InputDevice*/ get sourceDevice { throw new UnimplementedError(); }
 }
diff --git a/sdk/bin/pub b/sdk/bin/pub
index 50f0d1d..a8514ea 100755
--- a/sdk/bin/pub
+++ b/sdk/bin/pub
@@ -29,6 +29,13 @@
 unset VM_OPTIONS
 declare -a VM_OPTIONS
 
+if [[ `uname` == 'Darwin' ]];
+then
+  OUT_DIR="$BIN_DIR"/../../xcodebuild/
+else
+  OUT_DIR="$BIN_DIR"/../../out/
+fi
+
 # Allow extra VM options to be passed in through an environment variable.
 if [[ $DART_VM_OPTIONS ]]; then
   read -a OPTIONS <<< "$DART_VM_OPTIONS"
@@ -37,7 +44,29 @@
 
 if [ -z "$DART_CONFIGURATION" ];
 then
-  DART_CONFIGURATION="ReleaseX64"
+  DIRS=$( ls "$OUT_DIR" )
+  # list of possible configurations in decreasing desirability
+  CONFIGS=("ReleaseX64" "ReleaseIA32" "DebugX64" "DebugIA32"
+    "ReleaseARM"    "ReleaseARM64"    "ReleaseARMV5TE"    "ReleaseMIPS"
+    "DebugARM"      "DebugARM64"      "DebugARMV5TE"      "DebugMIPS")
+  DART_CONFIGURATION="None"
+  for CONFIG in ${CONFIGS[*]}
+  do
+    for DIR in $DIRS;
+    do
+      if [ "$CONFIG" = "$DIR" ];
+      then
+        # choose most desirable configuration that is available and break
+        DART_CONFIGURATION="$DIR"
+        break 2
+      fi
+    done
+  done
+  if [ "$DART_CONFIGURATION" = "None" ]
+  then
+    echo "No valid dart configuration found in $OUT_DIR"
+    exit 1
+  fi
 fi
 
 if [[ `uname` == 'Darwin' ]];
diff --git a/sdk/lib/_internal/js_runtime/lib/js_number.dart b/sdk/lib/_internal/js_runtime/lib/js_number.dart
index 907da4e..1f9748c 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_number.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_number.dart
@@ -66,20 +66,55 @@
 
   int toInt() {
     if (this >= _MIN_INT32 && this <= _MAX_INT32) {
+      // 0 and -0.0 handled here.
       return JS('int', '# | 0', this);
     }
     if (JS('bool', r'isFinite(#)', this)) {
       return JS('int', r'# + 0', truncateToDouble());  // Converts -0.0 to +0.0.
     }
-    // This is either NaN, Infinity or -Infinity.
-    throw new UnsupportedError(JS("String", '"" + #', this));
+    // [this] is either NaN, Infinity or -Infinity.
+    throw new UnsupportedError(JS("String", '"" + # + ".toInt()"', this));
   }
 
   int truncate() => toInt();
 
-  int ceil() => ceilToDouble().toInt();
+  int ceil() {
+    if (this >= 0) {
+      if (this <= _MAX_INT32) {
+        int truncated = JS('int', '# | 0', this);  // converts -0.0 to 0.
+        return this == truncated ? truncated : truncated + 1;
+      }
+    } else {
+      if (this >= _MIN_INT32) {
+        return JS('int', '# | 0', this);
+      }
+    }
+    var d = JS('num', 'Math.ceil(#)', this);
+    if (JS('bool', r'isFinite(#)', d)) {
+      return JS('int', r'#', d);
+    }
+    // [this] is either NaN, Infinity or -Infinity.
+    throw new UnsupportedError(JS("String", '"" + # + ".ceil()"', this));
+  }
 
-  int floor() => floorToDouble().toInt();
+  int floor() {
+    if (this >= 0) {
+      if (this <= _MAX_INT32) {
+        return JS('int', '# | 0', this);
+      }
+    } else {
+      if (this >= _MIN_INT32) {
+        int truncated = JS('int', '# | 0', this);
+        return this == truncated ? truncated : truncated - 1;
+      }
+    }
+    var d = JS('num', 'Math.floor(#)', this);
+    if (JS('bool', r'isFinite(#)', d)) {
+      return JS('int', r'#', d);
+    }
+    // [this] is either NaN, Infinity or -Infinity.
+    throw new UnsupportedError(JS("String", '"" + # + ".floor()"', this));
+  }
 
   int round() {
     if (this > 0) {
@@ -96,8 +131,8 @@
       // some JavaScript VMs can be a slow path.
       return JS('int', r'0 - Math.round(0 - #)', this);
     }
-    // This is either NaN, Infinity or -Infinity.
-    throw new UnsupportedError(JS("String", '"" + #', this));
+    // [this] is either NaN, Infinity or -Infinity.
+    throw new UnsupportedError(JS("String", '"" + # + ".round()"', this));
   }
 
   double ceilToDouble() => JS('num', r'Math.ceil(#)', this);
@@ -246,23 +281,43 @@
   bool _isInt32(value) => JS('bool', '(# | 0) === #', value, value);
 
   int operator ~/(num other) {
+    if (other is !num) throw argumentErrorValue(other);
     if (false) _tdivFast(other); // Ensure resolution.
-    if (_isInt32(this) && _isInt32(other) && 0 != other && -1 != other) {
-      return JS('int', r'(# / #) | 0', this, other);
-    } else {
-      return _tdivSlow(other);
+    if (_isInt32(this)) {
+      if (other >= 1 || other < -1) {
+        return JS('int', r'(# / #) | 0', this, other);
+      }
     }
+    return _tdivSlow(other);
   }
 
   int _tdivFast(num other) {
+    // [other] is known to be a number outside the range [-1, 1).
     return _isInt32(this)
         ? JS('int', r'(# / #) | 0', this, other)
-        : (JS('num', r'# / #', this, other)).toInt();
+        : _tdivSlow(other);
   }
 
   int _tdivSlow(num other) {
-    if (other is !num) throw argumentErrorValue(other);
-    return (JS('num', r'# / #', this, other)).toInt();
+    var quotient = JS('num', r'# / #', this, other);
+    if (quotient >= _MIN_INT32 && quotient <= _MAX_INT32) {
+      // This path includes -0.0 and +0.0.
+      return JS('int', '# | 0', quotient);
+    }
+    if (quotient > 0) {
+      // This path excludes the special cases -0.0, NaN and -Infinity, leaving
+      // only +Infinity, for which a direct test is faster than [isFinite].
+      if (JS('bool', r'# !== (1/0)', quotient)) {
+        return JS('int', r'Math.floor(#)', quotient);
+      }
+    } else if (JS('bool', '# > (-1/0)', quotient)) {
+      // This test excludes NaN and -Infinity.
+      return JS('int', r'Math.ceil(#)', quotient);
+    }
+
+    // [quotient] is either NaN, Infinity or -Infinity.
+    throw new UnsupportedError(
+        "Result of truncating division is $quotient: $this ~/ $other");
   }
 
   // TODO(ngeoffray): Move the bit operations below to [JSInt] and
diff --git a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
index e304873..0ecb55805 100644
--- a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
+++ b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
@@ -116,6 +116,12 @@
       maturity: Maturity.STABLE,
       dart2jsPath: "js/dart2js/js_dart2js.dart"),
 
+  "js_util": const LibraryInfo(
+      "js_util/dartium/js_util_dartium.dart",
+      categories: "Client",
+      maturity: Maturity.STABLE,
+      dart2jsPath: "js_util/dart2js/js_util_dart2js.dart"),
+
   "math": const LibraryInfo(
       "math/math.dart",
       categories: "Client,Server,Embedded",
diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart
index 24f83f8..b81a7fe 100644
--- a/sdk/lib/async/zone.dart
+++ b/sdk/lib/async/zone.dart
@@ -194,14 +194,26 @@
 }
 
 /**
- * This class wraps zones for delegation.
+ * An adapted view of the parent zone.
  *
- * When forwarding to parent zones one can't just invoke the parent zone's
- * exposed functions (like [Zone.run]), but one needs to provide more
- * information (like the zone the `run` was initiated). Zone callbacks thus
- * receive more information including this [ZoneDelegate] class. When delegating
- * to the parent zone one should go through the given instance instead of
- * directly invoking the parent zone.
+ * This class allows the implementation of a zone method to invoke methods on
+ * the parent zone while retaining knowledge of the originating zone.
+ *
+ * Custom zones (created through [Zone.fork] or [runZoned]) can provide
+ * implementations of most methods of zones. This is similar to overriding
+ * methods on [Zone], except that this mechanism doesn't require subclassing.
+ *
+ * A custom zone function (provided through a [ZoneSpecification]) typically
+ * records or wraps its parameters and then delegates the operation to its
+ * parent zone using the provided [ZoneDelegate].
+ *
+ * While zones have access to their parent zone (through [Zone.parent]) it is
+ * recommended to call the methods on the provided parent delegate for two
+ * reasons:
+ * 1. the delegate methods take an additional `zone` argument which is the
+ *   zone the action has been initiated in.
+ * 2. delegate calls are more efficient, since the implementation knows how
+ *   to skip zones that would just delegate to their parents.
  */
 abstract class ZoneDelegate {
   /*=R*/ handleUncaughtError/*<R>*/(
@@ -224,117 +236,266 @@
 }
 
 /**
- * A Zone represents the asynchronous version of a dynamic extent. Asynchronous
- * callbacks are executed in the zone they have been queued in. For example,
- * the callback of a `future.then` is executed in the same zone as the one where
- * the `then` was invoked.
+ * A zone represents an environment that remains stable across asynchronous
+ * calls.
+ *
+ * Code is always executed in the context of a zone, available as
+ * [Zone.current]. The initial `main` function runs in the context of the
+ * default zone ([Zone.ROOT]). Code can be run in a different zone using either
+ * [runZoned], to create a new zone, or [Zone.run] to run code in the context of
+ * an existing zone likely created using [Zone.fork].
+ *
+ * Developers can create a new zone that overrides some of the functionality of
+ * an existing zone. For example, custom zones can replace of modify the
+ * behavior of `print`, timers, microtasks or how uncaught errors are handled.
+ *
+ * The [Zone] class is not subclassable, but users can provide custom zones by
+ * forking an existing zone (usually [Zone.current]) with a [ZoneSpecification].
+ * This is similar to creating a new class that extends the base `Zone` class
+ * and that overrides some methods, except without actually creating a new
+ * class. Instead the overriding methods are provided as functions that
+ * explicitly take the equivalent of their own class, the "super" class and the
+ * `this` object as parameters.
+ *
+ * Asynchronous callbacks always run in the context of the zone where they were
+ * scheduled. This is implemented using two steps:
+ * 1. the callback is first registered using one of [registerCallback],
+ *   [registerUnaryCallback], or [registerBinaryCallback]. This allows the zone
+ *   to record that a callback exists and potentially modify it (by returning a
+ *   different callback). The code doing the registration (e.g., `Future.then`)
+ *   also remembers the current zone so that it can later run the callback in
+ *   that zone.
+ * 2. At a later point the registered callback is run in the remembered zone.
+ *
+ * This is all handled internally by the platform code and most users don't need
+ * to worry about it. However, developers of new asynchronous operations,
+ * provided by the underlying system or through native extensions, must follow
+ * the protocol to be zone compatible.
+ *
+ * For convenience, zones provide [bindCallback] (and the corresponding
+ * [bindUnaryCallback] or [bindBinaryCallback]) to make it easier to respect the
+ * zone contract: these functions first invoke the corresponding `register`
+ * functions and then wrap the returned function so that it runs in the current
+ * zone when it is later asynchronously invoked.
  */
 abstract class Zone {
   // Private constructor so that it is not possible instantiate a Zone class.
   Zone._();
 
-  /** The root zone that is implicitly created. */
+  /**
+   * The root zone.
+   *
+   * All isolate entry functions (`main` or spawned functions) start running in
+   * the root zone (that is, [Zone.current] is identical to [Zone.ROOT] when the
+   * entry function is called). If no custom zone is created, the rest of the
+   * program always runs in the root zone.
+   *
+   * The root zone implements the default behavior of all zone operations.
+   * Many methods, like [registerCallback] do the bare minimum required of the
+   * function, and are only provided as a hook for custom zones. Others, like
+   * [scheduleMicrotask], interact with the underlying system to implement the
+   * desired behavior.
+   */
   static const Zone ROOT = _ROOT_ZONE;
 
   /** The currently running zone. */
   static Zone _current = _ROOT_ZONE;
 
+  /** The zone that is currently active. */
   static Zone get current => _current;
 
+  /**
+   * Handles uncaught asynchronous errors.
+   *
+   * There are two kind of asynchronous errors that are handled by this
+   * function:
+   * 1. Uncaught errors that were thrown in asynchronous callbacks, for example,
+   *   a `throw` in the function passed to [Timer.run].
+   * 2. Asynchronous errors that are pushed through [Future] and [Stream]
+   *   chains, but for which no child registered an error handler.
+   *   Most asynchronous classes, like [Future] or [Stream] push errors to their
+   *   listeners. Errors are propagated this way until either a listener handles
+   *   the error (for example with [Future.catchError]), or no listener is
+   *   available anymore. In the latter case, futures and streams invoke the
+   *   zone's [handleUncaughtError].
+   *
+   * By default, when handled by the root zone, uncaught asynchronous errors are
+   * treated like uncaught synchronous exceptions.
+   */
   /*=R*/ handleUncaughtError/*<R>*/(error, StackTrace stackTrace);
 
   /**
-   * Returns the parent zone.
+   * The parent zone of the this zone.
    *
-   * Returns `null` if `this` is the [ROOT] zone.
+   * Is `null` if `this` is the [ROOT] zone.
+   *
+   * Zones are created by [fork] on an existing zone, or by [runZoned] which
+   * forks the [current] zone. The new zone's parent zone is the zone it was
+   * forked from.
    */
   Zone get parent;
 
   /**
    * The error zone is the one that is responsible for dealing with uncaught
    * errors.
-   * Errors are not allowed to cross between zones with different error-zones.
    *
-   * This is the closest parent or ancestor zone of this zone that has a custom
+   * This is the closest parent zone of this zone that provides a
    * [handleUncaughtError] method.
+   *
+   * Asynchronous errors never cross zone boundaries between zones with
+   * different error handlers.
+   *
+   * Example:
+   * ```
+   * import 'dart:async';
+   *
+   * main() {
+   *   var future;
+   *   runZoned(() {
+   *     // The asynchronous error is caught by the custom zone which prints
+   *     // 'asynchronous error'.
+   *     future = new Future.error("asynchronous error");
+   *   }, onError: (e) { print(e); });  // Creates a zone with an error handler.
+   *   // The following `catchError` handler is never invoked, because the
+   *   // custom zone created by the call to `runZoned` provides an
+   *   // error handler.
+   *   future.catchError((e) { throw "is never reached"; });
+   * }
+   * ```
+   *
+   * Note that errors cannot enter a child zone with a different error handler
+   * either:
+   * ```
+   * import 'dart:async';
+   *
+   * main() {
+   *   runZoned(() {
+   *     // The following asynchronous error is *not* caught by the `catchError`
+   *     // in the nested zone, since errors are not to cross zone boundaries
+   *     // with different error handlers.
+   *     // Instead the error is handled by the current error handler,
+   *     // printing "Caught by outer zone: asynchronous error".
+   *     var future = new Future.error("asynchronous error");
+   *     runZoned(() {
+   *       future.catchError((e) { throw "is never reached"; });
+   *     }, onError: (e) { throw "is never reached"; });
+   *   }, onError: (e) { print("Caught by outer zone: $e"); });
+   * }
+   * ```
    */
   Zone get errorZone;
 
   /**
    * Returns true if `this` and [otherZone] are in the same error zone.
    *
-   * Two zones are in the same error zone if they inherit their
-   * [handleUncaughtError] callback from the same [errorZone].
+   * Two zones are in the same error zone if they have the same [errorZone].
    */
   bool inSameErrorZone(Zone otherZone);
 
   /**
    * Creates a new zone as a child of `this`.
    *
-   * The new zone will have behavior like the current zone, except where
-   * overridden by functions in [specification].
+   * The new zone uses the closures in the given [specification] to override
+   * the current's zone behavior. All specification entries that are `null`
+   * inherit the behavior from the parent zone (`this`).
    *
-   * The new zone will have the same stored values (accessed through
-   * `operator []`) as this zone, but updated with the keys and values
-   * in [zoneValues]. If a key is in both this zone's values and in
-   * `zoneValues`, the new zone will use the value from `zoneValues``.
+   * The new zone inherits the stored values (accessed through [operator []])
+   * of this zone and updates them with values from [zoneValues], which either
+   * adds new values or overrides existing ones.
+   *
+   * Note that the fork operation is interceptible. A zone can thus change
+   * the zone specification (or zone values), giving the forking zone full
+   * control over the child zone.
    */
-  Zone fork({ ZoneSpecification specification,
-              Map zoneValues });
+  Zone fork({ZoneSpecification specification,
+             Map zoneValues});
 
   /**
-   * Executes the given function [f] in this zone.
+   * Executes [action] in this zone.
+   *
+   * By default (as implemented in the [ROOT] zone), runs [action]
+   * with [current] set to this zone.
+   *
+   * If [action] throws, the synchronous exception is not caught by the zone's
+   * error handler. Use [runGuarded] to achieve that.
+   *
+   * Since the root zone is the only zone that can modify the value of
+   * [current], custom zones intercepting run should always delegate to their
+   * parent zone. They may take actions before and after the call.
    */
-  /*=R*/ run/*<R>*/(/*=R*/ f());
+  /*=R*/ run/*<R>*/(/*=R*/ action());
 
   /**
-   * Executes the given callback [f] with argument [arg] in this zone.
+   * Executes the given [action] with [argument] in this zone.
+   *
+   * As [run] except that [action] is called with one [argument] instead of
+   * none.
    */
-  /*=R*/ runUnary/*<R, T>*/(/*=R*/ f(/*=T*/ arg), /*=T*/ arg);
+  /*=R*/ runUnary/*<R, T>*/(/*=R*/ action(/*=T*/ argument), /*=T*/ argument);
 
   /**
-   * Executes the given callback [f] with argument [arg1] and [arg2] in this
+   * Executes the given [action] with [argument1] and [argument2] in this
    * zone.
+   *
+   * As [run] except that [action] is called with two arguments instead of none.
    */
   /*=R*/ runBinary/*<R, T1, T2>*/(
-      /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2);
+      /*=R*/ action(/*=T1*/ argument1, /*=T2*/ argument2), /*=T1*/ argument1,
+      /*=T2*/ argument2);
 
   /**
-   * Executes the given function [f] in this zone.
+   * Executes the given [action] in this zone and catches synchronous
+   * errors.
    *
-   * Same as [run] but catches uncaught errors and gives them to
-   * [handleUncaughtError].
+   * This function is equivalent to:
+   * ```
+   * try {
+   *   return this.run(action);
+   * } catch (e, s) {
+   *   return this.handleUncaughtError(e, s);
+   * }
+   * ```
+   *
+   * See [run].
    */
-  /*=R*/ runGuarded/*<R>*/(/*=R*/ f());
+  /*=R*/ runGuarded/*<R>*/(/*=R*/ action());
 
   /**
-   * Executes the given callback [f] in this zone.
+   * Executes the given [action] with [argument] in this zone and
+   * catches synchronous errors.
    *
-   * Same as [runUnary] but catches uncaught errors and gives them to
-   * [handleUncaughtError].
+   * See [runGuarded].
    */
-  /*=R*/ runUnaryGuarded/*<R, T>*/(/*=R*/ f(/*=T*/ arg), /*=T*/ arg);
+  /*=R*/ runUnaryGuarded/*<R, T>*/(/*=R*/ action(/*=T*/ argument),
+      /*=T*/ argument);
 
   /**
-   * Executes the given callback [f] in this zone.
+   * Executes the given [action] with [argument1] and [argument2] in this
+   * zone and catches synchronous errors.
    *
-   * Same as [runBinary] but catches uncaught errors and gives them to
-   * [handleUncaughtError].
+   * See [runGuarded].
    */
   /*=R*/ runBinaryGuarded/*<R, T1, T2>*/(
-      /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2);
+      /*=R*/ action(/*=T1*/ argument1, /*=T2*/ argument2), /*=T1*/ argument1,
+      /*=T2*/ argument2);
 
   /**
    * Registers the given callback in this zone.
    *
-   * It is good practice to register asynchronous or delayed callbacks before
-   * invoking [run]. This gives the zone a chance to wrap the callback and
-   * to store information with the callback. For example, a zone may decide
+   * When implementing an asynchronous primitive that uses callbacks, the
+   * callback must be registered using [registerCallback] at the point where the
+   * user provides the callback. This allows zones to record other information
+   * that they need at the same time, perhaps even wrapping the callback, so
+   * that the callback is prepared when it is later run in the same zones
+   * (using [run]). For example, a zone may decide
    * to store the stack trace (at the time of the registration) with the
    * callback.
    *
-   * Returns a potentially new callback that should be used in place of the
-   * given [callback].
+   * Returns the callback that should be used in place of the provided
+   * [callback]. Frequently zones simply return the original callback.
+   *
+   * Custom zones may intercept this operation. The default implementation in
+   * [Zone.ROOT] returns the original callback unchanged.
    */
   ZoneCallback/*<R>*/ registerCallback/*<R>*/(/*=R*/ callback());
 
@@ -357,58 +518,79 @@
   /**
    *  Equivalent to:
    *
-   *      ZoneCallback registered = registerCallback(f);
+   *      ZoneCallback registered = this.registerCallback(action);
    *      if (runGuarded) return () => this.runGuarded(registered);
    *      return () => this.run(registered);
    *
    */
   ZoneCallback/*<R>*/ bindCallback/*<R>*/(
-      /*=R*/ f(), { bool runGuarded: true });
+      /*=R*/ action(), { bool runGuarded: true });
 
   /**
    *  Equivalent to:
    *
-   *      ZoneCallback registered = registerUnaryCallback(f);
+   *      ZoneCallback registered = this.registerUnaryCallback(action);
    *      if (runGuarded) return (arg) => this.runUnaryGuarded(registered, arg);
    *      return (arg) => thin.runUnary(registered, arg);
    */
   ZoneUnaryCallback/*<R, T>*/ bindUnaryCallback/*<R, T>*/(
-      /*=R*/ f(/*=T*/ arg), { bool runGuarded: true });
+      /*=R*/ action(/*=T*/ argument), { bool runGuarded: true });
 
   /**
    *  Equivalent to:
    *
-   *      ZoneCallback registered = registerBinaryCallback(f);
+   *      ZoneCallback registered = registerBinaryCallback(action);
    *      if (runGuarded) {
    *        return (arg1, arg2) => this.runBinaryGuarded(registered, arg);
    *      }
    *      return (arg1, arg2) => thin.runBinary(registered, arg1, arg2);
    */
   ZoneBinaryCallback/*<R, T1, T2>*/ bindBinaryCallback/*<R, T1, T2>*/(
-      /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), { bool runGuarded: true });
+      /*=R*/ action(/*=T1*/ argument1, /*=T2*/ argument2),
+      { bool runGuarded: true });
 
   /**
-   * Intercepts errors when added programmatically to a `Future` or `Stream`.
+   * Intercepts errors when added programatically to a `Future` or `Stream`.
    *
-   * When caling [Completer.completeError], [Stream.addError],
-   * or [Future] constructors that take an error or a callback that may throw,
-   * the current zone is allowed to intercept and replace the error.
+   * When calling [Completer.completeError], [Stream.addError],
+   * or some [Future] constructors, the current zone is allowed to intercept
+   * and replace the error.
    *
-   * When other libraries use intermediate controllers or completers, such
-   * calls may contain errors that have already been processed.
+   * Future constructors invoke this function when the error is received
+   * directly, for example with [Future.error], or when the error is caught
+   * synchronously, for example with [Future.sync].
    *
-   * Return `null` if no replacement is desired.
-   * The original error is used unchanged in that case.
-   * Otherwise return an instance of [AsyncError] holding
-   * the new pair of error and stack trace.
-   * If the [AsyncError.error] is `null`, it is replaced by a [NullThrownError].
+   * There is no guarantee that an error is only sent through [errorCallback]
+   * once. Libraries that use intermediate controllers or completers might
+   * end up invoking [errorCallback] multiple times.
+   *
+   * Returns `null` if no replacement is desired. Otherwise returns an instance
+   * of [AsyncError] holding the new pair of error and stack trace.
+   *
+   * Although not recommended, the returned instance may have its `error` member
+   * ([AsyncError.error]) be equal to `null` in which case the error should be
+   * replaced by a [NullThrownError].
+   *
+   * Custom zones may intercept this operation.
+   *
+   * Implementations of a new asynchronous primitive that converts synchronous
+   * errors to asynchronous errors rarely need to invoke [errorCallback], since
+   * errors are usually reported through future completers or stream
+   * controllers.
    */
   AsyncError errorCallback(Object error, StackTrace stackTrace);
 
   /**
-   * Runs [f] asynchronously in this zone.
+   * Runs [action] asynchronously in this zone.
+   *
+   * The global `scheduleMicrotask` delegates to the current zone's
+   * [scheduleMicrotask]. The root zone's implementation interacts with the
+   * underlying system to schedule the given callback as a microtask.
+   *
+   * Custom zones may intercept this operation (for example to wrap the given
+   * callback [action]).
    */
-  void scheduleMicrotask(void f());
+  void scheduleMicrotask(void action());
 
   /**
    * Creates a Timer where the callback is executed in this zone.
@@ -422,6 +604,24 @@
 
   /**
    * Prints the given [line].
+   *
+   * The global `print` function delegates to the current zone's [print]
+   * function which makes it possible to intercept printing.
+   *
+   * Example:
+   * ```
+   * import 'dart:async';
+   *
+   * main() {
+   *   runZoned(() {
+   *     // Ends up printing: "Intercepted: in zone".
+   *     print("in zone");
+   *   }, zoneSpecification: new ZoneSpecification(
+   *       print: (Zone self, ZoneDelegate parent, Zone zone, String line) {
+   *     parent.print(zone, "Intercepted: $line");
+   *   }));
+   * }
+   * ```
    */
   void print(String line);
 
diff --git a/sdk/lib/core/uri.dart b/sdk/lib/core/uri.dart
index 5718ca8..456bcb7 100644
--- a/sdk/lib/core/uri.dart
+++ b/sdk/lib/core/uri.dart
@@ -669,9 +669,9 @@
    * With non-Windows semantics the slash ("/") is used to separate
    * path segments.
    *
-   * With Windows semantics, backslash ("\") and forward-slash ("/")
+   * With Windows semantics, backslash ("\\") and forward-slash ("/")
    * are used to separate path segments, except if the path starts
-   * with "\\?\" in which case, only backslash ("\") separates path
+   * with "\\\\?\\" in which case, only backslash ("\\") separates path
    * segments.
    *
    * If the path starts with a path separator an absolute URI is
@@ -1878,7 +1878,7 @@
    * For non-Windows semantics the slash ("/") is used to separate
    * path segments.
    *
-   * For Windows semantics the backslash ("\") separator is used to
+   * For Windows semantics the backslash ("\\") separator is used to
    * separate path segments.
    *
    * If the URI is absolute the path starts with a path separator
diff --git a/sdk/lib/dart2dart.platform b/sdk/lib/dart2dart.platform
index fd9d8ed..d9aaa19 100644
--- a/sdk/lib/dart2dart.platform
+++ b/sdk/lib/dart2dart.platform
@@ -25,6 +25,7 @@
 io: io/io.dart
 isolate: isolate/isolate.dart
 js: js/dart2js/js_dart2js.dart
+js_util: js_util/dart2js/js_util_dart2js.dart
 math: math/math.dart
 mirrors: mirrors/mirrors.dart
 nativewrappers: html/dart2js/nativewrappers.dart
diff --git a/sdk/lib/dart_client.platform b/sdk/lib/dart_client.platform
index 2e01cd9..38442ef 100644
--- a/sdk/lib/dart_client.platform
+++ b/sdk/lib/dart_client.platform
@@ -26,6 +26,7 @@
 io: unsupported:
 isolate: isolate/isolate.dart
 js: js/dart2js/js_dart2js.dart
+js_util: js_util/dart2js/js_util_dart2js.dart
 math: math/math.dart
 mirrors: mirrors/mirrors.dart
 nativewrappers: html/dart2js/nativewrappers.dart
diff --git a/sdk/lib/dart_server.platform b/sdk/lib/dart_server.platform
index 821a175..f275aff 100644
--- a/sdk/lib/dart_server.platform
+++ b/sdk/lib/dart_server.platform
@@ -35,6 +35,7 @@
 web_sql: unsupported:
 _chrome: unsupported:
 js: unsupported:
+js_util: unsupported:
 _mirror_helper: unsupported:
 _internal: internal/internal.dart
 _js_helper: _internal/js_runtime/lib/js_helper.dart
diff --git a/sdk/lib/dart_shared.platform b/sdk/lib/dart_shared.platform
index 539b868..ae47359 100644
--- a/sdk/lib/dart_shared.platform
+++ b/sdk/lib/dart_shared.platform
@@ -24,6 +24,7 @@
 io: io/io.dart
 isolate: isolate/isolate.dart
 js: js/dart2js/js_dart2js.dart
+js_util: js_util/dart2js/js_util_dart2js.dart
 math: math/math.dart
 mirrors: mirrors/mirrors.dart
 nativewrappers: html/dart2js/nativewrappers.dart
diff --git a/sdk/lib/io/file.dart b/sdk/lib/io/file.dart
index 92d144f..73668e9 100644
--- a/sdk/lib/io/file.dart
+++ b/sdk/lib/io/file.dart
@@ -582,9 +582,9 @@
   List<int> readSync(int bytes);
 
   /**
-   * Reads into an existing List<int> from the file. If [start] is present, the
-   * bytes will be filled into [buffer] from at index [start], otherwise index
-   * 0. If [end] is present, the [end] - [start] bytes will be read into
+   * Reads into an existing [List<int>] from the file. If [start] is present,
+   * the bytes will be filled into [buffer] from at index [start], otherwise
+   * index 0. If [end] is present, the [end] - [start] bytes will be read into
    * [buffer], otherwise up to [buffer.length]. If [end] == [start] nothing
    * happends.
    *
@@ -593,8 +593,8 @@
   Future<int> readInto(List<int> buffer, [int start = 0, int end]);
 
   /**
-   * Synchronously reads into an existing List<int> from the file. If [start] is
-   * present, the bytes will be filled into [buffer] from at index [start],
+   * Synchronously reads into an existing [List<int>] from the file. If [start]
+   * is present, the bytes will be filled into [buffer] from at index [start],
    * otherwise index 0.  If [end] is present, the [end] - [start] bytes will be
    * read into [buffer], otherwise up to [buffer.length]. If [end] == [start]
    * nothing happends.
diff --git a/sdk/lib/io/file_system_entity.dart b/sdk/lib/io/file_system_entity.dart
index f39eafd..e0b22da 100644
--- a/sdk/lib/io/file_system_entity.dart
+++ b/sdk/lib/io/file_system_entity.dart
@@ -482,8 +482,8 @@
   /**
    * Returns a [bool] indicating whether this object's path is absolute.
    *
-   * On Windows, a path is absolute if it starts with \\ or a drive letter
-   * between a and z (upper or lower case) followed by :\ or :/.
+   * On Windows, a path is absolute if it starts with \\\\ or a drive letter
+   * between a and z (upper or lower case) followed by :\\ or :/.
    * On non-Windows, a path is absolute if it starts with /.
    */
   bool get isAbsolute {
@@ -624,7 +624,7 @@
   /**
    * Removes the final path component of a path, using the platform's
    * path separator to split the path.  Will not remove the root component
-   * of a Windows path, like "C:\" or "\\server_name\".
+   * of a Windows path, like "C:\\" or "\\\\server_name\\".
    * Ignores trailing path separators, and leaves no trailing path separators.
    */
   static String parentOf(String path) {
diff --git a/sdk/lib/js/dart2js/js_dart2js.dart b/sdk/lib/js/dart2js/js_dart2js.dart
index 4b3e4a6..61bf1da 100644
--- a/sdk/lib/js/dart2js/js_dart2js.dart
+++ b/sdk/lib/js/dart2js/js_dart2js.dart
@@ -707,7 +707,7 @@
   return Function.apply(callback, [self]..addAll(arguments));
 }
 
-Function /*=F*/ allowInterop/*<F extends Function>*/(Function /*=F*/ f) {
+Function/*=F*/ allowInterop/*<F extends Function>*/(Function/*=F*/ f) {
   if (JS('bool', 'typeof(#) == "function"', f)) {
     // Already supports interop, just use the existing function.
     return f;
diff --git a/sdk/lib/js/dartium/js_dartium.dart b/sdk/lib/js/dartium/js_dartium.dart
index 4d1d682..4ac1197 100644
--- a/sdk/lib/js/dartium/js_dartium.dart
+++ b/sdk/lib/js/dartium/js_dartium.dart
@@ -106,6 +106,11 @@
 final bool CHECK_JS_INVOCATIONS = true;
 
 final String _DART_RESERVED_NAME_PREFIX = r'JS$';
+// If a private class is defined to use @JS we need to inject a non-private
+// class with a name that will not cause collisions in the library so we can
+// make JSObject implement that interface even though it is in a different
+// library.
+final String escapePrivateClassPrefix = r'$JSImplClass23402893498';
 
 String _stripReservedNamePrefix(String name) =>
     name.startsWith(_DART_RESERVED_NAME_PREFIX)
@@ -133,6 +138,114 @@
 @Deprecated("Internal Use Only")
 Iterable<mirrors.ClassMirror> get jsInterfaceTypes => _jsInterfaceTypes;
 
+class _StringLiteralEscape {
+  // Character code constants.
+  static const int BACKSPACE = 0x08;
+  static const int TAB = 0x09;
+  static const int NEWLINE = 0x0a;
+  static const int CARRIAGE_RETURN = 0x0d;
+  static const int FORM_FEED = 0x0c;
+  static const int QUOTE = 0x22;
+  static const int CHAR_$ = 0x24;
+  static const int CHAR_0 = 0x30;
+  static const int BACKSLASH = 0x5c;
+  static const int CHAR_b = 0x62;
+  static const int CHAR_f = 0x66;
+  static const int CHAR_n = 0x6e;
+  static const int CHAR_r = 0x72;
+  static const int CHAR_t = 0x74;
+  static const int CHAR_u = 0x75;
+
+  final StringSink _sink;
+
+  _StringLiteralEscape(this._sink);
+
+  void writeString(String string) {
+    _sink.write(string);
+  }
+
+  void writeStringSlice(String string, int start, int end) {
+    _sink.write(string.substring(start, end));
+  }
+
+  void writeCharCode(int charCode) {
+    _sink.writeCharCode(charCode);
+  }
+
+  /// ('0' + x) or ('a' + x - 10)
+  static int hexDigit(int x) => x < 10 ? 48 + x : 87 + x;
+
+  /// Write, and suitably escape, a string's content as a JSON string literal.
+  void writeStringContent(String s) {
+    // Identical to JSON string literal escaping except that we also escape $.
+    int offset = 0;
+    final int length = s.length;
+    for (int i = 0; i < length; i++) {
+      int charCode = s.codeUnitAt(i);
+      if (charCode > BACKSLASH) continue;
+      if (charCode < 32) {
+        if (i > offset) writeStringSlice(s, offset, i);
+        offset = i + 1;
+        writeCharCode(BACKSLASH);
+        switch (charCode) {
+          case BACKSPACE:
+            writeCharCode(CHAR_b);
+            break;
+          case TAB:
+            writeCharCode(CHAR_t);
+            break;
+          case NEWLINE:
+            writeCharCode(CHAR_n);
+            break;
+          case FORM_FEED:
+            writeCharCode(CHAR_f);
+            break;
+          case CARRIAGE_RETURN:
+            writeCharCode(CHAR_r);
+            break;
+          default:
+            writeCharCode(CHAR_u);
+            writeCharCode(CHAR_0);
+            writeCharCode(CHAR_0);
+            writeCharCode(hexDigit((charCode >> 4) & 0xf));
+            writeCharCode(hexDigit(charCode & 0xf));
+            break;
+        }
+      } else if (charCode == QUOTE ||
+          charCode == BACKSLASH ||
+          charCode == CHAR_$) {
+        if (i > offset) writeStringSlice(s, offset, i);
+        offset = i + 1;
+        writeCharCode(BACKSLASH);
+        writeCharCode(charCode);
+      }
+    }
+    if (offset == 0) {
+      writeString(s);
+    } else if (offset < length) {
+      writeStringSlice(s, offset, length);
+    }
+  }
+
+  /**
+   * Serialize a [num], [String], [bool], [Null], [List] or [Map] value.
+   *
+   * Returns true if the value is one of these types, and false if not.
+   * If a value is both a [List] and a [Map], it's serialized as a [List].
+   */
+  bool writeStringLiteral(String str) {
+    writeString('"');
+    writeStringContent(str);
+    writeString('"');
+  }
+}
+
+String _escapeString(String str) {
+  StringBuffer output = new StringBuffer();
+  new _StringLiteralEscape(output)..writeStringLiteral(str);
+  return output.toString();
+}
+
 /// A collection of methods where all methods have the same name.
 /// This class is intended to optimize whether a specific invocation is
 /// appropritate for at least some of the methods in the collection.
@@ -183,8 +296,8 @@
         // Not enough positional arguments.
         return false;
       }
-      if (!_checkType(
-          invocation.positionalArguments[i], parameters[i].type)) return false;
+      if (!_checkType(invocation.positionalArguments[i], parameters[i].type))
+        return false;
     }
     if (invocation.namedArguments.isNotEmpty) {
       var startNamed;
@@ -203,8 +316,9 @@
         for (var j = startNamed; j < parameters.length; j++) {
           var p = parameters[j];
           if (p.simpleName == name) {
-            if (!_checkType(invocation.namedArguments[name],
-                parameters[j].type)) return false;
+            if (!_checkType(
+                invocation.namedArguments[name], parameters[j].type))
+              return false;
             match = true;
             break;
           }
@@ -340,7 +454,9 @@
 
 _getJsMemberName(mirrors.DeclarationMirror mirror) {
   var name = _getJsName(mirror);
-  return name == null || name.isEmpty ? _getDeclarationName(mirror) : name;
+  return name == null || name.isEmpty
+      ? _stripReservedNamePrefix(_getDeclarationName(mirror))
+      : name;
 }
 
 // TODO(jacobr): handle setters correctyl.
@@ -350,7 +466,7 @@
     assert(name.endsWith("="));
     name = name.substring(0, name.length - 1);
   }
-  return _stripReservedNamePrefix(name);
+  return name;
 }
 
 final _JS_LIBRARY_PREFIX = "js_library";
@@ -364,7 +480,7 @@
     ..write('${_JS_LIBRARY_PREFIX}.JsNative.getProperty(' * parts.length)
     ..write("${_JS_LIBRARY_PREFIX}.context");
   for (var p in parts) {
-    sb.write(", '$p')");
+    sb.write(", ${_escapeString(p)})");
   }
   return sb.toString();
 }
@@ -375,13 +491,13 @@
 String _accessJsPathSetter(String path) {
   var parts = path.split(".");
   return "${_JS_LIBRARY_PREFIX}.JsNative.setProperty(${_accessJsPathHelper(parts.getRange(0, parts.length - 1))
-      }, '${parts.last}', v)";
+      }, ${_escapeString(parts.last)}, v)";
 }
 
 String _accessJsPathCallMethodHelper(String path) {
   var parts = path.split(".");
   return "${_JS_LIBRARY_PREFIX}.JsNative.callMethod(${_accessJsPathHelper(parts.getRange(0, parts.length - 1))
-      }, '${parts.last}',";
+      }, ${_escapeString(parts.last)},";
 }
 
 @Deprecated("Internal Use Only")
@@ -402,8 +518,7 @@
   }
   sb.write(" ");
   if (declaration.isGetter) {
-    sb.write(
-        "get $name => ${_accessJsPath(path)};");
+    sb.write("get $name => ${_accessJsPath(path)};");
   } else if (declaration.isSetter) {
     sb.write("set $name(v) {\n"
         "  ${_JS_LIBRARY_PREFIX}.safeForTypedInterop(v);\n"
@@ -466,7 +581,8 @@
   return false;
 }
 
-List<String> _generateExternalMethods(List<String> libraryPaths, bool useCachedPatches) {
+List<String> _generateExternalMethods(
+    List<String> libraryPaths, bool useCachedPatches) {
   var staticCodegen = <String>[];
 
   if (libraryPaths.length == 0) {
@@ -484,7 +600,7 @@
         // the patches for this file.
         _generateLibraryCodegen(uri, library, staticCodegen);
       }
-    });    // End of library foreach
+    }); // End of library foreach
   } else {
     // Used to generate cached_patches.dart file for all IDL generated dart:
     // files to the WebKit DOM.
@@ -500,133 +616,140 @@
 }
 
 _generateLibraryCodegen(uri, library, staticCodegen) {
-    // Is it a dart generated library?
-    var dartLibrary = uri.scheme == 'dart';  
+  // Is it a dart generated library?
+  var dartLibrary = uri.scheme == 'dart';
 
-    var sb = new StringBuffer();
-    String jsLibraryName = _getJsName(library);
+  var sb = new StringBuffer();
+  String jsLibraryName = _getJsName(library);
 
-    // Sort by patch file by its declaration name.
-    var sortedDeclKeys = library.declarations.keys.toList();
-    sortedDeclKeys.sort((a, b) => mirrors.MirrorSystem.getName(a).compareTo(mirrors.MirrorSystem.getName(b)));
+  // Sort by patch file by its declaration name.
+  var sortedDeclKeys = library.declarations.keys.toList();
+  sortedDeclKeys.sort((a, b) => mirrors.MirrorSystem
+      .getName(a)
+      .compareTo(mirrors.MirrorSystem.getName(b)));
 
-    sortedDeclKeys.forEach((name) {
-      var declaration = library.declarations[name];
-      if (declaration is mirrors.MethodMirror) {
-        if ((_hasJsName(declaration) || jsLibraryName != null) &&
-            _isExternal(declaration)) {
-          addMemberHelper(declaration, jsLibraryName, sb);
-        }
-      } else if (declaration is mirrors.ClassMirror) {
-        mirrors.ClassMirror clazz = declaration;
-        var isDom = dartLibrary ? hasDomName(clazz) : false;
-        var isJsInterop = _hasJsName(clazz);
-        if (isDom || isJsInterop) {
-          // TODO(jacobr): verify class implements JavaScriptObject.
-          var className = mirrors.MirrorSystem.getName(clazz.simpleName);
-          var classNameImpl = '${className}Impl';
-          var sbPatch = new StringBuffer();
-          if (isJsInterop) {
-            String jsClassName = _getJsMemberName(clazz);
+  sortedDeclKeys.forEach((name) {
+    var declaration = library.declarations[name];
+    if (declaration is mirrors.MethodMirror) {
+      if ((_hasJsName(declaration) || jsLibraryName != null) &&
+          _isExternal(declaration)) {
+        addMemberHelper(declaration, jsLibraryName, sb);
+      }
+    } else if (declaration is mirrors.ClassMirror) {
+      mirrors.ClassMirror clazz = declaration;
+      var isDom = dartLibrary ? hasDomName(clazz) : false;
+      var isJsInterop = _hasJsName(clazz);
+      if (isDom || isJsInterop) {
+        // TODO(jacobr): verify class implements JavaScriptObject.
+        var className = mirrors.MirrorSystem.getName(clazz.simpleName);
+        bool isPrivate = className.startsWith('_');
+        var classNameImpl = '${className}Impl';
+        var sbPatch = new StringBuffer();
+        if (isJsInterop) {
+          String jsClassName = _getJsMemberName(clazz);
 
-            jsInterfaceTypes.add(clazz);
-            clazz.declarations.forEach((name, declaration) {
-              if (declaration is! mirrors.MethodMirror ||
-                  !_isExternal(declaration)) return;
-              if (declaration.isFactoryConstructor &&
-                  _isAnonymousClass(clazz)) {
-                sbPatch.write("  factory ${className}(");
-                int i = 0;
-                var args = <String>[];
-                for (var p in declaration.parameters) {
-                  args.add(mirrors.MirrorSystem.getName(p.simpleName));
-                  i++;
-                }
-                if (args.isNotEmpty) {
-                  sbPatch
-                    ..write('{')
-                    ..write(args
-                        .map((name) => '$name:${_UNDEFINED_VAR}')
-                        .join(", "))
-                    ..write('}');
-                }
-                sbPatch.write(") {\n"
-                    "    var ret = ${_JS_LIBRARY_PREFIX}.JsNative.newObject();\n");
-                i = 0;
-                for (var p in declaration.parameters) {
-                  assert(p.isNamed); // TODO(jacobr): throw.
-                  var name = args[i];
-                  var jsName = _stripReservedNamePrefix(
-                      mirrors.MirrorSystem.getName(p.simpleName));
-                  sbPatch.write("    if($name != ${_UNDEFINED_VAR}) {\n"
-                      "      ${_JS_LIBRARY_PREFIX}.safeForTypedInterop($name);\n"
-                      "      ${_JS_LIBRARY_PREFIX}.JsNative.setProperty(ret, '$jsName', $name);\n"
-                      "    }\n");
-                  i++;
-                }
+          jsInterfaceTypes.add(clazz);
+          clazz.declarations.forEach((name, declaration) {
+            if (declaration is! mirrors.MethodMirror ||
+                !_isExternal(declaration)) return;
+            if (declaration.isFactoryConstructor && _isAnonymousClass(clazz)) {
+              sbPatch.write("  factory ${className}(");
+              int i = 0;
+              var args = <String>[];
+              for (var p in declaration.parameters) {
+                args.add(mirrors.MirrorSystem.getName(p.simpleName));
+                i++;
+              }
+              if (args.isNotEmpty) {
+                sbPatch
+                  ..write('{')
+                  ..write(
+                      args.map((name) => '$name:${_UNDEFINED_VAR}').join(", "))
+                  ..write('}');
+              }
+              sbPatch.write(") {\n"
+                  "    var ret = ${_JS_LIBRARY_PREFIX}.JsNative.newObject();\n");
+              i = 0;
+              for (var p in declaration.parameters) {
+                assert(p.isNamed); // TODO(jacobr): throw.
+                var name = args[i];
+                var jsName = _stripReservedNamePrefix(
+                    mirrors.MirrorSystem.getName(p.simpleName));
+                sbPatch.write("    if($name != ${_UNDEFINED_VAR}) {\n"
+                    "      ${_JS_LIBRARY_PREFIX}.safeForTypedInterop($name);\n"
+                    "      ${_JS_LIBRARY_PREFIX}.JsNative.setProperty(ret, ${_escapeString(jsName)}, $name);\n"
+                    "    }\n");
+                i++;
+              }
 
-                sbPatch.write(
-                  "  return ret;"
+              sbPatch.write("  return ret;"
                   "}\n");
-              } else if (declaration.isConstructor ||
-                  declaration.isFactoryConstructor) {
-                sbPatch.write("  ");
-                addMemberHelper(
-                    declaration,
-                    (jsLibraryName != null && jsLibraryName.isNotEmpty)
-                        ? "${jsLibraryName}.${jsClassName}"
-                        : jsClassName,
-                    sbPatch,
-                    isStatic: true,
-                    memberName: className);
-              }
-            });   // End of clazz.declarations.forEach 
-
-            clazz.staticMembers.forEach((memberName, member) {
-              if (_isExternal(member)) {
-                sbPatch.write("  ");
-                addMemberHelper(
-                    member,
-                    (jsLibraryName != null && jsLibraryName.isNotEmpty)
-                        ? "${jsLibraryName}.${jsClassName}"
-                        : jsClassName,
-                    sbPatch,
-                    isStatic: true);
-              }
-            });
-          }
-          if (isDom) {
-            sbPatch.write("  static Type get instanceRuntimeType => ${classNameImpl};\n");
-          }
-          if (sbPatch.isNotEmpty) {
-            var typeVariablesClause = '';
-            if (!clazz.typeVariables.isEmpty) {
-              typeVariablesClause =
-                  '<${clazz.typeVariables.map((m) => mirrors.MirrorSystem.getName(m.simpleName)).join(',')}>';
+            } else if (declaration.isConstructor ||
+                declaration.isFactoryConstructor) {
+              sbPatch.write("  ");
+              addMemberHelper(
+                  declaration,
+                  (jsLibraryName != null && jsLibraryName.isNotEmpty)
+                      ? "${jsLibraryName}.${jsClassName}"
+                      : jsClassName,
+                  sbPatch,
+                  isStatic: true,
+                  memberName: className);
             }
-            sb.write("""
+          }); // End of clazz.declarations.forEach
+
+          clazz.staticMembers.forEach((memberName, member) {
+            if (_isExternal(member)) {
+              sbPatch.write("  ");
+              addMemberHelper(
+                  member,
+                  (jsLibraryName != null && jsLibraryName.isNotEmpty)
+                      ? "${jsLibraryName}.${jsClassName}"
+                      : jsClassName,
+                  sbPatch,
+                  isStatic: true);
+            }
+          });
+        }
+        if (isDom) {
+          sbPatch.write(
+              "  static Type get instanceRuntimeType => ${classNameImpl};\n");
+        }
+        if (isPrivate) {
+          sb.write("""
+class ${escapePrivateClassPrefix}${className} implements $className {}
+""");
+        }
+
+        if (sbPatch.isNotEmpty) {
+          var typeVariablesClause = '';
+          if (!clazz.typeVariables.isEmpty) {
+            typeVariablesClause =
+                '<${clazz.typeVariables.map((m) => mirrors.MirrorSystem.getName(m.simpleName)).join(',')}>';
+          }
+          sb.write("""
 patch class $className$typeVariablesClause {
 $sbPatch
 }
 """);
-            if (isDom) {
-              sb.write("""
+          if (isDom) {
+            sb.write("""
 class $classNameImpl$typeVariablesClause extends $className implements ${_JS_LIBRARY_PREFIX}.JSObjectInterfacesDom {
   ${classNameImpl}.internal_() : super.internal_();
   get runtimeType => $className;
   toString() => super.toString();
 }
 """);
-            }
           }
         }
       }
-    });
-    if (sb.isNotEmpty) {
-      staticCodegen
-        ..add(uri.toString())
-        ..add("${uri}_js_interop_patch.dart")
-        ..add("""
+    }
+  });
+  if (sb.isNotEmpty) {
+    staticCodegen
+      ..add(uri.toString())
+      ..add("${uri}_js_interop_patch.dart")
+      ..add("""
 import 'dart:js' as ${_JS_LIBRARY_PREFIX};
 
 /**
@@ -637,7 +760,7 @@
 
 ${sb}
 """);
-    }
+  }
 }
 
 // Remember the @JS type to compare annotation type.
@@ -667,11 +790,13 @@
  * signal to generate and emit the patches to stdout to be captured and put into
  * the file sdk/lib/js/dartium/cached_patches.dart
  */
-List<String> _generateInteropPatchFiles(List<String> libraryPaths, genCachedPatches) {
+List<String> _generateInteropPatchFiles(
+    List<String> libraryPaths, genCachedPatches) {
   // Cache the @JS Type.
   if (_atJsType == -1) setupJsTypeCache();
 
-  var ret = _generateExternalMethods(libraryPaths, genCachedPatches ? false : true);
+  var ret =
+      _generateExternalMethods(libraryPaths, genCachedPatches ? false : true);
   var libraryPrefixes = new Map<mirrors.LibraryMirror, String>();
   var prefixNames = new Set<String>();
   var sb = new StringBuffer();
@@ -705,8 +830,10 @@
     var isArray = typeMirror.isSubtypeOf(listMirror);
     var isFunction = typeMirror.isSubtypeOf(functionMirror);
     var isJSObject = typeMirror.isSubtypeOf(jsObjectMirror);
-    var fullName =
-        '${prefixName}.${mirrors.MirrorSystem.getName(typeMirror.simpleName)}';
+    var className = mirrors.MirrorSystem.getName(typeMirror.simpleName);
+    var isPrivate = className.startsWith('_');
+    if (isPrivate) className = '${escapePrivateClassPrefix}${className}';
+    var fullName = '${prefixName}.${className}';
     (isArray ? implementsArray : implements).add(fullName);
     if (!isArray && !isFunction && !isJSObject) {
       // For DOM classes we need to be a bit more conservative at tagging them
@@ -945,25 +1072,27 @@
 
 _lookupType(o, bool isCrossFrame, bool isElement) {
   try {
-   var type = html_common.lookupType(o, isElement);
-   var typeMirror = mirrors.reflectType(type);
-   var legacyInteropConvertToNative = typeMirror.isSubtypeOf(mirrors.reflectType(html.Blob)) ||
-        typeMirror.isSubtypeOf(mirrors.reflectType(html.Event)) ||
-        typeMirror.isSubtypeOf(mirrors.reflectType(indexed_db.KeyRange)) ||
-        typeMirror.isSubtypeOf(mirrors.reflectType(html.ImageData)) ||
-        typeMirror.isSubtypeOf(mirrors.reflectType(html.Node)) ||
+    var type = html_common.lookupType(o, isElement);
+    var typeMirror = mirrors.reflectType(type);
+    var legacyInteropConvertToNative =
+        typeMirror.isSubtypeOf(mirrors.reflectType(html.Blob)) ||
+            typeMirror.isSubtypeOf(mirrors.reflectType(html.Event)) ||
+            typeMirror.isSubtypeOf(mirrors.reflectType(indexed_db.KeyRange)) ||
+            typeMirror.isSubtypeOf(mirrors.reflectType(html.ImageData)) ||
+            typeMirror.isSubtypeOf(mirrors.reflectType(html.Node)) ||
 //        TypedData is removed from this list as it is converted directly
 //        rather than flowing through the interceptor code path.
 //        typeMirror.isSubtypeOf(mirrors.reflectType(typed_data.TypedData)) ||
-        typeMirror.isSubtypeOf(mirrors.reflectType(html.Window));
-    if (isCrossFrame && !typeMirror.isSubtypeOf(mirrors.reflectType(html.Window))) {
+            typeMirror.isSubtypeOf(mirrors.reflectType(html.Window));
+    if (isCrossFrame &&
+        !typeMirror.isSubtypeOf(mirrors.reflectType(html.Window))) {
       // TODO(jacobr): evaluate using the true cross frame Window class, etc.
       // as well as triggering that legacy JS Interop returns raw JsObject
       // instances.
       legacyInteropConvertToNative = false;
     }
     return [type, legacyInteropConvertToNative];
-  } catch (e) { }
+  } catch (e) {}
   return [JSObject.instanceRuntimeType, false];
 }
 
@@ -1045,7 +1174,8 @@
 
   static JsObject _jsify(object) native "JsObject_jsify";
 
-  static JsObject _fromBrowserObject(object) native "JsObject_fromBrowserObject";
+  static JsObject _fromBrowserObject(object)
+      native "JsObject_fromBrowserObject";
 
   /**
    * Returns the value associated with [property] from the proxied JavaScript
@@ -1088,8 +1218,7 @@
     return _identityEquality(this, other);
   }
 
-  static bool _identityEquality(a, b)
-      native "JsObject_identityEquality";
+  static bool _identityEquality(a, b) native "JsObject_identityEquality";
 
   /**
    * Returns `true` if the JavaScript object contains the specified property
@@ -1148,7 +1277,6 @@
   _callMethodLegacy(String name, List args) native "JsObject_callMethodLegacy";
 }
 
-
 /// Base class for all JS objects used through dart:html and typed JS interop.
 @Deprecated("Internal Use Only")
 class JSObject extends _JSObjectBase {
@@ -1185,8 +1313,8 @@
         if (matches != null) return ret;
         if (ret is Function ||
             (ret is JsFunction /* shouldn't be needed in the future*/) &&
-                _allowedMethods.containsKey(
-                    invocation.memberName)) return ret; // Warning: we have not bound "this"... we could type check on the Function but that is of little value in Dart.
+                _allowedMethods.containsKey(invocation.memberName))
+          return ret; // Warning: we have not bound "this"... we could type check on the Function but that is of little value in Dart.
         throwError();
       } else {
         // TODO(jacobr): should we throw if the JavaScript object doesn't have the property?
@@ -1195,8 +1323,8 @@
     } else if (invocation.isSetter) {
       if (CHECK_JS_INVOCATIONS) {
         var matches = _allowedSetters[invocation.memberName];
-        if (matches == null ||
-            !matches.checkInvocation(invocation)) throwError();
+        if (matches == null || !matches.checkInvocation(invocation))
+          throwError();
       }
       assert(name.endsWith("="));
       name = name.substring(0, name.length - 1);
@@ -1206,8 +1334,8 @@
       var matches;
       if (CHECK_JS_INVOCATIONS) {
         matches = _allowedMethods[invocation.memberName];
-        if (matches == null ||
-            !matches.checkInvocation(invocation)) throwError();
+        if (matches == null || !matches.checkInvocation(invocation))
+          throwError();
       }
       var ret = _callMethod(name, _buildArgs(invocation));
       if (CHECK_JS_INVOCATIONS) {
@@ -1287,7 +1415,8 @@
       a8 = _UNDEFINED,
       a9 = _UNDEFINED,
       a10 = _UNDEFINED]) {
-    return _apply(_stripUndefinedArgs([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10]));
+    return _apply(
+        _stripUndefinedArgs([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10]));
   }
 
   noSuchMethod(Invocation invocation) {
@@ -1299,7 +1428,8 @@
 
   dynamic _apply(List args, {thisArg}) native "JSFunction_apply";
 
-  static JSFunction _createWithThis(Function f) native "JSFunction_createWithThis";
+  static JSFunction _createWithThis(Function f)
+      native "JSFunction_createWithThis";
   static JSFunction _create(Function f) native "JSFunction_create";
 }
 
@@ -1314,11 +1444,16 @@
 
   static hasProperty(_JSObjectBase o, name) => o._hasProperty(name);
   static getProperty(_JSObjectBase o, name) => o._operator_getter(name);
-  static setProperty(_JSObjectBase o, name, value) => o._operator_setter(name, value);
-  static callMethod(_JSObjectBase o, String method, List args) => o._callMethod(method, args);
-  static instanceof(_JSObjectBase o, /*JsFunction|JSFunction*/ type) => o._instanceof(type);
-  static callConstructor0(_JSObjectBase constructor) native "JSNative_callConstructor0";
-  static callConstructor(_JSObjectBase constructor, List args) native "JSNative_callConstructor";
+  static setProperty(_JSObjectBase o, name, value) =>
+      o._operator_setter(name, value);
+  static callMethod(_JSObjectBase o, String method, List args) =>
+      o._callMethod(method, args);
+  static instanceof(_JSObjectBase o, /*JsFunction|JSFunction*/ type) =>
+      o._instanceof(type);
+  static callConstructor0(_JSObjectBase constructor)
+      native "JSNative_callConstructor0";
+  static callConstructor(_JSObjectBase constructor, List args)
+      native "JSNative_callConstructor";
 
   static toTypedObject(JsObject o) native "JSNative_toTypedObject";
 
@@ -1329,7 +1464,6 @@
   static JSFunction withThis(Function f) native "JsFunction_withThisNoWrap";
 }
 
-
 /**
  * Proxies a JavaScript Function object.
  */
@@ -1346,8 +1480,7 @@
    * Invokes the JavaScript function with arguments [args]. If [thisArg] is
    * supplied it is the value of `this` for the invocation.
    */
-  dynamic apply(List args, {thisArg}) =>
-      _apply(args, thisArg: thisArg);
+  dynamic apply(List args, {thisArg}) => _apply(args, thisArg: thisArg);
 
   dynamic _apply(List args, {thisArg}) native "JsFunction_apply";
 
@@ -1528,7 +1661,7 @@
 /// JavaScript. We may remove the need to call this method completely in the
 /// future if Dart2Js is refactored so that its function calling conventions
 /// are more compatible with JavaScript.
-Function /*=F*/ allowInterop/*<F extends Function>*/(Function /*=F*/ f) {
+Function/*=F*/ allowInterop/*<F extends Function>*/(Function/*=F*/ f) {
   if (f is JSFunction) {
     // The function is already a JSFunction... no need to do anything.
     return f;
@@ -1563,5 +1696,3 @@
     return ret;
   }
 }
-
-debugPrint(_) {}
\ No newline at end of file
diff --git a/sdk/lib/js_util/dart2js/js_util_dart2js.dart b/sdk/lib/js_util/dart2js/js_util_dart2js.dart
new file mode 100644
index 0000000..a587459
--- /dev/null
+++ b/sdk/lib/js_util/dart2js/js_util_dart2js.dart
@@ -0,0 +1,126 @@
+// 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.
+
+/// Utility methods to efficiently manipulate typed JSInterop objects in cases
+/// where the name to call is not known at runtime. You should only use these
+/// methods when the same effect cannot be achieved with @JS annotations.
+/// These methods would be extension methods on JSObject if Dart supported
+/// extension methods.
+library dart.js_util;
+
+import 'dart:_foreign_helper' show JS;
+import 'dart:collection' show HashMap;
+
+/// WARNING: performance of this method is much worse than other uitil
+/// methods in this library. Only use this method as a last resort.
+///
+/// Recursively converts a JSON-like collection of Dart objects to a
+/// collection of JavaScript objects and returns a [JsObject] proxy to it.
+///
+/// [object] must be a [Map] or [Iterable], the contents of which are also
+/// converted. Maps and Iterables are copied to a new JavaScript object.
+/// Primitives and other transferrable values are directly converted to their
+/// JavaScript type, and all other objects are proxied.
+jsify(object) {
+  if ((object is! Map) && (object is! Iterable)) {
+    throw new ArgumentError("object must be a Map or Iterable");
+  }
+  return _convertDataTree(object);
+}
+
+_convertDataTree(data) {
+  var _convertedObjects = new HashMap.identity();
+
+  _convert(o) {
+    if (_convertedObjects.containsKey(o)) {
+      return _convertedObjects[o];
+    }
+    if (o is Map) {
+      final convertedMap = JS('=Object', '{}');
+      _convertedObjects[o] = convertedMap;
+      for (var key in o.keys) {
+        JS('=Object', '#[#]=#', convertedMap, key, _convert(o[key]));
+      }
+      return convertedMap;
+    } else if (o is Iterable) {
+      var convertedList = [];
+      _convertedObjects[o] = convertedList;
+      convertedList.addAll(o.map(_convert));
+      return convertedList;
+    } else {
+      return o;
+    }
+  }
+
+  return _convert(data);
+}
+
+newObject() => JS('=Object', '{}');
+
+hasProperty(o, name) => JS('bool', '# in #', name, o);
+getProperty(o, name) => JS('Object', '#[#]', o, name);
+setProperty(o, name, value) => JS('', '#[#]=#', o, name, value);
+
+callMethod(o, String method, List args) =>
+    JS('Object', '#[#].apply(#, #)', o, method, o, args);
+
+instanceof(o, Function type) => JS('bool', '# instanceof #', o, type);
+callConstructor(Function constr, List arguments) {
+  if (arguments == null) {
+    return JS('Object', 'new #()', constr);
+  }
+
+  if (JS('bool', '# instanceof Array', arguments)) {
+    int argumentCount = JS('int', '#.length', arguments);
+    switch (argumentCount) {
+      case 0:
+        return JS('Object', 'new #()', constr);
+
+      case 1:
+        var arg0 = JS('', '#[0]', arguments);
+        return JS('Object', 'new #(#)', constr, arg0);
+
+      case 2:
+        var arg0 = JS('', '#[0]', arguments);
+        var arg1 = JS('', '#[1]', arguments);
+        return JS('Object', 'new #(#, #)', constr, arg0, arg1);
+
+      case 3:
+        var arg0 = JS('', '#[0]', arguments);
+        var arg1 = JS('', '#[1]', arguments);
+        var arg2 = JS('', '#[2]', arguments);
+        return JS('Object', 'new #(#, #, #)', constr, arg0, arg1, arg2);
+
+      case 4:
+        var arg0 = JS('', '#[0]', arguments);
+        var arg1 = JS('', '#[1]', arguments);
+        var arg2 = JS('', '#[2]', arguments);
+        var arg3 = JS('', '#[3]', arguments);
+        return JS(
+            'Object', 'new #(#, #, #, #)', constr, arg0, arg1, arg2, arg3);
+    }
+  }
+
+  // The following code solves the problem of invoking a JavaScript
+  // constructor with an unknown number arguments.
+  // First bind the constructor to the argument list using bind.apply().
+  // The first argument to bind() is the binding of 't', so add 'null' to
+  // the arguments list passed to apply().
+  // After that, use the JavaScript 'new' operator which overrides any binding
+  // of 'this' with the new instance.
+  var args = [null]..addAll(arguments);
+  var factoryFunction = JS('', '#.bind.apply(#, #)', constr, constr, args);
+  // Without this line, calling factoryFunction as a constructor throws
+  JS('String', 'String(#)', factoryFunction);
+  // This could return an UnknownJavaScriptObject, or a native
+  // object for which there is an interceptor
+  return JS('Object', 'new #()', factoryFunction);
+
+  // TODO(sra): Investigate:
+  //
+  //     var jsObj = JS('', 'Object.create(#.prototype)', constr);
+  //     JS('', '#.apply(#, #)', constr, jsObj,
+  //         []..addAll(arguments.map(_convertToJS)));
+  //     return _wrapToDart(jsObj);
+}
diff --git a/sdk/lib/js_util/dartium/js_util_dartium.dart b/sdk/lib/js_util/dartium/js_util_dartium.dart
new file mode 100644
index 0000000..5f1226d
--- /dev/null
+++ b/sdk/lib/js_util/dartium/js_util_dartium.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Utility methods to efficiently manipulate typed JSInterop objects in cases
+/// where the name to call is not known at runtime. You should only use these
+/// methods when the same effect cannot be achieved with @JS annotations.
+/// These methods would be extension methods on JSObject if Dart supported
+/// extension methods.
+library dart.js_util;
+
+import 'dart:js';
+
+/// WARNING: performance of this method is much worse than other uitil
+/// methods in this library. Only use this method as a last resort.
+///
+/// Recursively converts a JSON-like collection of Dart objects to a
+/// collection of JavaScript objects and returns a [JsObject] proxy to it.
+///
+/// [object] must be a [Map] or [Iterable], the contents of which are also
+/// converted. Maps and Iterables are copied to a new JavaScript object.
+/// Primitives and other transferrable values are directly converted to their
+/// JavaScript type, and all other objects are proxied.
+jsify(object) {
+  if ((object is! Map) && (object is! Iterable)) {
+    throw new ArgumentError("object must be a Map or Iterable");
+  }
+  return JsNative.jsify(object);
+}
+
+JSObject newObject() => JsNative.newObject();
+
+hasProperty(JSObject o, name) => JsNative.hasProperty(o, name);
+getProperty(JSObject o, name) => JsNative.getProperty(o, name);
+setProperty(JSObject o, name, value) => JsNative.setProperty(o, name, value);
+callMethod(JSObject o, String method, List args) => JsNative.callMethod(o, method, args);
+instanceof(JSObject o, Function type) => JsNative.instanceof(o, type);
+callConstructor(JSObject constructor, List args) => JsNative.callConstructor(constructor, args);
diff --git a/sdk/lib/vmservice/message.dart b/sdk/lib/vmservice/message.dart
index 08bb5b1..295214c 100644
--- a/sdk/lib/vmservice/message.dart
+++ b/sdk/lib/vmservice/message.dart
@@ -130,6 +130,7 @@
       case '_writeDevFSFile':
       case '_writeDevFSFiles':
       case '_readDevFSFile':
+      case '_spawnUri':
         return true;
       default:
         return false;
@@ -182,4 +183,4 @@
 
 external bool sendIsolateServiceMessage(SendPort sp, List m);
 external void sendRootServiceMessage(List m);
-external void sendObjectRootServiceMessage(List m);
\ No newline at end of file
+external void sendObjectRootServiceMessage(List m);
diff --git a/sdk/lib/vmservice/vmservice.dart b/sdk/lib/vmservice/vmservice.dart
index 4101023..df5642b 100644
--- a/sdk/lib/vmservice/vmservice.dart
+++ b/sdk/lib/vmservice/vmservice.dart
@@ -295,6 +295,37 @@
     return encodeSuccess(message);
   }
 
+  Future<String> _spawnUri(Message message) async {
+    var token = message.params['token'];
+    if (token == null) {
+      return encodeMissingParamError(message, 'token');
+    }
+    if (token is! String) {
+      return encodeInvalidParamError(message, 'token');
+    }
+    var uri = message.params['uri'];
+    if (uri == null) {
+      return encodeMissingParamError(message, 'uri');
+    }
+    if (uri is! String) {
+      return encodeInvalidParamError(message, 'uri');
+    }
+    var args = message.params['args'];
+    if (args != null &&
+        args is! List<String>) {
+      return encodeInvalidParamError(message, 'args');
+    }
+    var msg = message.params['message'];
+
+    Isolate.spawnUri(Uri.parse(uri), args, msg).then((isolate) {
+      _spawnUriNotify(isolate.controlPort, token);
+    }).catchError((e) {
+      _spawnUriNotify(e.toString(), token);
+    });
+
+    return encodeSuccess(message);
+  }
+
   // TODO(johnmccutchan): Turn this into a command line tool that uses the
   // service library.
   Future<String> _getCrashDump(Message message) async {
@@ -367,6 +398,9 @@
     if (message.method == 'streamCancel') {
       return _streamCancel(message);
     }
+    if (message.method == '_spawnUri') {
+      return _spawnUri(message);
+    }
     if (_devfs.shouldHandleMessage(message)) {
       return _devfs.handleMessage(message);
     }
@@ -404,3 +438,6 @@
 
 /// Get the bytes to the tar archive.
 external Uint8List _requestAssets();
+
+/// Notify the vm service that an isolate has been spawned via rpc.
+external void _spawnUriNotify(obj, String token);
diff --git a/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart b/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
index ac38baa..3dd54a8 100644
--- a/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
+++ b/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
@@ -354,7 +354,7 @@
 @DocsEditable()
 @DomName('ANGLEInstancedArrays')
 @Experimental() // untriaged
-@Native("ANGLEInstancedArrays")
+@Native("ANGLEInstancedArrays,ANGLE_instanced_arrays")
 class AngleInstancedArrays extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory AngleInstancedArrays._() { throw new UnsupportedError("Not supported"); }
@@ -469,7 +469,7 @@
 @DomName('WebGLCompressedTextureATC')
 // http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_atc/
 @Experimental()
-@Native("WebGLCompressedTextureATC")
+@Native("WebGLCompressedTextureATC,WEBGL_compressed_texture_atc")
 class CompressedTextureAtc extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory CompressedTextureAtc._() { throw new UnsupportedError("Not supported"); }
@@ -494,7 +494,7 @@
 @DocsEditable()
 @DomName('WebGLCompressedTextureETC1')
 @Experimental() // untriaged
-@Native("WebGLCompressedTextureETC1")
+@Native("WebGLCompressedTextureETC1,WEBGL_compressed_texture_etc1")
 class CompressedTextureETC1 extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory CompressedTextureETC1._() { throw new UnsupportedError("Not supported"); }
@@ -513,7 +513,7 @@
 @DomName('WebGLCompressedTexturePVRTC')
 // http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_pvrtc/
 @Experimental() // experimental
-@Native("WebGLCompressedTexturePVRTC")
+@Native("WebGLCompressedTexturePVRTC,WEBGL_compressed_texture_pvrtc")
 class CompressedTexturePvrtc extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory CompressedTexturePvrtc._() { throw new UnsupportedError("Not supported"); }
@@ -543,7 +543,7 @@
 @DomName('WebGLCompressedTextureS3TC')
 // http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/
 @Experimental() // experimental
-@Native("WebGLCompressedTextureS3TC")
+@Native("WebGLCompressedTextureS3TC,WEBGL_compressed_texture_s3tc")
 class CompressedTextureS3TC extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory CompressedTextureS3TC._() { throw new UnsupportedError("Not supported"); }
@@ -602,7 +602,7 @@
 @DomName('WebGLDebugRendererInfo')
 // http://www.khronos.org/registry/webgl/extensions/WEBGL_debug_renderer_info/
 @Experimental() // experimental
-@Native("WebGLDebugRendererInfo")
+@Native("WebGLDebugRendererInfo,WEBGL_debug_renderer_info")
 class DebugRendererInfo extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory DebugRendererInfo._() { throw new UnsupportedError("Not supported"); }
@@ -624,7 +624,7 @@
 @DomName('WebGLDebugShaders')
 // http://www.khronos.org/registry/webgl/extensions/WEBGL_debug_shaders/
 @Experimental() // experimental
-@Native("WebGLDebugShaders")
+@Native("WebGLDebugShaders,WEBGL_debug_shaders")
 class DebugShaders extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory DebugShaders._() { throw new UnsupportedError("Not supported"); }
@@ -642,7 +642,7 @@
 @DomName('WebGLDepthTexture')
 // http://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/
 @Experimental() // experimental
-@Native("WebGLDepthTexture")
+@Native("WebGLDepthTexture,WEBGL_depth_texture")
 class DepthTexture extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory DepthTexture._() { throw new UnsupportedError("Not supported"); }
@@ -660,7 +660,7 @@
 @DomName('WebGLDrawBuffers')
 // http://www.khronos.org/registry/webgl/specs/latest/
 @Experimental() // stable
-@Native("WebGLDrawBuffers")
+@Native("WebGLDrawBuffers,WEBGL_draw_buffers")
 class DrawBuffers extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory DrawBuffers._() { throw new UnsupportedError("Not supported"); }
@@ -814,7 +814,7 @@
 @DocsEditable()
 @DomName('EXTsRGB')
 @Experimental() // untriaged
-@Native("EXTsRGB")
+@Native("EXTsRGB,EXT_sRGB")
 class EXTsRgb extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory EXTsRgb._() { throw new UnsupportedError("Not supported"); }
@@ -847,7 +847,7 @@
 @DocsEditable()
 @DomName('EXTBlendMinMax')
 @Experimental() // untriaged
-@Native("EXTBlendMinMax")
+@Native("EXTBlendMinMax,EXT_blend_minmax")
 class ExtBlendMinMax extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory ExtBlendMinMax._() { throw new UnsupportedError("Not supported"); }
@@ -871,7 +871,7 @@
 @DomName('EXTFragDepth')
 // http://www.khronos.org/registry/webgl/extensions/EXT_frag_depth/
 @Experimental()
-@Native("EXTFragDepth")
+@Native("EXTFragDepth,EXT_frag_depth")
 class ExtFragDepth extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory ExtFragDepth._() { throw new UnsupportedError("Not supported"); }
@@ -884,7 +884,7 @@
 @DocsEditable()
 @DomName('EXTShaderTextureLOD')
 @Experimental() // untriaged
-@Native("EXTShaderTextureLOD")
+@Native("EXTShaderTextureLOD,EXT_shader_texture_lod")
 class ExtShaderTextureLod extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory ExtShaderTextureLod._() { throw new UnsupportedError("Not supported"); }
@@ -898,7 +898,7 @@
 @DomName('EXTTextureFilterAnisotropic')
 // http://www.khronos.org/registry/webgl/extensions/EXT_texture_filter_anisotropic/
 @Experimental()
-@Native("EXTTextureFilterAnisotropic")
+@Native("EXTTextureFilterAnisotropic,EXT_texture_filter_anisotropic")
 class ExtTextureFilterAnisotropic extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory ExtTextureFilterAnisotropic._() { throw new UnsupportedError("Not supported"); }
@@ -933,7 +933,7 @@
 @DomName('WebGLLoseContext')
 // http://www.khronos.org/registry/webgl/extensions/WEBGL_lose_context/
 @Experimental()
-@Native("WebGLLoseContext,WebGLExtensionLoseContext")
+@Native("WebGLLoseContext,WebGLExtensionLoseContext,WEBGL_lose_context")
 class LoseContext extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory LoseContext._() { throw new UnsupportedError("Not supported"); }
@@ -955,7 +955,7 @@
 @DomName('OESElementIndexUint')
 // http://www.khronos.org/registry/webgl/extensions/OES_element_index_uint/
 @Experimental() // experimental
-@Native("OESElementIndexUint")
+@Native("OESElementIndexUint,OES_element_index_uint")
 class OesElementIndexUint extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory OesElementIndexUint._() { throw new UnsupportedError("Not supported"); }
@@ -969,7 +969,7 @@
 @DomName('OESStandardDerivatives')
 // http://www.khronos.org/registry/webgl/extensions/OES_standard_derivatives/
 @Experimental() // experimental
-@Native("OESStandardDerivatives")
+@Native("OESStandardDerivatives,OES_standard_derivatives")
 class OesStandardDerivatives extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory OesStandardDerivatives._() { throw new UnsupportedError("Not supported"); }
@@ -987,7 +987,7 @@
 @DomName('OESTextureFloat')
 // http://www.khronos.org/registry/webgl/extensions/OES_texture_float/
 @Experimental() // experimental
-@Native("OESTextureFloat")
+@Native("OESTextureFloat,OES_texture_float")
 class OesTextureFloat extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory OesTextureFloat._() { throw new UnsupportedError("Not supported"); }
@@ -1001,7 +1001,7 @@
 @DomName('OESTextureFloatLinear')
 // http://www.khronos.org/registry/webgl/extensions/OES_texture_float_linear/
 @Experimental()
-@Native("OESTextureFloatLinear")
+@Native("OESTextureFloatLinear,OES_texture_float_linear")
 class OesTextureFloatLinear extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory OesTextureFloatLinear._() { throw new UnsupportedError("Not supported"); }
@@ -1015,7 +1015,7 @@
 @DomName('OESTextureHalfFloat')
 // http://www.khronos.org/registry/webgl/extensions/OES_texture_half_float/
 @Experimental() // experimental
-@Native("OESTextureHalfFloat")
+@Native("OESTextureHalfFloat,OES_texture_half_float")
 class OesTextureHalfFloat extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory OesTextureHalfFloat._() { throw new UnsupportedError("Not supported"); }
@@ -1033,7 +1033,7 @@
 @DomName('OESTextureHalfFloatLinear')
 // http://www.khronos.org/registry/webgl/extensions/OES_texture_half_float_linear/
 @Experimental()
-@Native("OESTextureHalfFloatLinear")
+@Native("OESTextureHalfFloatLinear,OES_texture_half_float_linear")
 class OesTextureHalfFloatLinear extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory OesTextureHalfFloatLinear._() { throw new UnsupportedError("Not supported"); }
@@ -1047,7 +1047,7 @@
 @DomName('OESVertexArrayObject')
 // http://www.khronos.org/registry/webgl/extensions/OES_vertex_array_object/
 @Experimental() // experimental
-@Native("OESVertexArrayObject")
+@Native("OESVertexArrayObject,OES_vertex_array_object")
 class OesVertexArrayObject extends Interceptor {
   // To suppress missing implicit constructor warnings.
   factory OesVertexArrayObject._() { throw new UnsupportedError("Not supported"); }
diff --git a/tests/co19/co19-analyzer2.status b/tests/co19/co19-analyzer2.status
index 1845277..12e0ed9 100644
--- a/tests/co19/co19-analyzer2.status
+++ b/tests/co19/co19-analyzer2.status
@@ -4,6 +4,15 @@
 
 [ $compiler == dart2analyzer ]
 
+# Trailing commas are now allowed by the language - issue #26644
+Language/Functions/Formal_Parameters/syntax_t12: MissingCompileTimeError
+Language/Functions/Formal_Parameters/syntax_t05: MissingCompileTimeError
+Language/Functions/Formal_Parameters/syntax_t04: MissingCompileTimeError
+Language/Expressions/Function_Invocation/Actual_Argument_List_Evaluation/syntax_t05: MissingCompileTimeError
+Language/Expressions/Method_Invocation/Ordinary_Invocation/syntax_t05: MissingCompileTimeError
+Language/Expressions/Method_Invocation/Ordinary_Invocation/syntax_t10: MissingCompileTimeError
+Language/Expressions/Method_Invocation/Super_Invocation/syntax_t05: MissingCompileTimeError
+
 WebPlatformTest/html/semantics/forms/the-textarea-element/textarea-type_t01: fail
 LayoutTests/fast/events/event-creation_t01: Skip # Roll 45 OverflowEvent removed
 LayoutTests/fast/forms/checkValidity-001_t01: fail
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status
index 80a6317..9d68884 100644
--- a/tests/co19/co19-co19.status
+++ b/tests/co19/co19-co19.status
@@ -76,7 +76,7 @@
 [ $runtime == dartium || $compiler == dart2js ]
 LibTest/async/Future/Future.delayed_A01_t02: Pass, Fail # Issue 15524
 
-[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == drt || $runtime == dartium || $runtime == dart_precompiled) ]
+[ ($compiler == none || $compiler == precompiler || $compiler == dart2appjit) && ($runtime == vm || $runtime == drt || $runtime == dartium || $runtime == dart_precompiled || $runtime == dart_app) ]
 # Optional trailing commas for argument and parameter lists added to language.
 # https://github.com/dart-lang/co19/issues/68
 Language/Expressions/Function_Invocation/Actual_Argument_List_Evaluation/syntax_t05: Fail, OK
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 2740bdf..d1662c9 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -3,6 +3,15 @@
 # BSD-style license that can be found in the LICENSE file.
 
 [ $compiler == dart2js ]
+# Trailing commas are now allowed by the language - issue #26644
+Language/Functions/Formal_Parameters/syntax_t12: MissingCompileTimeError
+Language/Functions/Formal_Parameters/syntax_t05: MissingCompileTimeError
+Language/Functions/Formal_Parameters/syntax_t04: MissingCompileTimeError
+Language/Expressions/Function_Invocation/Actual_Argument_List_Evaluation/syntax_t05: MissingCompileTimeError
+Language/Expressions/Method_Invocation/Ordinary_Invocation/syntax_t05: MissingCompileTimeError
+Language/Expressions/Method_Invocation/Ordinary_Invocation/syntax_t10: MissingCompileTimeError
+Language/Expressions/Method_Invocation/Super_Invocation/syntax_t05: MissingCompileTimeError
+
 Language/Classes/Constructors/Generative_Constructors/execution_of_a_superinitializer_t01: RuntimeError # compiler cancelled: cannot resolve type T
 Language/Classes/Constructors/Generative_Constructors/execution_of_a_superinitializer_t01: RuntimeError, OK # co19 issue 258
 Language/Classes/Constructors/Generative_Constructors/execution_of_an_initializer_t02: fail # Issue 13363
@@ -876,6 +885,7 @@
 LayoutTests/fast/css/counters/complex-before_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/css-escaped-identifier_t01: RuntimeError # co19 issue 14
 LayoutTests/fast/css/css-properties-case-insensitive_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/cssText-shorthand_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/css3-nth-tokens-style_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/csstext-of-content-string_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css/deprecated-flexbox-auto-min-size_t01: RuntimeError # Please triage this failure
@@ -890,11 +900,13 @@
 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-download-error_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/getPropertyValue-border_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
@@ -1028,6 +1040,7 @@
 LayoutTests/fast/dom/characterdata-api-arguments_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/click-method-on-html-element_t01: RuntimeError # Issue 25155
 LayoutTests/fast/dom/client-width-height-quirks_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/css-shorthand-common-value_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/custom/document-register-basic_t01: RuntimeError # Dartium JSInterop failure
 LayoutTests/fast/dom/custom/document-register-svg-extends_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/custom/element-names_t01: Pass, RuntimeError # Please triage this failure
@@ -1063,7 +1076,6 @@
 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
 LayoutTests/fast/dom/shadow/pseudoclass-update-disabled-option_t01: RuntimeError # Please triage this failure
@@ -1089,6 +1101,7 @@
 LayoutTests/fast/events/clipboard-dataTransferItemList_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/events/div-focus_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/events/document-elementFromPoint_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/events/event-attributes-after-exception_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/events/event-creation_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/events/event-listener-html-non-html-confusion_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/events/event-trace_t01: RuntimeError # Please triage this failure
@@ -1482,8 +1495,10 @@
 WebPlatformTest/html/semantics/document-metadata/styling/LinkStyle_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/embedded-content/media-elements/error-codes/error_t01: Skip # Times out. Please triage this failure
 WebPlatformTest/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/addTextTrack_t01: RuntimeError # Please triage this failure
+WebPlatformTest/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/kind_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/src_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/embedded-content/media-elements/interfaces/TextTrack/cues_t01: Skip # Times out. Please triage this failure
+WebPlatformTest/html/semantics/embedded-content/media-elements/interfaces/TextTrack/kind_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/embedded-content/media-elements/interfaces/TextTrack/mode_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/forms/attributes-common-to-form-controls/formaction_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/forms/textfieldselection/textfieldselection-setRangeText_t01: RuntimeError # Please triage this failure
@@ -1524,7 +1539,6 @@
 WebPlatformTest/html/semantics/selectors/pseudo-classes/enabled_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/selectors/pseudo-classes/focus_t01: Pass, RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/selectors/pseudo-classes/indeterminate_t01: RuntimeError # Please triage this failure
-WebPlatformTest/html/semantics/selectors/pseudo-classes/inrange-outofrange_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/selectors/pseudo-classes/link_t01: RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/selectors/pseudo-classes/valid-invalid_t01: Pass, RuntimeError # Please triage this failure
 WebPlatformTest/html/semantics/tabular-data/the-table-element/table-rows_t01: RuntimeError # Please triage this failure
@@ -1869,10 +1883,9 @@
 LayoutTests/fast/canvas/rgba-parsing_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/WebGLContextEvent_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/context-attributes-alpha-depth-stencil-antialias-t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/context-destroyed-crash_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/context-lost-restored_t01: RuntimeError # Please triage this failure
-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/context-destroyed-crash_t01: Pass, RuntimeError # Issue 26898
+LayoutTests/fast/canvas/webgl/context-lost-restored_t01: Pass, RuntimeError # Issue 26898
+LayoutTests/fast/canvas/webgl/context-lost_t01: Pass, RuntimeError # Issue 26898
 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
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 941a1d8..1af71e5 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -158,11 +158,13 @@
 Language/Metadata/*: SkipByDesign # Uses dart:mirrors
 Language/Expressions/Null/instance_of_class_null_t01: Skip # Uses dart:mirrors
 
+[ $noopt || $compiler == precompiler || $compiler == dart2appjit || $mode == product ]
+Language/Libraries_and_Scripts/Imports/deferred_import_t02: Skip # Eager loading
+Language/Libraries_and_Scripts/Imports/invalid_uri_deferred_t01: Skip # Eager loading
+Language/Libraries_and_Scripts/Imports/invalid_uri_deferred_t02: Skip # Eager loading
+
 [ $runtime == dart_precompiled || $runtime == dart_app ]
 LibTest/isolate/Isolate/spawnUri*: Skip # Isolate.spawnUri
-Language/Libraries_and_Scripts/Imports/invalid_uri_deferred_t01: CompileTimeError # spawnUri
-Language/Libraries_and_Scripts/Imports/invalid_uri_deferred_t02: RuntimeError # spawnUri
-Language/Libraries_and_Scripts/Imports/deferred_import_t02: RuntimeError # Unsupported
 
 [ $noopt || $compiler == precompiler ]
 LibTest/collection/ListBase/ListBase_class_A01_t02: Pass, Timeout
@@ -192,21 +194,41 @@
 LibTest/typed_data/Float32x4/operator_division_A01_t02: RuntimeError # Issue #26675
 
 [ $hot_reload ]
-LibTest/collection/DoubleLinkedQueue/DoubleLinkedQueue_class_A01_t01: Pass, Crash
-LibTest/collection/HashSet/HashSet_class_A01_t01: Crash
-LibTest/collection/IterableBase/IterableBase_class_A01_t02: Crash
-LibTest/collection/LinkedHashSet/LinkedHashSet_class_A01_t01: Crash
-LibTest/collection/LinkedList/iterator_current_A01_t01: Crash
-LibTest/collection/ListBase/ListBase_class_A01_t01: Pass, Timeout, Crash
+Language/Expressions/Property_Extraction/Ordinary_Member_Closurization/getter_closurization_t08: Pass, Fail # Closure identity
+Language/Expressions/Property_Extraction/Ordinary_Member_Closurization/method_identical_t03: Pass, Fail # Closure identity
+Language/Expressions/Property_Extraction/conditional_t05: Pass, Fail # Closure identity
+Language/Expressions/Assignment/prefix_object_t02: Crash # Requires deferred libraries
+Language/Expressions/Constants/constant_constructor_t03: Crash # Requires deferred libraries
+Language/Expressions/Constants/identifier_denotes_a_constant_t06: Crash # Requires deferred libraries
+Language/Expressions/Constants/identifier_denotes_a_constant_t07: Crash # Requires deferred libraries
+Language/Expressions/Constants/static_constant_t06: Crash # Requires deferred libraries
+Language/Expressions/Constants/static_constant_t07: Crash # Requires deferred libraries
+Language/Expressions/Constants/top_level_function_t04: Crash # Requires deferred libraries
+Language/Expressions/Constants/top_level_function_t05: Crash # Requires deferred libraries
+Language/Expressions/Instance_Creation/Const/deferred_type_t01: Crash # Requires deferred libraries
+Language/Expressions/Instance_Creation/Const/deferred_type_t02: Crash # Requires deferred libraries
+Language/Expressions/Instance_Creation/New/evaluation_t19: Crash # Requires deferred libraries
+Language/Expressions/Instance_Creation/New/evaluation_t20: Crash # Requires deferred libraries
+Language/Expressions/Property_Extraction/Anonymous_Constructor_Extraction/deferred_type_t01: Crash # Requires deferred libraries
+Language/Expressions/Property_Extraction/Named_Constructor_Extraction/deferred_type_t01: Crash # Requires deferred libraries
+Language/Expressions/Type_Cast/evaluation_t10: Crash # Requires deferred libraries
+Language/Expressions/Type_Test/evaluation_t10: Crash # Requires deferred libraries
+Language/Libraries_and_Scripts/Imports/deferred_import_t01: Crash # Requires deferred libraries
+Language/Libraries_and_Scripts/Imports/deferred_import_t02: Crash # Requires deferred libraries
+Language/Libraries_and_Scripts/Imports/invalid_uri_deferred_t01: Crash # Requires deferred libraries
+Language/Libraries_and_Scripts/Imports/invalid_uri_deferred_t02: Crash # Requires deferred libraries
+Language/Libraries_and_Scripts/Imports/invalid_uri_deferred_t03: Crash # Requires deferred libraries
+Language/Libraries_and_Scripts/Imports/static_type_t01: Crash # Requires deferred libraries
+Language/Types/Dynamic_Type_System/deferred_type_error_t01: Crash # Requires deferred libraries
+Language/Types/Static_Types/deferred_type_t01: Crash # Requires deferred libraries
+LibTest/async/DeferredLibrary/DeferredLibrary_A01_t01: Crash # Requires deferred libraries
+LibTest/collection/ListBase/ListBase_class_A01_t01: Pass, Timeout
 LibTest/collection/ListBase/ListBase_class_A01_t02: Pass, Timeout
-LibTest/collection/ListMixin/ListMixin_class_A01_t01: Pass, Timeout, Crash
+LibTest/collection/ListMixin/ListMixin_class_A01_t01: Pass, Timeout
 LibTest/collection/ListMixin/ListMixin_class_A01_t02: Pass, Timeout
-LibTest/collection/ListQueue/ListQueue_class_A01_t01: Pass, Crash
-LibTest/collection/Queue/Queue_class_A01_t01: Pass, Crash
-LibTest/core/List/List.from_A01_t01: Crash
-LibTest/core/List/List_class_A01_t01: Pass, Crash
-LibTest/core/List/List_class_A01_t02: Pass, Timeout, Crash
+LibTest/core/List/List_class_A01_t02: Pass, Timeout
 LibTest/core/Map/Map_class_A01_t04: Pass, Timeout
-LibTest/core/Set/IterableBase_A01_t01: Pass, Crash
 LibTest/core/Uri/Uri_A06_t03: Pass, Timeout
 LibTest/core/Uri/encodeQueryComponent_A01_t02: Pass, Timeout
+LibTest/isolate/Isolate/spawn_A01_t04: Pass, Timeout
+
diff --git a/tests/compiler/dart2js/async_await_js_transform_test.dart b/tests/compiler/dart2js/async_await_js_transform_test.dart
index 40c9eb6..e934d28 100644
--- a/tests/compiler/dart2js/async_await_js_transform_test.dart
+++ b/tests/compiler/dart2js/async_await_js_transform_test.dart
@@ -73,8 +73,6 @@
           v1 = 0;
           if (v1 < 0 || v1 >= v0.length)
             H.ioore(v0, v1);
-          else
-            ;
           v2 = 4;
           v3 = 2;
           P.print(v0[v1].call$2(v2, v3));
diff --git a/tests/compiler/dart2js/constant_expression_evaluate_test.dart b/tests/compiler/dart2js/constant_expression_evaluate_test.dart
index 49f3b51..3dd05ac 100644
--- a/tests/compiler/dart2js/constant_expression_evaluate_test.dart
+++ b/tests/compiler/dart2js/constant_expression_evaluate_test.dart
@@ -61,6 +61,8 @@
     const ConstantData('identical(0, 1)',
                        const { const {} : 'BoolConstant(false)' }),
     const ConstantData('"a" "b"', const { const {} : 'StringConstant("ab")' }),
+    const ConstantData(r'"${null}"',
+        const { const {} : 'StringConstant("null")' }),
     const ConstantData('identical',
         const { const {} : 'FunctionConstant(identical)' }),
     const ConstantData('true ? 0 : 1', const { const {} : 'IntConstant(0)' }),
@@ -79,6 +81,9 @@
         const { const {} :
           'MapConstant(<int, int>{IntConstant(0): IntConstant(1), '
                                  'IntConstant(2): IntConstant(3)})' }),
+    const ConstantData('const <int, int>{0: 1, 0: 2}',
+        const { const {} :
+        'MapConstant(<int, int>{IntConstant(0): IntConstant(2)})' }),
     const ConstantData(
         'const bool.fromEnvironment("foo", defaultValue: false)',
         const { const {} : 'BoolConstant(false)',
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index d4ef503..7b4c8f9 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -75,6 +75,7 @@
 serialization*: Slow, Pass
 uri_retention_test: Pass, Slow
 value_range_test: Pass, Slow
+jsinterop/world_test: Pass, Slow
 
 [ $mode == debug ]
 check_elements_invariants_test: Skip # Slow and only needs to be run in one
diff --git a/tests/compiler/dart2js/elide_callthrough_stub_test.dart b/tests/compiler/dart2js/elide_callthrough_stub_test.dart
new file mode 100644
index 0000000..bdb9667
--- /dev/null
+++ b/tests/compiler/dart2js/elide_callthrough_stub_test.dart
@@ -0,0 +1,60 @@
+// 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.
+
+// Check that calls through fields elide the call-through stub.  This
+// optimization is done by the simplifier, so inlining does not need to be
+// enabled.
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+import 'compiler_helper.dart';
+
+const String TEST1 = r'''
+class W {
+  final Function _fun;
+  W(this._fun);
+  foo(zzz) => _fun(zzz);   // this._fun$1(zzz) -->  this._fun.call$1(zzz)
+}
+add1(x) => x + 1;
+main() {
+  var w = new W(add1);
+  var x = w.foo(42);
+}
+''';
+
+const String TEST2 = r'''
+class W {
+  final Function __fun;
+  Function get _fun => __fun;
+  W(this.__fun);
+  foo(zzz) => _fun(zzz);   // this._fun$1(zzz) stays same.
+}
+add1(x) => x + 1;
+main() {
+  var w = new W(add1);
+  var x = w.foo(42);
+}
+''';
+
+main() {
+  asyncTest(() => compileAll(TEST1).then((generated) {
+    // Direct call through field.
+    Expect.isTrue(generated.contains(r'this._fun.call$1(zzz)'));
+    // No stub.
+    Expect.isFalse(generated.contains(r'_fun$1:'));
+    // No call to stub.
+    Expect.isFalse(generated.contains(r'_fun$1('));
+  }));
+
+  asyncTest(() => compileAll(TEST2).then((generated) {
+    // No call through field.
+    Expect.isFalse(generated.contains(r'this._fun.call$1(zzz)'));
+    // Call through stub.
+    Expect.isTrue(generated.contains(r'this._fun$1(zzz)'));
+    // Stub is generated.
+    Expect.isTrue(generated.contains(r'_fun$1:'));
+    // Call through getter (inside stub).
+    Expect.isTrue(generated.contains(r'get$_fun().call$1'));
+  }));
+}
diff --git a/tests/compiler/dart2js/exit_code_test.dart b/tests/compiler/dart2js/exit_code_test.dart
index ff419c7..bf3cdeb 100644
--- a/tests/compiler/dart2js/exit_code_test.dart
+++ b/tests/compiler/dart2js/exit_code_test.dart
@@ -150,10 +150,15 @@
 }
 
 class TestResolver extends ResolverTask {
-  TestResolver(TestCompiler compiler, ConstantCompiler constantCompiler)
-      : super(compiler, constantCompiler);
+  final TestCompiler compiler;
 
-  TestCompiler get compiler => super.compiler;
+  TestResolver(TestCompiler compiler, ConstantCompiler constantCompiler)
+      : this.compiler = compiler,
+        super(
+            compiler.resolution,
+            constantCompiler,
+            compiler.world,
+            compiler.measurer);
 
   void computeClassMembers(ClassElement element) {
     compiler.test('ResolverTask.computeClassMembers');
diff --git a/tests/compiler/dart2js/jsinterop/world_test.dart b/tests/compiler/dart2js/jsinterop/world_test.dart
new file mode 100644
index 0000000..f196b8e
--- /dev/null
+++ b/tests/compiler/dart2js/jsinterop/world_test.dart
@@ -0,0 +1,161 @@
+// 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 jsinterop.world_test;
+
+import 'package:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/common.dart';
+import 'package:compiler/src/elements/elements.dart'
+    show Element, ClassElement;
+import 'package:compiler/src/js_backend/js_backend.dart';
+import 'package:compiler/src/world.dart';
+import '../type_test_helper.dart';
+
+void main() {
+  asyncTest(() async {
+    await testClasses();
+  });
+}
+
+testClasses() async {
+  test(String mainSource,
+      {List<String> directlyInstantiated: const <String>[],
+       List<String> indirectlyInstantiated: const <String>[]}) async {
+    TypeEnvironment env = await TypeEnvironment.create(r"""
+@JS()
+class A {
+  get foo;
+
+  external A(var foo);
+}
+
+@JS()
+class B {
+  get foo;
+
+  external B(var foo);
+}
+
+@JS()
+@anonymous
+class C {
+  final foo;
+
+  external factory C({foo});
+}
+
+@JS()
+@anonymous
+class D {
+  final foo;
+
+  external factory D({foo});
+}
+
+class E {
+  final foo;
+
+  E(this.foo);
+}
+
+class F {
+  final foo;
+
+  F(this.foo);
+}
+
+newA() => new A(0);
+newB() => new B(1);
+newC() => new C(foo: 2);
+newD() => new D(foo: 3);
+newE() => new E(4);
+newF() => new F(5);
+""", mainSource: """
+import 'package:js/js.dart';
+
+$mainSource
+""", useMockCompiler: false);
+    Map<String, ClassElement> classEnvironment = <String, ClassElement>{};
+
+    ClassElement registerClass(ClassElement cls) {
+      classEnvironment[cls.name] = cls;
+      return cls;
+    }
+
+    ClassWorld world = env.compiler.world;
+    JavaScriptBackend backend = env.compiler.backend;
+    ClassElement Object_ = registerClass(env.compiler.coreClasses.objectClass);
+    ClassElement Interceptor =
+        registerClass(backend.helpers.jsInterceptorClass);
+    ClassElement JavaScriptObject =
+        registerClass(backend.helpers.jsJavaScriptObjectClass);
+    ClassElement A = registerClass(env.getElement('A'));
+    ClassElement B = registerClass(env.getElement('B'));
+    ClassElement C = registerClass(env.getElement('C'));
+    ClassElement D = registerClass(env.getElement('D'));
+    ClassElement E = registerClass(env.getElement('E'));
+    ClassElement F = registerClass(env.getElement('F'));
+
+    Expect.equals(Interceptor.superclass, Object_);
+    Expect.equals(JavaScriptObject.superclass, Interceptor);
+
+    Expect.equals(A.superclass, JavaScriptObject);
+    Expect.equals(B.superclass, JavaScriptObject);
+    Expect.equals(C.superclass, JavaScriptObject);
+    Expect.equals(D.superclass, JavaScriptObject);
+    Expect.equals(E.superclass, Object_);
+    Expect.equals(F.superclass, Object_);
+
+    for (String name in classEnvironment.keys) {
+      ClassElement cls = classEnvironment[name];
+      bool isInstantiated = false;
+      if (directlyInstantiated.contains(name)) {
+        isInstantiated = true;
+        Expect.isTrue(world.isDirectlyInstantiated(cls),
+            "Expected $name to be directly instantiated in `${mainSource}`:"
+                "\n${world.dump(cls)}");
+      }
+      if (indirectlyInstantiated.contains(name)) {
+        isInstantiated = true;
+        Expect.isTrue(world.isIndirectlyInstantiated(cls),
+            "Expected $name to be indirectly instantiated in `${mainSource}`:"
+                "\n${world.dump(cls)}");
+      }
+      if (!isInstantiated && (name != 'Object' && name != 'Interceptor')) {
+        Expect.isFalse(world.isInstantiated(cls),
+            "Expected $name to be uninstantiated in `${mainSource}`:"
+                "\n${world.dump(cls)}");
+      }
+    }
+  }
+
+  await test('main() {}');
+
+  await test('main() => newA();',
+      directlyInstantiated: ['A', 'B', 'C', 'D'],
+      indirectlyInstantiated: ['Object', 'Interceptor', 'JavaScriptObject']);
+
+  await test('main() => newB();',
+      directlyInstantiated: ['A', 'B', 'C', 'D'],
+      indirectlyInstantiated: ['Object', 'Interceptor', 'JavaScriptObject']);
+
+  await test('main() => newC();',
+      directlyInstantiated: ['A', 'B', 'C', 'D'],
+      indirectlyInstantiated: ['Object', 'Interceptor', 'JavaScriptObject']);
+
+  await test('main() => newD();',
+      directlyInstantiated: ['A', 'B', 'C', 'D'],
+      indirectlyInstantiated: ['Object', 'Interceptor', 'JavaScriptObject']);
+
+  await test('main() => newE();',
+      directlyInstantiated: ['E']);
+
+  await test('main() => newF();',
+      directlyInstantiated: ['F']);
+
+  await test('main() => [newD(), newE()];',
+      directlyInstantiated: ['A', 'B', 'C', 'D', 'E'],
+      indirectlyInstantiated: ['Object', 'Interceptor', 'JavaScriptObject']);
+}
diff --git a/tests/compiler/dart2js/memory_source_file_helper.dart b/tests/compiler/dart2js/memory_source_file_helper.dart
index 2efa806..c6b3b3c 100644
--- a/tests/compiler/dart2js/memory_source_file_helper.dart
+++ b/tests/compiler/dart2js/memory_source_file_helper.dart
@@ -33,7 +33,8 @@
     }
     String source = memorySourceFiles[resourceUri.path];
     if (source == null) {
-      return new Future.error(new Exception('No such file $resourceUri'));
+      return new Future.error(new Exception(
+          'No such memory file $resourceUri in ${memorySourceFiles.keys}'));
     }
     this.sourceFiles[resourceUri] =
         new StringSourceFile.fromUri(resourceUri, source);
@@ -48,7 +49,8 @@
     }
     String source = memorySourceFiles[resourceUri.path];
     if (source == null) {
-      throw new Exception('No such file $resourceUri');
+      throw new Exception(
+          'No such memory file $resourceUri in ${memorySourceFiles.keys}');
     }
     return new StringSourceFile.fromUri(resourceUri, source);
   }
diff --git a/tests/compiler/dart2js/minimal_resolution_test.dart b/tests/compiler/dart2js/minimal_resolution_test.dart
index 7de35a3..ddc1eaf 100644
--- a/tests/compiler/dart2js/minimal_resolution_test.dart
+++ b/tests/compiler/dart2js/minimal_resolution_test.dart
@@ -29,19 +29,17 @@
   bool isProcessed = enqueuer.isClassProcessed(cls);
   Expect.equals(expected, isInstantiated,
       'Unexpected instantiation state of class $cls.');
-  Expect.equals(expected, isProcessed,
-      'Unexpected processing state of class $cls.');
+  Expect.equals(
+      expected, isProcessed, 'Unexpected processing state of class $cls.');
 }
 
 analyze(String code,
-        {bool proxyConstant: false,
-         bool deprecatedClass: false}) async {
+    {bool proxyConstant: false, bool deprecatedClass: false}) async {
   CompilationResult result = await runCompiler(
-      memorySourceFiles: {'main.dart': code},
-      options: ['--analyze-only']);
+      memorySourceFiles: {'main.dart': code}, options: ['--analyze-only']);
   Expect.isTrue(result.isSuccess);
   Compiler compiler = result.compiler;
-  Expect.equals(proxyConstant, compiler.proxyConstant != null,
+  Expect.equals(proxyConstant, compiler.resolution.proxyConstant != null,
       "Unexpected computation of proxy constant.");
 
   checkInstantiated(
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 9c5b770..cf612bf 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -228,9 +228,9 @@
                                           ExecutableElement element) {
     ResolverVisitor visitor =
         new ResolverVisitor(
-            this,
+            this.resolution,
             element,
-            new ResolutionRegistry(this,
+            new ResolutionRegistry(this.backend,
                 new CollectingTreeElements(element)),
             scope: new MockTypeVariablesScope(
                 element.enclosingElement.buildScope()));
@@ -247,10 +247,10 @@
     Element mockElement = new MockElement(mainApp.entryCompilationUnit);
     ResolverVisitor visitor =
         new ResolverVisitor(
-            this,
+            this.resolution,
             mockElement,
             new ResolutionRegistry(
-                this, new CollectingTreeElements(mockElement)),
+                this.backend, new CollectingTreeElements(mockElement)),
             scope: mockElement.enclosingElement.buildScope());
     visitor.scope = new MethodScope(visitor.scope, mockElement);
     return visitor;
diff --git a/tests/compiler/dart2js/patch_test.dart b/tests/compiler/dart2js/patch_test.dart
index 2130f06..607fae9 100644
--- a/tests/compiler/dart2js/patch_test.dart
+++ b/tests/compiler/dart2js/patch_test.dart
@@ -1023,13 +1023,17 @@
     class A {
       A() : super();
       factory A.forward() = B.patchTarget;
+      factory A.forwardOne() = B.patchFactory;
       factory A.forwardTwo() = B.reflectBack;
+      factory A.forwardThree() = B.patchInjected;
     }
     class B extends A {
       B() : super();
       external B.patchTarget();
+      external factory B.patchFactory();
       external factory B.reflectBack();
       B.originTarget() : super();
+      external factory B.patchInjected();
     }
     """;
   String patch = """
@@ -1037,7 +1041,14 @@
       @patch
       B.patchTarget() : super();
       @patch
+      factory B.patchFactory() => new B.patchTarget();
+      @patch
       factory B.reflectBack() = B.originTarget;
+      @patch
+      factory B.patchInjected() = _C.injected;
+    }
+    class _C extends B {
+      _C.injected() : super.patchTarget();
     }
     """;
 
@@ -1048,14 +1059,28 @@
 
   ConstructorElement forward = clsA.lookupConstructor("forward");
   ConstructorElement target = forward.effectiveTarget;
-  Expect.isTrue(target.isPatch);
+  Expect.isTrue(target.isPatched, "Unexpected target $target for $forward");
+  Expect.isFalse(target.isPatch, "Unexpected target $target for $forward");
   Expect.equals("patchTarget", target.name);
 
+  ConstructorElement forwardOne = clsA.lookupConstructor("forwardOne");
+  target = forwardOne.effectiveTarget;
+  Expect.isFalse(forwardOne.isMalformed);
+  Expect.isFalse(target.isPatch, "Unexpected target $target for $forwardOne");
+  Expect.equals("patchFactory", target.name);
+
   ConstructorElement forwardTwo = clsA.lookupConstructor("forwardTwo");
   target = forwardTwo.effectiveTarget;
   Expect.isFalse(forwardTwo.isMalformed);
-  Expect.isFalse(target.isPatch);
+  Expect.isFalse(target.isPatch, "Unexpected target $target for $forwardTwo");
   Expect.equals("originTarget", target.name);
+
+  ConstructorElement forwardThree = clsA.lookupConstructor("forwardThree");
+  target = forwardThree.effectiveTarget;
+  Expect.isFalse(forwardThree.isMalformed);
+  Expect.isTrue(target.isInjected,
+      "Unexpected target $target for $forwardThree");
+  Expect.equals("injected", target.name);
 }
 
 Future testTypecheckPatchedMembers() async {
diff --git a/tests/compiler/dart2js/resolver_test.dart b/tests/compiler/dart2js/resolver_test.dart
index 2e1868a..5ddf37c 100644
--- a/tests/compiler/dart2js/resolver_test.dart
+++ b/tests/compiler/dart2js/resolver_test.dart
@@ -223,9 +223,11 @@
     FunctionElement fooA = classA.lookupLocalMember("foo");
 
     ResolverVisitor visitor = new ResolverVisitor(
-        compiler,
+        compiler.resolution,
         fooB,
-        new ResolutionRegistry(compiler, new CollectingTreeElements(fooB)),
+        new ResolutionRegistry(
+            compiler.backend,
+            new CollectingTreeElements(fooB)),
         scope: new MockTypeVariablesScope(classB.buildScope()));
     FunctionExpression node =
         (fooB as FunctionElementX).parseNode(compiler.parsingContext);
@@ -268,10 +270,10 @@
       ClassElement fooElement = compiler.mainApp.find("Foo");
       FunctionElement funElement = fooElement.lookupLocalMember("foo");
       ResolverVisitor visitor = new ResolverVisitor(
-          compiler,
+          compiler.resolution,
           funElement,
           new ResolutionRegistry(
-              compiler, new CollectingTreeElements(funElement)),
+              compiler.backend, new CollectingTreeElements(funElement)),
           scope: new MockTypeVariablesScope(fooElement.buildScope()));
       FunctionExpression function =
           (funElement as FunctionElementX).parseNode(compiler.parsingContext);
@@ -296,10 +298,10 @@
       ClassElement fooElement = compiler.mainApp.find("Foo");
       FunctionElement funElement = fooElement.lookupLocalMember("foo");
       ResolverVisitor visitor = new ResolverVisitor(
-          compiler,
+          compiler.resolution,
           funElement,
           new ResolutionRegistry(
-              compiler, new CollectingTreeElements(funElement)),
+              compiler.backend, new CollectingTreeElements(funElement)),
           scope: new MockTypeVariablesScope(fooElement.buildScope()));
       FunctionExpression function =
           (funElement as FunctionElementX).parseNode(compiler.parsingContext);
@@ -588,9 +590,11 @@
     compiler.parseScript("abstract class Bar {}");
 
     ResolverVisitor visitor = new ResolverVisitor(
-        compiler,
+        compiler.resolution,
         null,
-        new ResolutionRegistry(compiler, new CollectingTreeElements(null)));
+        new ResolutionRegistry(
+            compiler.backend,
+            new CollectingTreeElements(null)));
     compiler.resolveStatement("Foo bar;");
 
     ClassElement fooElement = compiler.mainApp.find('Foo');
@@ -707,9 +711,11 @@
     element = classElement.lookupConstructor(constructor);
     FunctionExpression tree = (element as FunctionElement).node;
     ResolverVisitor visitor = new ResolverVisitor(
-        compiler,
+        compiler.resolution,
         element,
-        new ResolutionRegistry(compiler, new CollectingTreeElements(element)),
+        new ResolutionRegistry(
+            compiler.backend,
+            new CollectingTreeElements(element)),
         scope: classElement.buildScope());
     new InitializerResolver(visitor, element, tree).resolveInitializers();
     visitor.visit(tree.body);
diff --git a/tests/compiler/dart2js/serialization/analysis1_test.dart b/tests/compiler/dart2js/serialization/analysis1_test.dart
index 1b8532e..e78f634 100644
--- a/tests/compiler/dart2js/serialization/analysis1_test.dart
+++ b/tests/compiler/dart2js/serialization/analysis1_test.dart
@@ -5,8 +5,8 @@
 library dart2js.serialization.analysis1_test;
 
 import 'analysis_test_helper.dart' as test;
-import 'test_data.dart';
+import 'test_helper.dart';
 
 main() {
-  test.main(['0', '${TESTS.length ~/ 2}']);
+  test.main(testSegment(1, test.SPLIT_COUNT, test.SKIP_COUNT));
 }
diff --git a/tests/compiler/dart2js/serialization/analysis2_test.dart b/tests/compiler/dart2js/serialization/analysis2_test.dart
index b13a6a3..05c3339 100644
--- a/tests/compiler/dart2js/serialization/analysis2_test.dart
+++ b/tests/compiler/dart2js/serialization/analysis2_test.dart
@@ -5,8 +5,8 @@
 library dart2js.serialization.analysis2_test;
 
 import 'analysis_test_helper.dart' as test;
-import 'test_data.dart';
+import 'test_helper.dart';
 
 main() {
-  test.main(['${TESTS.length ~/ 2}']);
+  test.main(testSegment(2, test.SPLIT_COUNT, test.SKIP_COUNT));
 }
diff --git a/tests/compiler/dart2js/serialization/analysis_test_helper.dart b/tests/compiler/dart2js/serialization/analysis_test_helper.dart
index 152972b..52b0271 100644
--- a/tests/compiler/dart2js/serialization/analysis_test_helper.dart
+++ b/tests/compiler/dart2js/serialization/analysis_test_helper.dart
@@ -14,6 +14,12 @@
 import 'helper.dart';
 import 'test_data.dart';
 
+/// Number of tests that are not part of the automatic test grouping.
+int SKIP_COUNT = 0;
+
+/// Number of groups that the [TESTS] are split into.
+int SPLIT_COUNT = 2;
+
 main(List<String> args) {
   asyncTest(() async {
     Arguments arguments = new Arguments.from(args);
@@ -27,6 +33,7 @@
     } else {
       await arguments.forEachTest(serializedData, TESTS, analyze);
     }
+    printMeasurementResults();
   });
 }
 
@@ -39,27 +46,27 @@
      bool verbose: false}) async {
   String testDescription = test != null ? test.name : '${entryPoint}';
   String id = index != null ? '$index: ' : '';
-  print('------------------------------------------------------------------');
-  print('analyze ${id}${testDescription}');
-  print('------------------------------------------------------------------');
-  DiagnosticCollector diagnosticCollector = new DiagnosticCollector();
-  await runCompiler(
-      entryPoint: entryPoint,
-      resolutionInputs: resolutionInputs,
-      memorySourceFiles: sourceFiles,
-      options: [Flags.analyzeOnly],
-      diagnosticHandler: diagnosticCollector);
-  if (test != null) {
-    Expect.equals(test.expectedErrorCount, diagnosticCollector.errors.length,
-        "Unexpected error count.");
-    Expect.equals(
-        test.expectedWarningCount,
-        diagnosticCollector.warnings.length,
-        "Unexpected warning count.");
-    Expect.equals(test.expectedHintCount, diagnosticCollector.hints.length,
-        "Unexpected hint count.");
-    Expect.equals(test.expectedInfoCount, diagnosticCollector.infos.length,
-        "Unexpected info count.");
-  }
+  String title = '${id}${testDescription}';
+  await measure(title, 'analyze', () async {
+    DiagnosticCollector diagnosticCollector = new DiagnosticCollector();
+    await runCompiler(
+        entryPoint: entryPoint,
+        resolutionInputs: resolutionInputs,
+        memorySourceFiles: sourceFiles,
+        options: [Flags.analyzeOnly],
+        diagnosticHandler: diagnosticCollector);
+    if (test != null) {
+      Expect.equals(test.expectedErrorCount, diagnosticCollector.errors.length,
+          "Unexpected error count.");
+      Expect.equals(
+          test.expectedWarningCount,
+          diagnosticCollector.warnings.length,
+          "Unexpected warning count.");
+      Expect.equals(test.expectedHintCount, diagnosticCollector.hints.length,
+          "Unexpected hint count.");
+      Expect.equals(test.expectedInfoCount, diagnosticCollector.infos.length,
+          "Unexpected info count.");
+    }
+  });
 }
 
diff --git a/tests/compiler/dart2js/serialization/compilation0_test.dart b/tests/compiler/dart2js/serialization/compilation0_test.dart
index 9df7f53..3e68dd2 100644
--- a/tests/compiler/dart2js/serialization/compilation0_test.dart
+++ b/tests/compiler/dart2js/serialization/compilation0_test.dart
@@ -5,8 +5,8 @@
 library dart2js.serialization.compilation0_test;
 
 import 'compilation_test_helper.dart' as test;
-import 'test_data.dart';
+import 'test_helper.dart';
 
 main() {
-  test.main(['0', '0']);
+  test.main(testSkipped(0, test.SKIP_COUNT));
 }
diff --git a/tests/compiler/dart2js/serialization/compilation1_test.dart b/tests/compiler/dart2js/serialization/compilation1_test.dart
index e3f6176..f59e0a0 100644
--- a/tests/compiler/dart2js/serialization/compilation1_test.dart
+++ b/tests/compiler/dart2js/serialization/compilation1_test.dart
@@ -5,8 +5,8 @@
 library dart2js.serialization.compilation1_test;
 
 import 'compilation_test_helper.dart' as test;
-import 'test_data.dart';
+import 'test_helper.dart';
 
 main() {
-  test.main(['1', '${TESTS.length ~/ 4}']);
+  test.main(testSegment(1, test.SPLIT_COUNT, test.SKIP_COUNT));
 }
diff --git a/tests/compiler/dart2js/serialization/compilation2_test.dart b/tests/compiler/dart2js/serialization/compilation2_test.dart
index 6141cbb..1947010 100644
--- a/tests/compiler/dart2js/serialization/compilation2_test.dart
+++ b/tests/compiler/dart2js/serialization/compilation2_test.dart
@@ -5,8 +5,8 @@
 library dart2js.serialization.compilation2_test;
 
 import 'compilation_test_helper.dart' as test;
-import 'test_data.dart';
+import 'test_helper.dart';
 
 main() {
-  test.main(['${TESTS.length ~/ 4}', '${2 * TESTS.length ~/ 4}']);
+  test.main(testSegment(2, test.SPLIT_COUNT, test.SKIP_COUNT));
 }
diff --git a/tests/compiler/dart2js/serialization/compilation3_test.dart b/tests/compiler/dart2js/serialization/compilation3_test.dart
index c168f22..90bc6ff 100644
--- a/tests/compiler/dart2js/serialization/compilation3_test.dart
+++ b/tests/compiler/dart2js/serialization/compilation3_test.dart
@@ -5,8 +5,8 @@
 library dart2js.serialization.compilation3_test;
 
 import 'compilation_test_helper.dart' as test;
-import 'test_data.dart';
+import 'test_helper.dart';
 
 main() {
-  test.main(['${2 * TESTS.length ~/ 4}', '${3 * TESTS.length ~/ 4}']);
+  test.main(testSegment(3, test.SPLIT_COUNT, test.SKIP_COUNT));
 }
diff --git a/tests/compiler/dart2js/serialization/compilation4_test.dart b/tests/compiler/dart2js/serialization/compilation4_test.dart
index 7e2dc7c..809f62b 100644
--- a/tests/compiler/dart2js/serialization/compilation4_test.dart
+++ b/tests/compiler/dart2js/serialization/compilation4_test.dart
@@ -5,8 +5,8 @@
 library dart2js.serialization.compilation4_test;
 
 import 'compilation_test_helper.dart' as test;
-import 'test_data.dart';
+import 'test_helper.dart';
 
 main() {
-  test.main(['${3 * TESTS.length ~/ 4}']);
+  test.main(testSegment(4, test.SPLIT_COUNT, test.SKIP_COUNT));
 }
diff --git a/tests/compiler/dart2js/serialization/compilation_1_test.dart b/tests/compiler/dart2js/serialization/compilation_1_test.dart
new file mode 100644
index 0000000..355cddc
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/compilation_1_test.dart
@@ -0,0 +1,12 @@
+// 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.compilation_1_test;
+
+import 'compilation_test_helper.dart' as test;
+import 'test_helper.dart';
+
+main() {
+  test.main(testSkipped(1, test.SKIP_COUNT));
+}
diff --git a/tests/compiler/dart2js/serialization/compilation_test_helper.dart b/tests/compiler/dart2js/serialization/compilation_test_helper.dart
index 9889bf4..5eda517 100644
--- a/tests/compiler/dart2js/serialization/compilation_test_helper.dart
+++ b/tests/compiler/dart2js/serialization/compilation_test_helper.dart
@@ -6,13 +6,19 @@
 
 import 'dart:async';
 import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/filenames.dart';
 import '../memory_compiler.dart';
 import 'helper.dart';
 import 'test_data.dart';
 import '../output_collector.dart';
 
+/// Number of tests that are not part of the automatic test grouping.
+int SKIP_COUNT = 2;
+
+/// Number of groups that the [TESTS] are split into.
+int SPLIT_COUNT = 4;
+
 main(List<String> args) {
   asyncTest(() async {
     Arguments arguments = new Arguments.from(args);
@@ -28,6 +34,7 @@
       Uri entryPoint = Uri.parse('memory:main.dart');
       await arguments.forEachTest(serializedData, TESTS, compile);
     }
+    printMeasurementResults();
   });
 }
 
@@ -40,16 +47,20 @@
      bool verbose: false}) async {
   String testDescription = test != null ? test.name : '${entryPoint}';
   String id = index != null ? '$index: ' : '';
-  print('------------------------------------------------------------------');
-  print('compile ${id}${testDescription}');
-  print('------------------------------------------------------------------');
+  String title = '${id}${testDescription}';
   OutputCollector outputCollector = new OutputCollector();
-  await runCompiler(
-      entryPoint: entryPoint,
-      memorySourceFiles: sourceFiles,
-      resolutionInputs: resolutionInputs,
-      options: [],
-      outputProvider: outputCollector);
+  await measure(title, 'compile', () async {
+    List<String> options = [];
+    if (test.checkedMode) {
+      options.add(Flags.enableCheckedMode);
+    }
+    await runCompiler(
+        entryPoint: entryPoint,
+        memorySourceFiles: sourceFiles,
+        resolutionInputs: resolutionInputs,
+        options: options,
+        outputProvider: outputCollector);
+  });
   if (verbose) {
     print(outputCollector.getOutput('', 'js'));
   }
diff --git a/tests/compiler/dart2js/serialization/equivalence_test.dart b/tests/compiler/dart2js/serialization/equivalence_test.dart
index 4e3d6e2..ee110f6 100644
--- a/tests/compiler/dart2js/serialization/equivalence_test.dart
+++ b/tests/compiler/dart2js/serialization/equivalence_test.dart
@@ -27,9 +27,34 @@
 
 const TEST_SOURCES = const <String, String>{
   'main.dart': '''
-import 'a.dart' deferred as a;
+import 'library.dart';
+import 'deferred_library.dart' deferred as prefix;
+
+asyncMethod() async {}
+asyncStarMethod() async* {}
+syncStarMethod() sync* {}
+get asyncGetter async {}
+get asyncStarGetter async* {}
+get syncStarGetter sync* {}
+
+genericMethod<T>() {}
+
+class Class1 {
+  factory Class1.deferred() = prefix.DeferredClass;
+  factory Class1.unresolved() = Unresolved;
+}
 ''',
-  'a.dart': '''
+  'deferred_library.dart': '''
+class DeferredClass {
+}
+
+get getter => 0;
+set setter(_) {}
+get property => 0;
+set property(_) {}
+''',
+  'library.dart': '''
+class Type {}
 ''',
 };
 
@@ -65,7 +90,7 @@
     CompilationResult result = await runCompiler(
         memorySourceFiles: sourceFiles,
         entryPoint: entryPoint,
-        options: [Flags.analyzeAll]);
+        options: [Flags.analyzeAll, Flags.genericMethodSyntax]);
     Compiler compiler = result.compiler;
     testSerialization(
         compiler.libraryLoader.libraries,
@@ -277,6 +302,9 @@
 
   void visit(Element element1, Element element2) {
     if (element1 == null && element2 == null) return;
+    if (element1 == null || element2 == null) {
+      throw currentCheck;
+    }
     element1 = element1.declaration;
     element2 = element2.declaration;
     if (element1 == element2) return;
@@ -333,22 +361,35 @@
         LibrarySerializer.getCompilationUnits(element1),
         LibrarySerializer.getCompilationUnits(element2));
 
-    checkElementListIdentities(
+    checkElementLists(
         element1, element2, 'imports',
         LibrarySerializer.getImports(element1),
         LibrarySerializer.getImports(element2));
-    checkElementListIdentities(
+    checkElementLists(
         element1, element2, 'exports', element1.exports, element2.exports);
 
+    List<Element> imported1 = LibrarySerializer.getImportedElements(element1);
+    List<Element> imported2 = LibrarySerializer.getImportedElements(element2);
     checkElementListIdentities(
-        element1, element2, 'importScope',
-        LibrarySerializer.getImportedElements(element1),
-        LibrarySerializer.getImportedElements(element2));
+        element1, element2, 'importScope', imported1, imported2);
 
     checkElementListIdentities(
         element1, element2, 'exportScope',
         LibrarySerializer.getExportedElements(element1),
         LibrarySerializer.getExportedElements(element2));
+
+    for (int index = 0; index < imported1.length; index++) {
+      checkImportsFor(element1, element2, imported1[index], imported2[index]);
+    }
+  }
+
+  void checkImportsFor(Element element1, Element element2,
+      Element import1, Element import2) {
+    List<ImportElement> imports1 = element1.library.getImportsFor(import1);
+    List<ImportElement> imports2 = element2.library.getImportsFor(import2);
+    checkElementListIdentities(
+        element1, element2, 'importsFor($import1/$import2)',
+        imports1, imports2);
   }
 
   @override
@@ -639,6 +680,8 @@
         element1, element2, 'functionSignature.orderedOptionalParameters',
         element1.functionSignature.orderedOptionalParameters,
         element2.functionSignature.orderedOptionalParameters);
+    checkTypeLists(element1, element2, 'typeVariables',
+        element1.typeVariables, element2.typeVariables);
   }
 
   @override
@@ -678,6 +721,17 @@
         element1.isRedirectingFactory, element2.isRedirectingFactory);
     checkElementIdentities(element1, element2, 'effectiveTarget',
         element1.effectiveTarget, element2.effectiveTarget);
+    if (element1.isRedirectingFactory) {
+      checkElementIdentities(element1, element2, 'immediateRedirectionTarget',
+          element1.immediateRedirectionTarget,
+          element2.immediateRedirectionTarget);
+      checkElementIdentities(element1, element2, 'redirectionDeferredPrefix',
+          element1.redirectionDeferredPrefix,
+          element2.redirectionDeferredPrefix);
+      check(element1, element2, 'isEffectiveTargetMalformed',
+          element1.isEffectiveTargetMalformed,
+          element2.isEffectiveTargetMalformed);
+    }
     checkElementIdentities(element1, element2, 'definingConstructor',
         element1.definingConstructor, element2.definingConstructor);
     check(
@@ -817,6 +871,19 @@
       checkElementProperties(element1, element2,
           'loadLibrary', element1.loadLibrary, element2.loadLibrary);
     }
-    // TODO(johnniwinther): Check members.
+    element1.forEachLocalMember((Element member1) {
+      String name = member1.name;
+      Element member2 = element2.lookupLocalMember(name);
+      checkElementIdentities(element1, element2, 'lookupLocalMember:$name',
+          member1, member2);
+      checkImportsFor(element1, element2, member1, member2);
+    });
+  }
+
+  @override
+  void visitErroneousElement(
+      ErroneousElement element1, ErroneousElement element2) {
+    check(element1, element2, 'messageKind',
+        element1.messageKind, element2.messageKind);
   }
 }
diff --git a/tests/compiler/dart2js/serialization/helper.dart b/tests/compiler/dart2js/serialization/helper.dart
index e5fab48..44d3786 100644
--- a/tests/compiler/dart2js/serialization/helper.dart
+++ b/tests/compiler/dart2js/serialization/helper.dart
@@ -77,9 +77,9 @@
       TestFunction testFunction) async {
     Uri entryPoint = Uri.parse('memory:main.dart');
     int first = start ?? 0;
-    int last = end ?? tests.length - 1;
+    int last = end ?? tests.length;
 
-    for (int index = first; index <= last; index++) {
+    for (int index = first; index < last; index++) {
       Test test = TESTS[index];
       List<SerializedData> dataList =
           await preserializeData(serializedData, test);
@@ -115,28 +115,28 @@
      bool verbose});
 
 Future<SerializedData> serializeDartCore(
-    {Arguments arguments: const Arguments()}) async {
-  Uri uri = Uri.parse('memory:${arguments.serializedDataFileName}');
-  print('------------------------------------------------------------------');
-  print('serialize dart:core');
-  print('------------------------------------------------------------------');
-  SerializedData serializedData;
-  if (arguments.loadSerializedData) {
-    File file = new File(arguments.serializedDataFileName);
-    if (file.existsSync()) {
-      print('Loading data from $file');
-      serializedData = new SerializedData(uri, file.readAsStringSync());
+    {Arguments arguments: const Arguments()}) {
+  return measure('dart:core', 'serialize', () async {
+    Uri uri = Uri.parse('memory:${arguments.serializedDataFileName}');
+    SerializedData serializedData;
+    if (arguments.loadSerializedData) {
+      File file = new File(arguments.serializedDataFileName);
+      if (file.existsSync()) {
+        print('Loading data from $file');
+        serializedData = new SerializedData(uri, file.readAsStringSync());
+      }
+    } else {
+      SerializationResult result =
+          await serialize(Uris.dart_core, dataUri: uri);
+      serializedData = result.serializedData;
     }
-  } else {
-    SerializationResult result = await serialize(Uris.dart_core, dataUri: uri);
-    serializedData = result.serializedData;
-  }
-  if (arguments.saveSerializedData) {
-    File file = new File(arguments.serializedDataFileName);
-    print('Saving data to $file');
-    file.writeAsStringSync(serializedData.data);
-  }
-  return serializedData;
+    if (arguments.saveSerializedData) {
+      File file = new File(arguments.serializedDataFileName);
+      print('Saving data to $file');
+      file.writeAsStringSync(serializedData.data);
+    }
+    return serializedData;
+  });
 }
 
 class SerializationResult {
@@ -153,16 +153,15 @@
   if (dataUri == null) {
     dataUri = Uri.parse('memory:${DEFAULT_DATA_FILE_NAME}');
   }
+  OutputCollector outputCollector = new OutputCollector();
   Compiler compiler = compilerFor(
-      options: [Flags.analyzeAll],
+      options: [Flags.resolveOnly],
       memorySourceFiles: memorySourceFiles,
-      resolutionInputs: resolutionInputs);
-  compiler.serialization.supportSerialization = true;
+      resolutionInputs: resolutionInputs,
+      outputProvider: outputCollector);
   await compiler.run(entryPoint);
-  BufferedEventSink sink = new BufferedEventSink();
-  compiler.serialization.serializeToSink(
-      sink, compiler.libraryLoader.libraries);
-  SerializedData serializedData = new SerializedData(dataUri, sink.text);
+  SerializedData serializedData = new SerializedData(
+      dataUri, outputCollector.getOutput('', 'data'));
   return new SerializationResult(compiler, serializedData);
 }
 
@@ -170,7 +169,10 @@
   final Uri uri;
   final String data;
 
-  SerializedData(this.uri, this.data);
+  SerializedData(this.uri, this.data) {
+    assert(uri != null);
+    assert(data != null);
+  }
 
   Map<String, String> toMemorySourceFiles([Map<String, String> input]) {
     Map<String, String> sourceFiles = <String, String>{};
@@ -201,13 +203,6 @@
   }
 }
 
-String extractSerializedData(
-    Compiler compiler, Iterable<LibraryElement> libraries) {
-  BufferedEventSink sink = new BufferedEventSink();
-  compiler.serialization.serializeToSink(sink, libraries);
-  return sink.text;
-}
-
 Future<List<SerializedData>> preserializeData(
     SerializedData serializedData, Test test) async {
   if (test == null ||
@@ -224,19 +219,76 @@
   if (test.unserializedSourceFiles != null) {
     sourceFiles.addAll(test.unserializedSourceFiles);
   }
+  OutputCollector outputCollector = new OutputCollector();
   Compiler compiler = compilerFor(
       memorySourceFiles: sourceFiles,
       resolutionInputs: serializedData.toUris(),
-      options: [Flags.analyzeOnly, Flags.analyzeMain]);
+      options: [Flags.resolveOnly],
+      outputProvider: outputCollector);
   compiler.librariesToAnalyzeWhenRun = uriList;
-  compiler.serialization.supportSerialization = true;
   await compiler.run(null);
   List<LibraryElement> libraries = <LibraryElement>[];
   for (Uri uri in uriList) {
     libraries.add(compiler.libraryLoader.lookupLibrary(uri));
   }
-  SerializedData additionalSerializedData =
-      new SerializedData(Uri.parse('memory:additional.data'),
-      extractSerializedData(compiler, libraries));
+  SerializedData additionalSerializedData = new SerializedData(
+      Uri.parse('memory:additional.data'),
+      outputCollector.getOutput('', 'data'));
   return <SerializedData>[serializedData, additionalSerializedData];
 }
+
+class MeasurementResult {
+  final String title;
+  final String taskTitle;
+  final int elapsedMilliseconds;
+
+  MeasurementResult(this.title, this.taskTitle, this.elapsedMilliseconds);
+}
+
+final List<MeasurementResult> measurementResults = <MeasurementResult>[];
+
+/// Print all store [measurementResults] grouped by title and sorted by
+/// decreasing execution time.
+void printMeasurementResults() {
+  Map<String, int> totals = <String, int>{};
+
+  for (MeasurementResult result in measurementResults) {
+    totals.putIfAbsent(result.title, () => 0);
+    totals[result.title] += result.elapsedMilliseconds;
+  }
+
+  List<String> sorted = totals.keys.toList();
+  sorted.sort((a, b) => -totals[a].compareTo(totals[b]));
+
+  int paddingLength = '${totals[sorted.first]}'.length;
+
+  String pad(int value) {
+    String text = '$value';
+    return '${' ' * (paddingLength - text.length)}$text';
+  }
+
+  print('================================================================');
+  print('Summary:');
+  for (String task in sorted) {
+    int time = totals[task];
+    print('${pad(time)}ms $task');
+  }
+
+  measurementResults.clear();
+}
+
+/// Measure execution of [task], print the result and store it in
+/// [measurementResults] for a summary.
+Future measure(String title, String taskTitle, Future task()) async {
+  Stopwatch stopwatch = new Stopwatch()..start();
+  print('================================================================');
+  print('$taskTitle: $title');
+  print('----------------------------------------------------------------');
+  var result = await task();
+  stopwatch.stop();
+  int elapsedMilliseconds = stopwatch.elapsedMilliseconds;
+  print('$taskTitle: $title: ${elapsedMilliseconds}ms');
+  measurementResults.add(
+      new MeasurementResult(title, taskTitle, elapsedMilliseconds));
+  return result;
+}
\ No newline at end of file
diff --git a/tests/compiler/dart2js/serialization/model0_test.dart b/tests/compiler/dart2js/serialization/model0_test.dart
new file mode 100644
index 0000000..c4ef537
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/model0_test.dart
@@ -0,0 +1,12 @@
+// 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.model0_test;
+
+import 'model_test_helper.dart' as test;
+import 'test_helper.dart';
+
+main() {
+  test.main(testSkipped(0, test.SKIP_COUNT));
+}
diff --git a/tests/compiler/dart2js/serialization/model1_test.dart b/tests/compiler/dart2js/serialization/model1_test.dart
index 9582274..aec8489 100644
--- a/tests/compiler/dart2js/serialization/model1_test.dart
+++ b/tests/compiler/dart2js/serialization/model1_test.dart
@@ -5,8 +5,8 @@
 library dart2js.serialization.model1_test;
 
 import 'model_test_helper.dart' as test;
-import 'test_data.dart';
+import 'test_helper.dart';
 
 main() {
-  test.main(['0', '${TESTS.length ~/ 2}']);
+  test.main(testSegment(1, test.SPLIT_COUNT, test.SKIP_COUNT));
 }
diff --git a/tests/compiler/dart2js/serialization/model2_test.dart b/tests/compiler/dart2js/serialization/model2_test.dart
index 369e4a1..8f02334 100644
--- a/tests/compiler/dart2js/serialization/model2_test.dart
+++ b/tests/compiler/dart2js/serialization/model2_test.dart
@@ -5,8 +5,8 @@
 library dart2js.serialization.model2_test;
 
 import 'model_test_helper.dart' as test;
-import 'test_data.dart';
+import 'test_helper.dart';
 
 main() {
-  test.main(['${TESTS.length ~/ 2}']);
+  test.main(testSegment(2, test.SPLIT_COUNT, test.SKIP_COUNT));
 }
diff --git a/tests/compiler/dart2js/serialization/model3_test.dart b/tests/compiler/dart2js/serialization/model3_test.dart
new file mode 100644
index 0000000..d3a2ff1
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/model3_test.dart
@@ -0,0 +1,12 @@
+// 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.model3_test;
+
+import 'model_test_helper.dart' as test;
+import 'test_helper.dart';
+
+main() {
+  test.main(testSegment(3, test.SPLIT_COUNT, test.SKIP_COUNT));
+}
diff --git a/tests/compiler/dart2js/serialization/model4_test.dart b/tests/compiler/dart2js/serialization/model4_test.dart
new file mode 100644
index 0000000..5871fc2
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/model4_test.dart
@@ -0,0 +1,12 @@
+// 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.model4_test;
+
+import 'model_test_helper.dart' as test;
+import 'test_helper.dart';
+
+main() {
+  test.main(testSegment(4, test.SPLIT_COUNT, test.SKIP_COUNT));
+}
diff --git a/tests/compiler/dart2js/serialization/model_1_test.dart b/tests/compiler/dart2js/serialization/model_1_test.dart
new file mode 100644
index 0000000..e74bd17
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/model_1_test.dart
@@ -0,0 +1,12 @@
+// 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.model_1_test;
+
+import 'model_test_helper.dart' as test;
+import 'test_helper.dart';
+
+main() {
+  test.main(testSkipped(1, test.SKIP_COUNT));
+}
diff --git a/tests/compiler/dart2js/serialization/model_test_helper.dart b/tests/compiler/dart2js/serialization/model_test_helper.dart
index 2c6d861..daf68663 100644
--- a/tests/compiler/dart2js/serialization/model_test_helper.dart
+++ b/tests/compiler/dart2js/serialization/model_test_helper.dart
@@ -10,7 +10,9 @@
 import 'package:expect/expect.dart';
 import 'package:compiler/src/closure.dart';
 import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/common.dart';
 import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/deferred_load.dart';
 import 'package:compiler/src/elements/elements.dart';
 import 'package:compiler/src/filenames.dart';
 import 'package:compiler/src/js_backend/js_backend.dart';
@@ -22,6 +24,12 @@
 import 'test_data.dart';
 import 'test_helper.dart';
 
+/// Number of tests that are not part of the automatic test grouping.
+int SKIP_COUNT = 2;
+
+/// Number of groups that the [TESTS] are split into.
+int SPLIT_COUNT = 4;
+
 main(List<String> args) {
   asyncTest(() async {
     Arguments arguments = new Arguments.from(args);
@@ -29,13 +37,24 @@
         await serializeDartCore(arguments: arguments);
     if (arguments.filename != null) {
       Uri entryPoint = Uri.base.resolve(nativeToUriPath(arguments.filename));
+      SerializationResult result = await measure(
+          '${entryPoint}', 'serialize', () {
+        return serialize(
+            entryPoint,
+            memorySourceFiles: serializedData.toMemorySourceFiles(),
+            resolutionInputs: serializedData.toUris(),
+            dataUri: Uri.parse('memory:test.data'));
+      });
       await checkModels(entryPoint,
-          sourceFiles: serializedData.toMemorySourceFiles(),
-          resolutionInputs: serializedData.toUris());
+          sourceFiles: serializedData.toMemorySourceFiles(
+              result.serializedData.toMemorySourceFiles()),
+          resolutionInputs: serializedData.toUris(
+              result.serializedData.toUris()));
     } else {
       Uri entryPoint = Uri.parse('memory:main.dart');
       await arguments.forEachTest(serializedData, TESTS, checkModels);
     }
+    printMeasurementResults();
   });
 }
 
@@ -48,88 +67,101 @@
      bool verbose: false}) async {
   String testDescription = test != null ? test.name : '${entryPoint}';
   String id = index != null ? '$index: ' : '';
-  print('------------------------------------------------------------------');
-  print('compile normal ${id}${testDescription}');
-  print('------------------------------------------------------------------');
-  Compiler compilerNormal = compilerFor(
-      memorySourceFiles: sourceFiles,
-      options: [Flags.analyzeOnly]);
-  compilerNormal.resolution.retainCachesForTesting = true;
-  await compilerNormal.run(entryPoint);
-  compilerNormal.phase = Compiler.PHASE_DONE_RESOLVING;
-  compilerNormal.world.populate();
-  compilerNormal.backend.onResolutionComplete();
+  String title = '${id}${testDescription}';
+  Compiler compilerNormal = await measure(
+      title, 'compile normal', () async {
+    Compiler compilerNormal = compilerFor(
+        memorySourceFiles: sourceFiles,
+        options: [Flags.analyzeOnly]);
+    compilerNormal.resolution.retainCachesForTesting = true;
+    await compilerNormal.run(entryPoint);
+    compilerNormal.phase = Compiler.PHASE_DONE_RESOLVING;
+    compilerNormal.world.populate();
+    compilerNormal.backend.onResolutionComplete();
+    compilerNormal.deferredLoadTask.onResolutionComplete(
+        compilerNormal.mainFunction);
+    return compilerNormal;
+  });
 
-  print('------------------------------------------------------------------');
-  print('compile deserialized ${id}${testDescription}');
-  print('------------------------------------------------------------------');
-  Compiler compilerDeserialized = compilerFor(
-      memorySourceFiles: sourceFiles,
-      resolutionInputs: resolutionInputs,
-      options: [Flags.analyzeOnly]);
-  compilerDeserialized.resolution.retainCachesForTesting = true;
-  await compilerDeserialized.run(entryPoint);
-  compilerDeserialized.phase = Compiler.PHASE_DONE_RESOLVING;
-  compilerDeserialized.world.populate();
-  compilerDeserialized.backend.onResolutionComplete();
+  Compiler compilerDeserialized = await measure(
+      title, 'compile deserialized', () async {
+    Compiler compilerDeserialized = compilerFor(
+        memorySourceFiles: sourceFiles,
+        resolutionInputs: resolutionInputs,
+        options: [Flags.analyzeOnly]);
+    compilerDeserialized.resolution.retainCachesForTesting = true;
+    await compilerDeserialized.run(entryPoint);
+    compilerDeserialized.phase = Compiler.PHASE_DONE_RESOLVING;
+    compilerDeserialized.world.populate();
+    compilerDeserialized.backend.onResolutionComplete();
+    compilerDeserialized.deferredLoadTask.onResolutionComplete(
+        compilerDeserialized.mainFunction);
+    return compilerDeserialized;
+  });
 
-  checkAllImpacts(
-      compilerNormal, compilerDeserialized,
-      verbose: verbose);
+  return measure(title, 'check models', () async {
+    checkAllImpacts(
+        compilerNormal, compilerDeserialized,
+        verbose: verbose);
 
-  checkSets(
-      compilerNormal.resolverWorld.directlyInstantiatedClasses,
-      compilerDeserialized.resolverWorld.directlyInstantiatedClasses,
-      "Directly instantiated classes mismatch",
-      areElementsEquivalent,
-      verbose: verbose);
+    checkSets(
+        compilerNormal.resolverWorld.directlyInstantiatedClasses,
+        compilerDeserialized.resolverWorld.directlyInstantiatedClasses,
+        "Directly instantiated classes mismatch",
+        areElementsEquivalent,
+        verbose: verbose);
 
-  checkSets(
-      compilerNormal.resolverWorld.instantiatedTypes,
-      compilerDeserialized.resolverWorld.instantiatedTypes,
-      "Instantiated types mismatch",
-      areTypesEquivalent,
-      verbose: verbose);
+    checkSets(
+        compilerNormal.resolverWorld.instantiatedTypes,
+        compilerDeserialized.resolverWorld.instantiatedTypes,
+        "Instantiated types mismatch",
+        areTypesEquivalent,
+        verbose: verbose);
 
-  checkSets(
-      compilerNormal.resolverWorld.isChecks,
-      compilerDeserialized.resolverWorld.isChecks,
-      "Is-check mismatch",
-      areTypesEquivalent,
-      verbose: verbose);
+    checkSets(
+        compilerNormal.resolverWorld.isChecks,
+        compilerDeserialized.resolverWorld.isChecks,
+        "Is-check mismatch",
+        areTypesEquivalent,
+        verbose: verbose);
 
-  checkSets(
-      compilerNormal.enqueuer.resolution.processedElements,
-      compilerDeserialized.enqueuer.resolution.processedElements,
-      "Processed element mismatch",
-      areElementsEquivalent,
-      onSameElement: (a, b) {
-        checkElements(
-            compilerNormal, compilerDeserialized, a, b, verbose: verbose);
-      },
-      verbose: verbose);
+    checkSets(
+        compilerNormal.enqueuer.resolution.processedElements,
+        compilerDeserialized.enqueuer.resolution.processedElements,
+        "Processed element mismatch",
+        areElementsEquivalent,
+        onSameElement: (a, b) {
+          checkElements(
+              compilerNormal, compilerDeserialized, a, b, verbose: verbose);
+        },
+        verbose: verbose);
 
-  checkClassHierarchyNodes(
-      compilerNormal,
-      compilerDeserialized,
-      compilerNormal.world.getClassHierarchyNode(
-          compilerNormal.coreClasses.objectClass),
-      compilerDeserialized.world.getClassHierarchyNode(
-          compilerDeserialized.coreClasses.objectClass),
-      verbose: verbose);
+    checkClassHierarchyNodes(
+        compilerNormal,
+        compilerDeserialized,
+        compilerNormal.world.getClassHierarchyNode(
+            compilerNormal.coreClasses.objectClass),
+        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");
+    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");
+    Expect.equals(
+        compilerNormal.deferredLoadTask.isProgramSplit,
+        compilerDeserialized.deferredLoadTask.isProgramSplit,
+        "isProgramSplit mismatch");
+  });
 }
 
 void checkElements(
@@ -182,6 +214,28 @@
         "$element1.variablesUsedInTryOrGenerator",
         areLocalsEquivalent,
         verbose: verbose);
+    if (element1 is MemberElement && element2 is MemberElement) {
+      MemberElement member1 = element1.implementation;
+      MemberElement member2 = element2.implementation;
+      checkSets(
+          member1.nestedClosures,
+          member2.nestedClosures,
+          "$member1.nestedClosures",
+          areElementsEquivalent,
+          verbose: verbose,
+          onSameElement: (a, b) {
+            LocalFunctionElement localFunction1 = a.expression;
+            LocalFunctionElement localFunction2 = b.expression;
+            checkElementIdentities(
+                localFunction1, localFunction2,
+                'enclosingClass',
+                localFunction1.enclosingClass, localFunction2.enclosingClass);
+            testResolvedAstEquivalence(
+                localFunction1.resolvedAst,
+                localFunction2.resolvedAst,
+                const CheckStrategy());
+          });
+    }
   }
   JavaScriptBackend backend1 = compiler1.backend;
   JavaScriptBackend backend2 = compiler2.backend;
@@ -189,6 +243,8 @@
       backend1.inlineCache.getCurrentCacheDecisionForTesting(element1),
       backend2.inlineCache.getCurrentCacheDecisionForTesting(element2),
       "Inline cache decision mismatch for $element1 vs $element2");
+
+  checkOutputUnits(compiler1, compiler2, element1, element2);
 }
 
 void checkMixinUses(
@@ -302,4 +358,19 @@
     return '(${node.runtimeType}) ${text.substring(0, 37)}...';
   }
   return '(${node.runtimeType}) $text';
+}
+
+void checkOutputUnits(Compiler compiler1, Compiler compiler2, Element element1,
+    Element element2) {
+  OutputUnit outputUnit1 =
+      compiler1.deferredLoadTask.outputUnitForElement(element1);
+  OutputUnit outputUnit2 =
+      compiler2.deferredLoadTask.outputUnitForElement(element2);
+  check(outputUnit1, outputUnit2,
+      'OutputUnit.isMainOutput for $element1 vs $element2',
+      outputUnit1.isMainOutput, outputUnit2.isMainOutput);
+  checkSetEquivalence(outputUnit1, outputUnit2,
+      'OutputUnit.imports for $element1 vs $element2',
+      outputUnit1.imports, outputUnit2.imports,
+      (a, b) => areElementsEquivalent(a.declaration, b.declaration));
 }
\ No newline at end of file
diff --git a/tests/compiler/dart2js/serialization/test_data.dart b/tests/compiler/dart2js/serialization/test_data.dart
index 83cf2da..568b453 100644
--- a/tests/compiler/dart2js/serialization/test_data.dart
+++ b/tests/compiler/dart2js/serialization/test_data.dart
@@ -5,8 +5,8 @@
 library dart2js.serialization_test_data;
 
 const List<Test> TESTS = const <Test>[
-  // This test is very long-running and put here first to compile it on its own
-  // in compilation0_test.dart
+  // These tests are very long-running and put here first to compile them on
+  // their own tests.
   const Test('Disable tree shaking through reflection', const {
     'main.dart': '''
 import 'dart:mirrors';
@@ -17,6 +17,19 @@
 ''',
   }, expectedWarningCount: 1),
 
+  const Test('Use of dart:indexed_db', const {
+    'main.dart': '''
+import 'a.dart';
+
+main() {}
+''',
+  }, preserializedSourceFiles: const {
+    'a.dart': '''
+import 'dart:indexed_db';
+''',
+  }),
+
+  // These tests
   const Test('Empty program', const {
     'main.dart': 'main() {}'
   }),
@@ -122,7 +135,7 @@
   },
   expectedWarningCount: 1),
 
-  const Test('Impliment Comparable with incompatible parameter types', const {
+  const Test('Implement Comparable with incompatible parameter types', const {
     'main.dart': r'''
 class Class implements Comparable<Class> {
   int compareTo(String other) => 0;
@@ -134,7 +147,7 @@
   expectedWarningCount: 1,
   expectedInfoCount: 1),
 
-  const Test('Impliment Comparable with incompatible parameter count', const {
+  const Test('Implement Comparable with incompatible parameter count', const {
     'main.dart': r'''
 class Class implements Comparable {
   bool compareTo(a, b) => true;
@@ -457,6 +470,18 @@
 ''',
   }),
 
+  const Test('Index set if null', const {
+    'main.dart': '''
+import 'a.dart';
+
+main() => m(null, null, null);
+''',
+  }, preserializedSourceFiles: const {
+    'a.dart': '''
+m(a, b, c) => a[b] ??= c;
+''',
+  }),
+
   const Test('If-null expression in constant constructor', const {
     'main.dart': '''
 import 'a.dart';
@@ -546,6 +571,79 @@
     'c.dart': '''
 ''',
   }, expectedErrorCount: 1),
+
+  const Test('Closure in operator function', const {
+    'main.dart': '''
+import 'a.dart';
+
+main() {
+  test();
+}
+''',
+  }, preserializedSourceFiles: const {
+    'a.dart': '''
+class C {
+  operator ==(other) => () {};
+}
+
+test() => new C() == null;
+''',
+  }),
+
+  const Test('Checked setter', const {
+    'main.dart': '''
+import 'a.dart';
+
+main() {
+  test();
+}
+''',
+  }, preserializedSourceFiles: const {
+    'a.dart': '''
+class C {
+  set foo(int i) {}
+}
+
+test() => new C().foo = 0;
+''',
+  }, checkedMode: true),
+
+  const Test('Deferred access', const {
+    'main.dart': '''
+import 'a.dart';
+
+main() {
+  test();
+}
+''',
+  }, preserializedSourceFiles: const {
+    'a.dart': '''
+import 'b.dart' deferred as b;
+
+test() => b.loadLibrary().then((_) => b.test2());
+''',
+    'b.dart': '''
+test2() {}
+''',
+  }),
+
+  const Test('Deferred access of dart:core', const {
+    'main.dart': '''
+import 'a.dart';
+
+main() {
+  test();
+}
+''',
+  }, preserializedSourceFiles: const {
+    'a.dart': '''
+import "dart:core" deferred as core;
+
+test() {
+  core.loadLibrary().then((_) => null);
+}
+''',
+  }),
 ];
 
 class Test {
@@ -557,6 +655,7 @@
   final int expectedWarningCount;
   final int expectedHintCount;
   final int expectedInfoCount;
+  final bool checkedMode;
 
   const Test(
       this.name,
@@ -566,5 +665,6 @@
       this.expectedErrorCount: 0,
       this.expectedWarningCount: 0,
       this.expectedHintCount: 0,
-      this.expectedInfoCount: 0});
+      this.expectedInfoCount: 0,
+      this.checkedMode: false});
 }
diff --git a/tests/compiler/dart2js/serialization/test_helper.dart b/tests/compiler/dart2js/serialization/test_helper.dart
index 9d3115f..2c74a07 100644
--- a/tests/compiler/dart2js/serialization/test_helper.dart
+++ b/tests/compiler/dart2js/serialization/test_helper.dart
@@ -13,6 +13,7 @@
 import 'package:compiler/src/serialization/equivalence.dart';
 import 'package:compiler/src/tree/nodes.dart';
 import 'package:expect/expect.dart';
+import 'test_data.dart';
 
 Check currentCheck;
 
@@ -589,3 +590,33 @@
   testResolvedAstEquivalence(
       resolvedAst1, resolvedAst2, const CheckStrategy());
 }
+
+/// Returns the test arguments for testing the [index]th skipped test. The
+/// [skip] count is used to check that [index] is a valid index.
+List<String> testSkipped(int index, int skip) {
+  if (index < 0 || index >= skip) {
+    throw new ArgumentError('Invalid skip index $index');
+  }
+  return ['${index}', '${index + 1}'];
+}
+
+/// Return the test arguments for testing the [index]th segment (1-based) of
+/// the [TESTS] split into [count] groups. The first [skip] tests are excluded
+/// from the automatic grouping.
+List<String> testSegment(int index, int count, int skip) {
+  if (index < 0 || index > count) {
+    throw new ArgumentError('Invalid segment index $index');
+  }
+
+  String segmentNumber(int i) {
+    return '${skip + i * (TESTS.length - skip) ~/ count}';
+  }
+
+  if (index == 1 && skip != 0) {
+    return ['${skip}', segmentNumber(index)];
+  } else if (index  == count) {
+    return [segmentNumber(index - 1)];
+  } else {
+    return [segmentNumber(index - 1), segmentNumber(index)];
+  }
+}
diff --git a/tests/compiler/dart2js_extra/invalid_annotation2_test.dart b/tests/compiler/dart2js_extra/invalid_annotation2_test.dart
index d8dafd5..5b1f41a 100644
--- a/tests/compiler/dart2js_extra/invalid_annotation2_test.dart
+++ b/tests/compiler/dart2js_extra/invalid_annotation2_test.dart
@@ -14,7 +14,7 @@
 import 'dart:mirrors';
 
 @Deprecated("m"
-,                                /// 01: compile-time error
+,,                                /// 01: compile-time error
 )
 class A {
 }
diff --git a/tests/compiler/dart2js_extra/invalid_annotation_test.dart b/tests/compiler/dart2js_extra/invalid_annotation_test.dart
index 5e0285a8..50e8e6f 100644
--- a/tests/compiler/dart2js_extra/invalid_annotation_test.dart
+++ b/tests/compiler/dart2js_extra/invalid_annotation_test.dart
@@ -8,7 +8,7 @@
 // annotation had a syntax error.
 
 @Deprecated("m"
-,                                /// 01: compile-time error
+,,                                /// 01: compile-time error
 )
 class A {}
 
diff --git a/tests/compiler/dart2js_extra/truncation_errors_test.dart b/tests/compiler/dart2js_extra/truncation_errors_test.dart
new file mode 100644
index 0000000..1e3767c
--- /dev/null
+++ b/tests/compiler/dart2js_extra/truncation_errors_test.dart
@@ -0,0 +1,119 @@
+// 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.
+
+// Check that exception messages for truncating operations contains the
+// operands.
+
+import 'package:expect/expect.dart';
+
+@NoInline() @AssumeDynamic()
+confuse(x) => x;
+
+void find1(expected, thunk) {
+  if (thunk == null) return;
+  var returned, exceptionText;
+  try {
+    returned = thunk();
+  } catch (e) {
+    exceptionText = '$e';
+  }
+  if (exceptionText == null) {
+    Expect.fail(
+        'Expected exception containing "$expected", returned: $returned');
+  }
+  Expect.isTrue(
+      exceptionText.contains(expected),
+      'Expected "$expected" in "$exceptionText"');
+}
+
+void find(expected, [thunk1, thunk2, thunk3, thunk4]) {
+  find1(expected, thunk1);
+  find1(expected, thunk2);
+  find1(expected, thunk3);
+  find1(expected, thunk4);
+}
+
+main() {
+
+  var NaN = double.NAN;
+  var Infinity = double.INFINITY;
+
+  find(' Infinity: 123 ~/ 0',
+       () => confuse(123) ~/ confuse(0),
+       () => confuse(123) ~/ 0,
+       () => 123 ~/ confuse(0),
+       () => 123 ~/ 0);
+
+  find('-Infinity: 123 ~/ -0.0',
+       () => confuse(123) ~/ confuse(-0.0),
+       () => confuse(123) ~/ -0.0,
+       () => 123 ~/ confuse(-0.0),
+       () => 123 ~/ -0.0);
+
+  find(' NaN: NaN ~/ 123',
+       () => confuse(NaN) ~/ confuse(123),
+       () => confuse(NaN) ~/ 123,
+       () => NaN ~/ confuse(123),
+       () => NaN ~/ 123);
+
+  find(' Infinity: 1e+200 ~/ 1e-200',
+       () => confuse(1e200) ~/ confuse(1e-200),
+       () => confuse(1e200) ~/ 1e-200,
+       () => 1e200 ~/ confuse(1e-200),
+       () => 1e200 ~/ 1e-200);
+
+  find('NaN.toInt()',
+       () => confuse(NaN).toInt(),
+       () => NaN.toInt());
+  find(' Infinity.toInt()',
+       () => confuse(Infinity).toInt(),
+       () => Infinity.toInt());
+  find('-Infinity.toInt()',
+       () => confuse(-Infinity).toInt(),
+       () => (-Infinity).toInt());
+
+  find('NaN.ceil()',
+       () => confuse(NaN).ceil(),
+       () => NaN.ceil());
+  find(' Infinity.ceil()',
+       () => confuse(Infinity).ceil(),
+       () => Infinity.ceil());
+  find('-Infinity.ceil()',
+       () => confuse(-Infinity).ceil(),
+       () => (-Infinity).ceil());
+
+  find('NaN.floor()',
+       () => confuse(NaN).floor(),
+       () => NaN.floor());
+  find(' Infinity.floor()',
+       () => confuse(Infinity).floor(),
+       () => Infinity.floor());
+  find('-Infinity.floor()',
+       () => confuse(-Infinity).floor(),
+       () => (-Infinity).floor());
+
+  find('NaN.round()',
+       () => confuse(NaN).round(),
+       () => NaN.round());
+  find(' Infinity.round()',
+       () => confuse(Infinity).round(),
+       () => Infinity.round());
+  find('-Infinity.round()',
+       () => confuse(-Infinity).round(),
+       () => (-Infinity).round());
+
+  // `truncate()` is the same as `toInt()`.
+  // We could change the runtime so that `truncate` is reported.
+  find('NaN.toInt()',
+       () => confuse(NaN).truncate(),
+       () => NaN.truncate());
+  find(' Infinity.toInt()',
+       () => confuse(Infinity).truncate(),
+       () => Infinity.truncate());
+  find('-Infinity.toInt()',
+       () => confuse(-Infinity).truncate(),
+       () => (-Infinity).truncate());
+
+}
+
diff --git a/tests/compiler/dart2js_native/call_on_native_class_test.dart b/tests/compiler/dart2js_native/call_on_native_class_test.dart
deleted file mode 100644
index 5142982..0000000
--- a/tests/compiler/dart2js_native/call_on_native_class_test.dart
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:_js_helper';
-
-@Native('*A')
-class A {
-}
-
-class B extends A {
-  call() => 42;
-}
-
-main() {
-  new B()();
-}
diff --git a/tests/compiler/dart2js_native/dart2js_native.status b/tests/compiler/dart2js_native/dart2js_native.status
index 28abf25..cae6550 100644
--- a/tests/compiler/dart2js_native/dart2js_native.status
+++ b/tests/compiler/dart2js_native/dart2js_native.status
@@ -6,7 +6,6 @@
 *: Skip
 
 [ $compiler == dart2js ]
-call_on_native_class_test: CompileTimeError # Issue 14813
 native_no_such_method_exception4_frog_test: CompileTimeError # Issue 9631
 native_no_such_method_exception5_frog_test: CompileTimeError # Issue 9631
 
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 53ec300..78010e9 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -41,6 +41,7 @@
 symbol_reserved_word_test/10: MissingCompileTimeError # bug 11669, 19972
 
 [ $compiler == none && ($runtime == drt || $runtime == dartium) ]
+package_resource_test: RuntimeError # Issue 26842
 symbol_reserved_word_test/02: RuntimeError # bug 20191 / dartium/drt cannot detect CompileTimeErrors
 symbol_reserved_word_test/05: RuntimeError # bug 20191 / dartium/drt cannot detect CompileTimeErrors
 symbol_reserved_word_test/04: Fail # bug 11669, 19972 / dartium/drt cannot detect CompileTimeErrors
@@ -138,8 +139,6 @@
 
 [ $compiler == dart2analyzer ]
 int_parse_radix_bad_handler_test: fail
-list_insert_test: fail
-list_removeat_test: fail
 hash_set_type_check_test: StaticWarning, OK # Tests failing type tests.
 error_stack_trace_test: StaticWarning, OK # Test generates errors on purpose.
 iterable_element_at_test: StaticWarning, OK # Test generates errors on purpose.
@@ -162,8 +161,8 @@
 file_resource_test: Skip, OK # VM specific test, uses dart:io.
 http_resource_test: Skip, OK # VM specific test, uses dart:io.
 
-[ $runtime != vm && $runtime != dart_precompiled && $compiler != dart2analyzer && $cps_ir == false ]
-package_resource_test: RuntimeError # Issue 23825 (not implemented yet).
+[ $compiler == dart2js && $browser == false ]
+package_resource_test: RuntimeError # Issue 26842
 
 [ $mode == debug ]
 regexp/pcre_test: Pass, Slow # Timeout. Issue 22008
@@ -173,7 +172,6 @@
 big_integer_parsed_mul_div_vm_test: Pass, Slow
 
 [ $compiler == dart2js && $cps_ir ]
-package_resource_test: Crash # Surprisingly null object in type propagation.
 regexp/pcre_test: Crash # Stack Overflow in LoopHierarchy.
 core_runtime_types_test: Pass, RuntimeError # Issue 25795.
 
@@ -184,9 +182,6 @@
 regexp/pcre_test: Crash # Stack Overflow
 collection_removes_test: Crash # Issue 25911
 
-[ $compiler == dart2js && $host_checked ]
-package_resource_test: Crash # Issue 25911
-
 [ $noopt || $compiler == precompiler ]
 # Stacktraces in precompilation omit inlined frames.
 stacktrace_current_test: Pass, RuntimeError
@@ -209,15 +204,3 @@
 
 [ $arch == simdbc || $arch == simdbc64 ]
 regexp/stack-overflow_test: RuntimeError, OK # Smaller limit with irregex interpreter
-
-[ $hot_reload ]
-big_integer_huge_mul_vm_test: Pass, Timeout
-big_integer_parsed_mul_div_vm_test: Pass, Timeout
-collection_length_test: Fail, Crash
-hash_map2_test: Pass, Crash
-queue_test: Pass, Crash
-regexp/regexp_test: Pass, Fail, Crash
-uri_parse_test: Pass, Timeout
-uri_test: Pass, RuntimeError
-data_uri_test: Pass, RuntimeError
-int_parse_radix_test: Pass, Timeout
diff --git a/tests/corelib/double_floor_test.dart b/tests/corelib/double_floor_test.dart
index c59f411..7407561 100644
--- a/tests/corelib/double_floor_test.dart
+++ b/tests/corelib/double_floor_test.dart
@@ -79,4 +79,4 @@
   Expect.isTrue((-9007199254740991.0).floor() is int);
   Expect.isTrue((-9007199254740992.0).floor() is int);
   Expect.isTrue((-double.MAX_FINITE).floor() is int);
-}
\ No newline at end of file
+}
diff --git a/tests/html/html.status b/tests/html/html.status
index 4d57f42..c7afa75 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -26,6 +26,9 @@
 wrapping_collections_test: SkipByDesign # Testing an issue that is only relevant to Dartium
 js_typed_interop_default_arg_test/default_value: MissingCompileTimeError # Issue #25759
 mirrors_js_typed_interop_test: Pass, Slow
+js_type_test/dynamic-null-not-Foo: Fail  # Issue 26838
+js_type_test/dynamic-String-not-Foo: Fail  # Issue 26838
+js_type_test/dynamic-String-not-dynamic-Foo: Fail  # Issue 26838
 
 
 [ $compiler == dart2js && $checked ]
@@ -338,14 +341,29 @@
 [ $compiler == dart2js && ($runtime == drt || $runtime == ff) ]
 request_animation_frame_test: Skip # Async test hangs.
 
+[ $runtime == drt ]
+webgl_extensions_test: Skip # webgl does not work properly on DRT, which is 'headless'.
+
+[ $runtime == dartium && ($system == windows || $system == linux) ]
+webgl_extensions_test: Fail # WebGL extension tests fail on Dartium without graphics. This is dependent on our bot configuration.
+
+[ $runtime == chrome && ($system == windows || $system == linux) ]
+webgl_extensions_test: Fail # WebGL extension tests fail without graphics. This is dependent on our bot configuration.
+
 [ $compiler == dart2js && $csp && ($runtime == drt || $runtime == safari || $runtime == ff || $runtime == chrome || $runtime == chromeOnAndroid) ]
 # Note: these tests are all injecting scripts by design.  This is not allowed under CSP.
+# TODO(sra): Change these tests to use a same-origin JavaScript script file.
 event_customevent_test: SkipByDesign
 js_interop_1_test: SkipByDesign
 js_test: SkipByDesign
 js_array_test: SkipByDesign
+js_util_test: SkipByDesign
+js_typed_interop_bind_this_test: SkipByDesign
+js_typed_interop_callable_object_test: SkipByDesign
 js_typed_interop_test: SkipByDesign
 js_typed_interop_default_arg_test: SkipByDesign
+js_typed_interop_type_test: SkipByDesign
+js_typed_interop_window_property_test: SkipByDesign
 js_function_getter_test: SkipByDesign
 js_function_getter_trust_types_test: SkipByDesign
 js_dart_to_string_test: SkipByDesign
diff --git a/tests/html/js_type_test.dart b/tests/html/js_type_test.dart
new file mode 100644
index 0000000..90df68f
--- /dev/null
+++ b/tests/html/js_type_test.dart
@@ -0,0 +1,146 @@
+// 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 jsTest;
+
+import 'dart:html';
+
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_individual_config.dart';
+import 'package:expect/expect.dart' show NoInline, AssumeDynamic;
+
+import 'js_type_test_lib.dart';
+
+class Bar {}
+
+@NoInline() @AssumeDynamic()
+confuse(x) => x;
+
+class Is<T> {
+  const Is();
+  check(o) => o is T;
+}
+
+main() {
+  useHtmlIndividualConfiguration();
+
+  new Is<Foo>().check(new Bar());  // Bar is instantiated by this code.
+  new Is<Foo>().check([]);
+  new Is<List>().check([]);
+
+  group('static', () {
+    test('not-String', () {
+      Foo e = new Foo();
+      expect(e is String, isFalse);
+    });
+
+    test('not-int', () {
+      Foo e = new Foo();
+      expect(e is int, isFalse);
+    });
+
+    test('not-Null', () {
+      Foo e = new Foo();
+      expect(e is Null, isFalse);
+    });
+
+    test('not-Bar', () {
+      Foo e = new Foo();
+      expect(e is Bar, isFalse);
+    });
+
+    test('is-Foo', () {
+      Foo e = new Foo();
+      expect(e is Foo, isTrue);
+    });
+
+    test('String-not-Foo', () {
+      String e = 'hello';
+      expect(e is Foo, isFalse);
+    });
+  });
+
+  group('dynamic', () {
+    test('not-String', () {
+      var e = confuse(new Foo());
+      expect(e is String, isFalse);
+    });
+
+    test('not-int', () {
+      var e = confuse(new Foo());
+      expect(e is int, isFalse);
+    });
+
+    test('not-Null', () {
+      var e = confuse(new Foo());
+      expect(e is Null, isFalse);
+    });
+
+    test('not-Bar', () {
+      var e = confuse(new Foo());
+      expect(e is Bar, isFalse);
+    });
+
+    test('is-Foo', () {
+      var e = confuse(new Foo());
+      expect(e is Foo, isTrue);
+    });
+  });
+
+  group('dynamic-String-not-Foo', () {
+    test('test', () {
+      var e = confuse('hello');
+      expect(e is Foo, isFalse);
+    });
+  });
+
+  group('dynamic-null-not-Foo', () {
+    test('test', () {
+      var e = confuse(null);
+      expect(e is Foo, isFalse);
+    });
+  });
+
+  group('dynamic-type', () {
+    test('not-String', () {
+      var e = confuse(new Foo());
+      expect(const Is<String>().check(e), isFalse);
+    });
+
+    test('not-int', () {
+      var e = confuse(new Foo());
+      expect(const Is<int>().check(e), isFalse);
+    });
+
+    test('not-Null', () {
+      var e = confuse(new Foo());
+      expect(const Is<Null>().check(e), isFalse);
+    });
+
+    test('not-Bar', () {
+      var e = confuse(new Foo());
+      expect(const Is<Bar>().check(e), isFalse);
+    });
+
+    test('is-Foo', () {
+      var e = confuse(new Foo());
+      expect(const Is<Foo>().check(e), isTrue);
+    });
+  });
+
+  group('dynamic-String-not-dynamic-Foo', () {
+    test('test', () {
+      var e = confuse('hello');
+      expect(const Is<Foo>().check(e), isFalse);
+    });
+  });
+
+  group('dynamic-null-not-dynamic-Foo', () {
+    test('test', () {
+      var e = confuse(null);
+      expect(const Is<Foo>().check(e), isFalse);
+    });
+  });
+
+}
diff --git a/tests/html/js_type_test.html b/tests/html/js_type_test.html
new file mode 100644
index 0000000..69628ed
--- /dev/null
+++ b/tests/html/js_type_test.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<--
+// 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.
+-->
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> js_type_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+</head>
+<body>
+  <h1> Running js_type_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/tests/html/js_type_test_js.js"></script>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/html/js_type_test_js.js b/tests/html/js_type_test_js.js
new file mode 100644
index 0000000..1f12f38
--- /dev/null
+++ b/tests/html/js_type_test_js.js
@@ -0,0 +1,5 @@
+// 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.
+
+function Foo() {}
diff --git a/tests/html/js_type_test_lib.dart b/tests/html/js_type_test_lib.dart
new file mode 100644
index 0000000..6b7113c
--- /dev/null
+++ b/tests/html/js_type_test_lib.dart
@@ -0,0 +1,13 @@
+// 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.
+
+@JS()
+library js_type_test_lib;
+
+import 'package:js/js.dart';
+
+@JS()
+class Foo {
+  external factory Foo();
+}
diff --git a/tests/html/js_typed_interop_bind_this_test.dart b/tests/html/js_typed_interop_bind_this_test.dart
new file mode 100644
index 0000000..d241cb9
--- /dev/null
+++ b/tests/html/js_typed_interop_bind_this_test.dart
@@ -0,0 +1,53 @@
+// 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.
+
+@JS()
+library js_typed_interop_bind_this_test;
+
+import 'dart:html';
+
+import 'package:js/js.dart';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+import 'package:unittest/html_individual_config.dart';
+
+// This is a regression test for https://github.com/dart-lang/sdk/issues/25658
+
+_injectJs() {
+  document.body.append(new ScriptElement()
+    ..type = 'text/javascript'
+    ..innerHtml = r"""
+  "use strict";
+
+  function JsTest() {
+  }
+
+  JsTest.returnThis = function(name, value) {
+    return this;
+  };
+""");
+}
+
+@JS('JsTest.returnThis')
+external returnThis([name, value]);
+
+@JS('JsTest')
+external get jsTestObject;
+
+@JS('window')
+external get jsWindow;
+
+main() {
+  _injectJs();
+
+  useHtmlIndividualConfiguration();
+
+  group('bind this', () {
+    test('simple', () {
+      expect(identical(returnThis(), jsWindow), isFalse);
+      expect(identical(returnThis(), null), isFalse);
+      expect(identical(returnThis(), jsTestObject), isTrue);
+    });
+  });
+}
diff --git a/tests/html/js_typed_interop_callable_object_test.dart b/tests/html/js_typed_interop_callable_object_test.dart
new file mode 100644
index 0000000..4456459
--- /dev/null
+++ b/tests/html/js_typed_interop_callable_object_test.dart
@@ -0,0 +1,72 @@
+// 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.
+
+@JS()
+library js_typed_interop_callable_object_test;
+
+import 'dart:html';
+
+import 'package:expect/expect.dart' show NoInline, AssumeDynamic;
+import 'package:js/js.dart';
+import 'package:unittest/html_config.dart';
+import 'package:unittest/html_individual_config.dart';
+import 'package:unittest/unittest.dart';
+
+// This is a regression test for https://github.com/dart-lang/sdk/issues/25658
+
+@NoInline()
+@AssumeDynamic()
+confuse(x) => x;
+
+_injectJs() {
+  document.body.append(new ScriptElement()
+    ..type = 'text/javascript'
+    ..innerHtml = r"""
+  "use strict";
+
+  window.callableObject = function (a, b) { return a + b; };
+  window.callableObject.foo = function() { return "bar"; };
+  window.callableObject.bar = 42;
+
+""");
+}
+
+@JS()
+@anonymous
+class CallableObject {
+  /// If a @JS class implements `call`, the underlying representation must be
+  /// a JavaScript callable (i.e. function).
+  external num call(num a, num b);
+  external int get bar;
+  external String foo();
+}
+
+@JS()
+external CallableObject get callableObject;
+
+main() {
+  _injectJs();
+
+  useHtmlIndividualConfiguration();
+
+  group('callable object', () {
+    test('simple', () {
+      var obj = callableObject;
+      expect(obj(4, 5), equals(9));
+      expect(obj.bar, equals(42));
+      expect(obj.foo(), equals("bar"));
+
+      expect(callableObject(4, 5), equals(9));
+      expect(callableObject.bar, equals(42));
+      expect(callableObject.foo(), equals("bar"));
+    });
+
+    test('dynamic', () {
+      var obj = confuse(callableObject);
+      expect(obj(4, 5), equals(9));
+      expect(obj.bar, equals(42));
+      expect(obj.foo(), equals("bar"));
+    });
+  });
+}
diff --git a/tests/html/js_typed_interop_test.dart b/tests/html/js_typed_interop_test.dart
index 431d533..960c0cc 100644
--- a/tests/html/js_typed_interop_test.dart
+++ b/tests/html/js_typed_interop_test.dart
@@ -71,6 +71,15 @@
     getA: function() { return this.a;}
   };
 
+  function _PrivateClass(a, b) {
+    this._a = a;
+    this._b = b;
+  };
+
+  _PrivateClass.prototype = {
+    _getA: function() { return this._a;}
+  };
+
   var selection = ["a", "b", "c", foo, bar];  
 
   function returnNumArgs() { return arguments.length; };
@@ -78,6 +87,23 @@
 
   function confuse(obj) { return obj; }
 
+  window['class'] = function() { return 42; };
+  window['delete'] = 100;
+  window['JS$hasJsInName'] = 'unicorn';
+  window['JS$hasJsInNameMethod'] = function(x) { return x*5; };
+
+  function JS$ClassWithJSInName(x) {
+    this.x = x;
+    this.JS$hasJsInName = 73;
+    this.$JS$doesNotNeedEscape = 103;
+  };
+
+  JS$ClassWithJSInName.prototype = {
+    JS$getXwithJsInName: function() { return this.x;}
+  };
+
+  JS$ClassWithJSInName.JS$staticMethod = function(x) { return x * 3; };
+
   function StringWrapper(str) {
     this.str = str;
   }
@@ -110,6 +136,49 @@
   external get b;
 }
 
+@JS('ClassWithConstructor')
+class _ClassWithConstructor {
+  external _ClassWithConstructor(aParam, bParam);
+  external getA();
+  external get a;
+  external get b;
+}
+
+@JS()
+class JS$_PrivateClass {
+  external JS$_PrivateClass(aParam, bParam);
+  external JS$_getA();
+  external get JS$_a;
+  external get JS$_b;
+  // Equivalent to JS$_a but only visible within
+  // the class.
+  external get _a;
+}
+
+@JS()
+external String get JS$JS$hasJsInName;
+
+@JS()
+external int JS$JS$hasJsInNameMethod(int x);
+
+// This is the prefered way to handle static or top level members that start
+// with JS$. We verify that JS$JS$ works purely to prevent bugs.
+@JS(r'JS$hasJsInName')
+external String get JS$hasJsInName;
+
+@JS(r'JS$hasJsInNameMethod')
+external int JS$hasJsInNameMethod(int x);
+
+@JS()
+class JS$JS$ClassWithJSInName {
+  external JS$JS$ClassWithJSInName(x);
+  external int get x;
+  external int get JS$JS$hasJsInName;
+  external int get $JS$doesNotNeedEscape;
+  external int JS$JS$getXwithJsInName();
+  external static int JS$JS$staticMethod(x);
+}
+
 typedef num MultiplyWithDefault(num a, [num b]);
 
 @JS()
@@ -118,6 +187,7 @@
   external set x(int v);
   external num multiplyByX(num y);
   external num multiplyBy2(num y);
+  external num JS$multiplyBy2(num y);
   external MultiplyWithDefault get multiplyDefault2Function;
 
   external callClosureWithArgAndThis(Function closure, arg);
@@ -126,14 +196,17 @@
   external Bar getBar();
 
   external static num multiplyDefault2(num a, [num b]);
+  // Should desugar to multiplyDefault2.
+  external static num JS$multiplyDefault2(num a, [num b]);
 }
 
 @anonymous
 @JS()
 class ExampleLiteral {
-  external factory ExampleLiteral({int x, String y, num z});
+  external factory ExampleLiteral({int x, String y, num z, JS$class});
 
   external int get x;
+  external int get JS$class;
   external String get y;
   external num get z;
 }
@@ -182,6 +255,13 @@
 @JS()
 external confuse(obj);
 
+/// Desugars to calling the js method named class.
+@JS()
+external JS$class();
+
+@JS()
+external get JS$delete;
+
 @JS()
 external CanvasRenderingContext2D getCanvasContext();
 
@@ -191,6 +271,16 @@
 @JS('window.self.window.window.windowProperty')
 external num get propertyOnWindow;
 
+@JS()
+@anonymous
+class Simple
+{
+    external List<int> get numbers;
+    external set numbers(List<int> numbers);
+
+    external factory Simple({ List<int> numbers });
+}
+
 main() {
   _injectJs();
 
@@ -210,6 +300,17 @@
       expect(stringify(l), equals('{"z":100}'));
     });
 
+    test('with array', () {
+      // Repro for https://github.com/dart-lang/sdk/issues/26768
+       var simple = new Simple(numbers: [ 1, 2, 3 ]);
+       expect(stringify(simple), equals('{"numbers":[1,2,3]}'));
+    });
+
+    test(r'JS$ escaped name', () {
+      var l = new ExampleLiteral(JS$class: 3, y: "foo");
+      expect(l.JS$class, equals(3));
+    });
+
     test('empty', () {
       var l = new EmptyLiteral();
       expect(stringify(l), equals('{}'));
@@ -225,6 +326,25 @@
     });
   });
 
+  group('private class', () {
+    test('simple', () {
+      var o = new _ClassWithConstructor("foo", "bar");
+      expect(o.a, equals("foo"));
+      expect(o.b, equals("bar"));
+      expect(o.getA(), equals("foo"));
+    });
+  });
+
+  group('private class', () {
+    test('simple', () {
+      var o = new JS$_PrivateClass("foo", "bar");
+      expect(o.JS$_a, equals("foo"));
+      expect(o.JS$_b, equals("bar"));
+      expect(o._a, equals("foo"));
+      expect(o.JS$_getA(), equals("foo"));
+    });
+  });
+
   group('property', () {
     test('get', () {
       expect(foo.x, equals(3));
@@ -276,6 +396,22 @@
       expect(untypedFunction(), isNaN);
 
     });
+
+    test(r'JS$ escaped name', () {
+      foo.x = 10;
+      expect(foo.JS$multiplyBy2(5), equals(10));
+
+      Function multiplyBy2 = foo.JS$multiplyBy2;
+      expect(multiplyBy2(5), equals(10));
+    });
+
+    test(r'JS$ double escaped name', () {
+      var obj = new JS$JS$ClassWithJSInName(42);
+      expect(obj.x, equals(42));
+      expect(obj.JS$JS$getXwithJsInName(), equals(42));
+      expect(obj.JS$JS$hasJsInName, equals(73));
+      expect(obj.$JS$doesNotNeedEscape, equals(103));
+    });
   });
 
   group('static_method_call', () {
@@ -283,6 +419,15 @@
       expect(Foo.multiplyDefault2(6, 7), equals(42));
       expect(Foo.multiplyDefault2(6), equals(12));
     });
+
+    test(r'JS$ escaped name', () {
+      expect(Foo.JS$multiplyDefault2(6, 7), equals(42));
+      expect(Foo.JS$multiplyDefault2(6), equals(12));
+    });
+
+    test(r'JS$ double escaped name', () {
+      expect(JS$JS$ClassWithJSInName.JS$JS$staticMethod(4), equals(12));
+    });
   });
 
   // Note: these extra groups are added to be able to mark each test
@@ -384,6 +529,17 @@
     });
   });
 
+  group(r'JS$ escaped', () {
+    test('top level', () {
+      expect(JS$class(), equals(42));
+      expect(JS$delete, equals(100));
+    });
+    test('top level double escaped', () {
+      expect(JS$JS$hasJsInName, equals('unicorn'));
+      expect(JS$JS$hasJsInNameMethod(4), equals(20));
+    });
+  });
+
   group('type check', () {
     test('js interfaces', () {
       // Is checks return true for all  JavaScript interfaces.
diff --git a/tests/html/js_typed_interop_type_test.dart b/tests/html/js_typed_interop_type_test.dart
new file mode 100644
index 0000000..59266dc
--- /dev/null
+++ b/tests/html/js_typed_interop_type_test.dart
@@ -0,0 +1,166 @@
+// 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.
+
+
+@JS()
+library js_typed_interop_type_test;
+
+import 'dart:html';
+import 'package:js/js.dart';
+import 'package:expect/expect.dart';
+
+@JS()
+class A {
+  var foo;
+
+  external A(var foo);
+}
+
+@JS()
+class B {
+  var foo;
+
+  external B(var foo);
+}
+
+@JS()
+@anonymous
+class C {
+  final foo;
+
+  external factory C({foo});
+}
+
+@JS()
+@anonymous
+class D {
+  final foo;
+
+  external factory D({foo});
+}
+
+class E {
+  final foo;
+
+  E(this.foo);
+}
+
+class F {
+  final foo;
+
+  F(this.foo);
+}
+
+@NoInline()
+testA(A o) {
+  return o.foo;
+}
+
+
+@NoInline()
+testB(B o) {
+  return o.foo;
+}
+
+
+@NoInline()
+testC(C o) {
+  return o.foo;
+}
+
+
+@NoInline()
+testD(D o) {
+  return o.foo;
+}
+
+@NoInline()
+testE(E o) {
+  return o.foo;
+}
+
+@NoInline()
+testF(F o) {
+  return o.foo;
+}
+
+
+_injectJs() {
+  document.body.append(new ScriptElement()
+    ..type = 'text/javascript'
+    ..innerHtml = r"""
+function A(foo) {
+  this.foo = foo;
+}
+
+function B(foo) {
+  this.foo = foo;
+}
+""");
+}
+
+void expectValueOrTypeError(f(), value) {
+  try {
+    var i = 0;
+    String s = i; // Test for checked mode.
+    Expect.equals(f(), value);
+  } on TypeError catch (error) {
+    Expect.throws(f, (ex) => ex is TypeError);
+  }
+}
+
+main() {
+  _injectJs();
+
+  var a = new A(1);
+  var b = new B(2);
+  var c = new C(foo: 3);
+  var d = new D(foo: 4);
+  var e = new E(5);
+  var f = new F(6);
+
+  Expect.equals(testA(a), 1);
+  Expect.equals(testA(b), 2);
+  Expect.equals(testA(c), 3);
+  Expect.equals(testA(d), 4);
+  expectValueOrTypeError(() => testA(e), 5);
+  expectValueOrTypeError(() => testA(f), 6);
+
+  Expect.equals(testB(a), 1);
+  Expect.equals(testB(b), 2);
+  Expect.equals(testB(c), 3);
+  Expect.equals(testB(d), 4);
+  expectValueOrTypeError(() => testB(e), 5);
+  expectValueOrTypeError(() => testB(f), 6);
+
+  Expect.equals(testC(a), 1);
+  Expect.equals(testC(b), 2);
+  Expect.equals(testC(c), 3);
+  Expect.equals(testC(d), 4);
+  expectValueOrTypeError(() => testC(e), 5);
+  expectValueOrTypeError(() => testC(f), 6);
+
+  Expect.equals(testD(a), 1);
+  Expect.equals(testD(b), 2);
+  Expect.equals(testD(c), 3);
+  Expect.equals(testD(d), 4);
+  expectValueOrTypeError(() => testD(e), 5);
+  expectValueOrTypeError(() => testD(f), 6);
+
+  expectValueOrTypeError(() => testE(a), 1);
+  expectValueOrTypeError(() => testE(b), 2);
+  expectValueOrTypeError(() => testE(c), 3);
+  expectValueOrTypeError(() => testE(d), 4);
+  Expect.equals(testE(e), 5);
+  expectValueOrTypeError(() => testE(f), 6);
+
+  expectValueOrTypeError(() => testF(a), 1);
+  expectValueOrTypeError(() => testF(b), 2);
+  expectValueOrTypeError(() => testF(c), 3);
+  expectValueOrTypeError(() => testF(d), 4);
+  expectValueOrTypeError(() => testF(e), 5);
+  Expect.equals(testF(f), 6);
+}
+
+
diff --git a/tests/html/js_typed_interop_window_property_test.dart b/tests/html/js_typed_interop_window_property_test.dart
new file mode 100644
index 0000000..0f2bdc6
--- /dev/null
+++ b/tests/html/js_typed_interop_window_property_test.dart
@@ -0,0 +1,40 @@
+// 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.
+
+@JS()
+library js_typed_interop_window_property_test;
+
+import 'dart:html';
+
+import 'package:js/js.dart';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+import 'package:unittest/html_individual_config.dart';
+
+// This is a regression test for https://github.com/dart-lang/sdk/issues/24817
+
+_injectJs() {
+  document.body.append(new ScriptElement()
+    ..type = 'text/javascript'
+    ..innerHtml = r"""
+  "use strict";
+
+  window.foo = [function() { return 42; }];
+""");
+}
+
+@JS("window.foo")
+external List<Function> get foo;
+
+main() {
+  _injectJs();
+
+  useHtmlIndividualConfiguration();
+
+  group('bind this', () {
+    test('simple', () {
+      expect(foo[0](), equals(42));
+    });
+  });
+}
diff --git a/tests/html/js_util_test.dart b/tests/html/js_util_test.dart
new file mode 100644
index 0000000..b0130b2
--- /dev/null
+++ b/tests/html/js_util_test.dart
@@ -0,0 +1,347 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+@JS()
+library js_native_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:typed_data' show ByteBuffer, Int32List;
+import 'dart:indexed_db' show IdbFactory, KeyRange;
+
+import 'package:js/js.dart';
+import 'package:js/js_util.dart' as js_util;
+
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_individual_config.dart';
+
+_injectJs() {
+  final script = new ScriptElement();
+  script.type = 'text/javascript';
+  script.innerHtml = r"""
+var x = 42;
+
+var _x = 123;
+
+var myArray = ["value1"];
+
+function returnThis() {
+  return this;
+}
+
+function getTypeOf(o) {
+  return typeof(o);
+}
+
+function Foo(a) {
+  this.a = a;
+}
+
+Foo.b = 38;
+
+Foo.prototype.bar = function() {
+  return this.a;
+}
+Foo.prototype.toString = function() {
+  return "I'm a Foo a=" + this.a;
+}
+
+var container = new Object();
+container.Foo = Foo;
+
+function checkMap(m, key, value) {
+  if (m.hasOwnProperty(key))
+    return m[key] == value;
+  else
+    return false;
+}
+
+""";
+  document.body.append(script);
+}
+
+@JS()
+external bool checkMap(m, String, value);
+
+@JS('JSON.stringify')
+external String stringify(o);
+
+@JS('Node')
+external get JSNodeType;
+
+@JS('Element')
+external get JSElementType;
+
+@JS('Text')
+external get JSTextType;
+
+@JS('HTMLCanvasElement')
+external get JSHtmlCanvasElementType;
+
+@JS()
+class Foo {
+  external Foo(num a);
+
+  external num get a;
+  external num bar();
+}
+
+@JS('Foo')
+external get JSFooType;
+
+@JS()
+@anonymous
+class ExampleTypedLiteral {
+  external factory ExampleTypedLiteral({a, b, JS$_c, JS$class});
+
+  external get a;
+  external get b;
+  external get JS$_c;
+  external set JS$_c(v);
+  // Identical to JS$_c but only accessible within the library.
+  external get _c;
+  external get JS$class;
+  external set JS$class(v);
+}
+
+@JS("Object.prototype.hasOwnProperty")
+external get _hasOwnProperty;
+
+bool hasOwnProperty(o, String name) {
+  return js_util.callMethod(_hasOwnProperty, 'call', [o, name]);
+}
+
+main() {
+  _injectJs();
+  useHtmlIndividualConfiguration();
+
+  group('js_util.jsify()', () {
+    test('convert a List', () {
+      final list = [1, 2, 3, 4, 5, 6, 7, 8];
+      var array = js_util.jsify(list);
+      expect(array is List, isTrue);
+      expect(identical(array, list), isFalse);
+      expect(array.length, equals(list.length));
+      for (var i = 0; i < list.length; i++) {
+        expect(array[i], equals(list[i]));
+      }
+    });
+
+    test('convert an Iterable', () {
+      final set = new Set.from([1, 2, 3, 4, 5, 6, 7, 8]);
+      var array = js_util.jsify(set);
+      expect(array is List, isTrue);
+      expect(array.length, equals(set.length));
+      for (var i = 0; i < array.length; i++) {
+        expect(set.contains(array[i]), isTrue);
+      }
+    });
+
+    test('convert a Map', () {
+      var map = {'a': 1, 'b': 2, 'c': 3};
+      var jsMap = js_util.jsify(map);
+      expect(jsMap is! List, isTrue);
+      for (var key in map.keys) {
+        expect(checkMap(jsMap, key, map[key]), isTrue);
+      }
+    });
+
+    test('deep convert a complex object', () {
+      final object = {
+        'a': [
+          1,
+          [2, 3]
+        ],
+        'b': {'c': 3, 'd': new Foo(42)},
+        'e': null
+      };
+      var jsObject = js_util.jsify(object);
+      expect(js_util.getProperty(jsObject, 'a')[0], equals(object['a'][0]));
+      expect(
+          js_util.getProperty(jsObject, 'a')[1][0], equals(object['a'][1][0]));
+      expect(
+          js_util.getProperty(jsObject, 'a')[1][1], equals(object['a'][1][1]));
+      expect(js_util.getProperty(js_util.getProperty(jsObject, 'b'), 'c'),
+          equals(object['b']['c']));
+      expect(js_util.getProperty(js_util.getProperty(jsObject, 'b'), 'd'),
+          equals(object['b']['d']));
+      expect(
+          js_util.callMethod(
+              js_util.getProperty(js_util.getProperty(jsObject, 'b'), 'd'),
+              'bar', []),
+          equals(42));
+      expect(js_util.getProperty(jsObject, 'e'), isNull);
+    });
+
+    test('throws if object is not a Map or Iterable', () {
+      expect(() => js_util.jsify('a'),
+          throwsA(new isInstanceOf<ArgumentError>()));
+    });
+  });
+
+  group('js_util.newObject', () {
+    test('create', () {
+      expect(identical(js_util.newObject(), js_util.newObject()), isFalse);
+    });
+
+    test('callMethod', () {
+      var o = js_util.newObject();
+      expect(js_util.callMethod(o, 'toString', []), equals('[object Object]'));
+      expect(stringify(o), equals('{}'));
+    });
+
+    test('properties', () {
+      var o = js_util.newObject();
+      expect(js_util.hasProperty(o, 'foo bar'), isFalse);
+      expect(js_util.hasProperty(o, 'toString'), isTrue);
+      expect(hasOwnProperty(o, 'toString'), isFalse);
+      expect(hasOwnProperty(o, 'foo bar'), isFalse);
+      js_util.setProperty(o, 'foo bar', 42);
+      expect(hasOwnProperty(o, 'foo bar'), isTrue);
+      expect(js_util.getProperty(o, 'foo bar'), equals(42));
+      expect(js_util.hasProperty(o, 'foo bar'), isTrue);
+      expect(stringify(o), equals('{"foo bar":42}'));
+    });
+  });
+
+  group('hasProperty', () {
+    test('typed object', () {
+      var f = new Foo(42);
+      expect(js_util.hasProperty(f, 'a'), isTrue);
+      expect(js_util.hasProperty(f, 'toString'), isTrue);
+      js_util.setProperty(f, '__proto__', null);
+      expect(js_util.hasProperty(f, 'toString'), isFalse);
+    });
+    test('typed literal', () {
+      var l =
+          new ExampleTypedLiteral(a: 'x', b: 42, JS$_c: null, JS$class: true);
+      expect(js_util.hasProperty(l, 'a'), isTrue);
+      expect(js_util.hasProperty(l, 'b'), isTrue);
+      expect(js_util.hasProperty(l, '_c'), isTrue);
+      expect(l.JS$_c, isNull);
+      expect(js_util.hasProperty(l, 'class'), isTrue);
+      // JS$_c escapes to _c so the property JS$_c will not exist on the object.
+      expect(js_util.hasProperty(l, r'JS$_c'), isFalse);
+      expect(js_util.hasProperty(l, r'JS$class'), isFalse);
+      expect(l.JS$class, isTrue);
+
+      l = new ExampleTypedLiteral(a: null);
+      expect(js_util.hasProperty(l, 'a'), isTrue);
+      expect(js_util.hasProperty(l, 'b'), isFalse);
+      expect(js_util.hasProperty(l, '_c'), isFalse);
+      expect(js_util.hasProperty(l, 'class'), isFalse);
+
+      l = new ExampleTypedLiteral(JS$_c: 74);
+      expect(js_util.hasProperty(l, '_c'), isTrue);
+      expect(l.JS$_c, equals(74));
+    });
+  });
+
+  group('getProperty', () {
+    test('typed object', () {
+      var f = new Foo(42);
+      expect(js_util.getProperty(f, 'a'), equals(42));
+      expect(js_util.getProperty(f, 'toString') is Function, isTrue);
+      js_util.setProperty(f, '__proto__', null);
+      expect(js_util.getProperty(f, 'toString'), isNull);
+    });
+
+    test('typed literal', () {
+      var l = new ExampleTypedLiteral(a: 'x', b: 42, JS$_c: 7, JS$class: true);
+      expect(js_util.getProperty(l, 'a'), equals('x'));
+      expect(js_util.getProperty(l, 'b'), equals(42));
+      expect(js_util.getProperty(l, '_c'), equals(7));
+      expect(l.JS$_c, equals(7));
+      expect(js_util.getProperty(l, 'class'), isTrue);
+      expect(js_util.getProperty(l, r'JS$_c'), isNull);
+      expect(js_util.getProperty(l, r'JS$class'), isNull);
+    });
+  });
+
+  group('setProperty', () {
+    test('typed object', () {
+      var f = new Foo(42);
+      expect(js_util.getProperty(f, 'a'), equals(42));
+      js_util.setProperty(f, 'a', 100);
+      expect(f.a, equals(100));
+      expect(js_util.getProperty(f, 'a'), equals(100));
+    });
+
+    test('typed literal', () {
+      var l = new ExampleTypedLiteral();
+      js_util.setProperty(l, 'a', 'foo');
+      expect(js_util.getProperty(l, 'a'), equals('foo'));
+      expect(l.a, equals('foo'));
+      js_util.setProperty(l, 'a', l);
+      expect(identical(l.a, l), isTrue);
+      var list = ['arr'];
+      js_util.setProperty(l, 'a', list);
+      expect(identical(l.a, list), isTrue);
+      l.JS$class = 42;
+      expect(l.JS$class, equals(42));
+      js_util.setProperty(l, 'class', 100);
+      expect(l.JS$class, equals(100));
+    });
+  });
+
+  group('callMethod', () {
+    test('html object', () {
+      var canvas = new Element.tag('canvas');
+      expect(
+          identical(canvas.getContext('2d'),
+              js_util.callMethod(canvas, 'getContext', ['2d'])),
+          isTrue);
+    });
+
+    test('typed object', () {
+      var f = new Foo(42);
+      expect(js_util.callMethod(f, 'bar', []), equals(42));
+    });
+  });
+
+  group('instanceof', () {
+    test('html object', () {
+      var canvas = new Element.tag('canvas');
+      expect(js_util.instanceof(canvas, JSNodeType), isTrue);
+      expect(js_util.instanceof(canvas, JSTextType), isFalse);
+      expect(js_util.instanceof(canvas, JSElementType), isTrue);
+      expect(js_util.instanceof(canvas, JSHtmlCanvasElementType), isTrue);
+      var div = new Element.tag('div');
+      expect(js_util.instanceof(div, JSNodeType), isTrue);
+      expect(js_util.instanceof(div, JSTextType), isFalse);
+      expect(js_util.instanceof(div, JSElementType), isTrue);
+      expect(js_util.instanceof(div, JSHtmlCanvasElementType), isFalse);
+
+      var text = new Text('foo');
+      expect(js_util.instanceof(text, JSNodeType), isTrue);
+      expect(js_util.instanceof(text, JSTextType), isTrue);
+      expect(js_util.instanceof(text, JSElementType), isFalse);
+    });
+
+    test('typed object', () {
+      var f = new Foo(42);
+      expect(js_util.instanceof(f, JSFooType), isTrue);
+      expect(js_util.instanceof(f, JSNodeType), isFalse);
+    });
+
+    test('typed literal', () {
+      var l = new ExampleTypedLiteral();
+      expect(js_util.instanceof(l, JSFooType), isFalse);
+    });
+  });
+
+  group('callConstructor', () {
+    test('html object', () {
+      var textNode = js_util.callConstructor(JSTextType, ['foo']);
+      expect(js_util.instanceof(textNode, JSTextType), isTrue);
+      expect(textNode is Text, isTrue);
+      expect(textNode.text, equals('foo'));
+    });
+
+    test('typed object', () {
+      Foo f = js_util.callConstructor(JSFooType, [42]);
+      expect(f.a, equals(42));
+    });
+  });
+}
diff --git a/tests/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart b/tests/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart
index 4d7d338..6859e87 100644
--- a/tests/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart
+++ b/tests/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart
@@ -116,6 +116,14 @@
         validator,
         '<span>![CDATA[ some text ]]></span>');
 
+    testHtml('backquotes not removed',
+             validator,
+             '<img src="dice.png" alt="``onload=xss()" />');
+
+    testHtml('0x3000 not removed',
+             validator,
+             '<a href="&#x3000;javascript:alert(1)">CLICKME</a>');
+
     test('sanitizes template contents', () {
       if (!TemplateElement.supported) return;
 
diff --git a/tests/html/webgl_extensions_test.dart b/tests/html/webgl_extensions_test.dart
new file mode 100644
index 0000000..07232f0
--- /dev/null
+++ b/tests/html/webgl_extensions_test.dart
@@ -0,0 +1,199 @@
+// 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 web_gl_test;
+
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_individual_config.dart';
+import 'dart:html';
+import 'dart:typed_data';
+import 'dart:web_gl';
+import 'dart:web_gl' as gl;
+
+// Test that various webgl extensions are available. Only test advertised
+// supported extensions. If the extension has methods, we just test the presence
+// of some methods - we don't test if functionality works.
+
+main() {
+  useHtmlIndividualConfiguration();
+
+  if (!RenderingContext.supported) return;
+
+
+  const allExtensions = const [
+    'ANGLE_instanced_arrays',
+    'EXT_blend_minmax',
+    'EXT_color_buffer_float',
+    'EXT_color_buffer_half_float',
+    'EXT_disjoint_timer_query',
+    'EXT_frag_depth',
+    'EXT_sRGB',
+    'EXT_shader_texture_lod',
+    'EXT_texture_filter_anisotropic',
+    'OES_element_index_uint',
+    'OES_standard_derivatives',
+    'OES_texture_float',
+    'OES_texture_float_linear',
+    'OES_texture_half_float',
+    'OES_texture_half_float_linear',
+    'OES_vertex_array_object',
+    'WEBGL_color_buffer_float',
+    'WEBGL_compressed_texture_atc',
+    'WEBGL_compressed_texture_es3',
+    'WEBGL_compressed_texture_etc1',
+    'WEBGL_compressed_texture_pvrtc',
+    'WEBGL_compressed_texture_s3tc',
+    'WEBGL_debug_renderer_info',
+    'WEBGL_debug_shaders',
+    'WEBGL_depth_texture',
+    'WEBGL_draw_buffers',
+    'WEBGL_lose_context',
+  ];
+
+  getExtension(String name) {
+    expect(name, isIn(allExtensions), reason: 'unknown extension');
+    var canvas = new CanvasElement();
+    var context = canvas.getContext3d();
+    var supportedExtensions = context.getSupportedExtensions();
+    if (supportedExtensions.contains(name)) {
+      var extension = context.getExtension(name);
+      expect(extension, isNotNull);
+      return extension;
+    }
+    return null;
+  }
+
+  testType(name, typeMatcher) {
+    test('type', () {
+      var extension = getExtension(name);
+      if (extension == null) return;
+      expect(extension, typeMatcher);
+      // Ensure that isInstanceOf<X> is not instantiated for an erroneous type
+      // X.  If X is erroneous, there is only a warning at compile time and X is
+      // treated as dynamic, which would make the above line pass.
+      expect(1, isNot(typeMatcher), reason: 'invalid typeMatcher');
+    });
+  }
+
+  group('ANGLE_instanced_arrays', () {
+    const name = 'ANGLE_instanced_arrays';
+    testType(name, const isInstanceOf<AngleInstancedArrays>());
+    test('vertexAttribDivisorAngle', () {
+      var extension = getExtension(name);
+      if (extension == null) return;
+      expect(extension.vertexAttribDivisorAngle, isFunction);
+    });
+  });
+
+  group('EXT_blend_minmax', () {
+    testType('EXT_blend_minmax', const isInstanceOf<ExtBlendMinMax>());
+  });
+
+  group('EXT_frag_depth', () {
+    testType('EXT_frag_depth', const isInstanceOf<ExtFragDepth>());
+  });
+
+  group('EXT_sRGB', () {
+    testType('EXT_sRGB', const isInstanceOf<EXTsRgb>());
+  });
+
+  group('EXT_shader_texture_lod', () {
+    testType(
+        'EXT_shader_texture_lod', const isInstanceOf<ExtShaderTextureLod>());
+  });
+
+  group('EXT_texture_filter_anisotropic', () {
+    testType('EXT_texture_filter_anisotropic',
+        const isInstanceOf<ExtTextureFilterAnisotropic>());
+  });
+
+  group('OES_element_index_uint', () {
+    testType(
+        'OES_element_index_uint', const isInstanceOf<OesElementIndexUint>());
+  });
+
+  group('OES_standard_derivatives', () {
+    testType('OES_standard_derivatives',
+        const isInstanceOf<OesStandardDerivatives>());
+  });
+
+  group('OES_texture_float', () {
+    testType('OES_texture_float', const isInstanceOf<OesTextureFloat>());
+  });
+
+  group('OES_texture_float_linear', () {
+    testType('OES_texture_float_linear',
+        const isInstanceOf<OesTextureFloatLinear>());
+  });
+
+  group('OES_texture_half_float', () {
+    testType(
+        'OES_texture_half_float', const isInstanceOf<OesTextureHalfFloat>());
+  });
+
+  group('OES_texture_half_float_linear', () {
+    testType('OES_texture_half_float_linear',
+        const isInstanceOf<OesTextureHalfFloatLinear>());
+  });
+
+  group('OES_vertex_array_object', () {
+    testType(
+        'OES_vertex_array_object', const isInstanceOf<OesVertexArrayObject>());
+  });
+
+  group('WEBGL_compressed_texture_atc', () {
+    testType('WEBGL_compressed_texture_atc',
+        const isInstanceOf<CompressedTextureAtc>());
+  });
+
+  group('WEBGL_compressed_texture_etc1', () {
+    testType('WEBGL_compressed_texture_etc1',
+        const isInstanceOf<CompressedTextureETC1>());
+  });
+
+  group('WEBGL_compressed_texture_pvrtc', () {
+    testType('WEBGL_compressed_texture_pvrtc',
+        const isInstanceOf<CompressedTexturePvrtc>());
+  });
+
+  group('WEBGL_compressed_texture_s3tc', () {
+    testType('WEBGL_compressed_texture_s3tc',
+        const isInstanceOf<CompressedTextureS3TC>());
+  });
+
+  group('WEBGL_debug_renderer_info', () {
+    testType(
+        'WEBGL_debug_renderer_info', const isInstanceOf<DebugRendererInfo>());
+  });
+
+  group('WEBGL_debug_shaders', () {
+    testType('WEBGL_debug_shaders', const isInstanceOf<DebugShaders>());
+  });
+
+  group('WEBGL_depth_texture', () {
+    testType('WEBGL_depth_texture', const isInstanceOf<DepthTexture>());
+  });
+
+  group('WEBGL_draw_buffers', () {
+    const name = 'WEBGL_draw_buffers';
+    testType(name, const isInstanceOf<DrawBuffers>());
+    test('drawBuffersWebgl', () {
+      var extension = getExtension(name);
+      if (extension == null) return;
+      expect(extension.drawBuffersWebgl, isFunction);
+    });
+  });
+
+  group('WEBGL_lose_context', () {
+    const name = 'WEBGL_lose_context';
+    testType(name, const isInstanceOf<LoseContext>());
+    test('loseContext', () {
+      var extension = getExtension(name);
+      if (extension == null) return;
+      expect(extension.loseContext, isFunction);
+    });
+  });
+}
+
+Matcher isFunction = const isInstanceOf<Function>();
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index 67d2941..1902a62 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -207,3 +207,10 @@
 
 [ $compiler == precompiler && $runtime == dart_precompiled && $system == android ]
 *: Skip # Issue #26373
+
+[ $hot_reload ]
+function_send_test: Pass, Fail # Closure identity
+message3_test/fun: Pass, Fail # Closure identity
+deferred_in_isolate_test: Crash # Requires deferred libraries
+deferred_in_isolate2_test: Crash # Requires deferred libraries
+issue_21398_parent_isolate2_test: Crash # Requires deferred libraries
diff --git a/tests/isolate/package_config_test.dart b/tests/isolate/package_config_test.dart
index 1b55194..58792d9 100644
--- a/tests/isolate/package_config_test.dart
+++ b/tests/isolate/package_config_test.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-
+// VMOptions=--trace_shutdown
 import 'dart:io';
 import 'dart:isolate';
 
diff --git a/tests/language/arg_param_trailing_comma_test.dart b/tests/language/arg_param_trailing_comma_test.dart
index 4b87b1a..cd0d3a4 100644
--- a/tests/language/arg_param_trailing_comma_test.dart
+++ b/tests/language/arg_param_trailing_comma_test.dart
@@ -41,7 +41,7 @@
 void afterFunsigY([void f(),]) {}                     /// none: continued
 void afterFunsigZ({void f(),}) {}                     /// none: continued
 void afterFunsigDefaultValueY([void f() = topy,]) {}  /// none: continued
-void afterFunsigDefaultValueZ({void f() : topt,}) {}  /// none: continued
+void afterFunsigDefaultValueZ({void f() : topz,}) {}  /// none: continued
 
 class C {
   C();
@@ -77,8 +77,8 @@
 
 main() {
   testCalls();                                        /// none: continued
-  // Make sure the Bad class is checked.
-  new Bad().method();
+  // Make sure the cases are checked.
+  testBadCalls();
 }
 
 void testCalls() {
@@ -124,7 +124,7 @@
   c + x;                                              /// none: continued
   c[x] = y;                                           /// none: continued
 
-  // Call with ekstra comma (not possible for setters and operators).
+  // Call with extra comma (not possible for setters and operators).
   topx(x, );                                          /// none: continued
   topy(y, );                                          /// none: continued
   topxy(x, y, );                                      /// none: continued
@@ -169,7 +169,6 @@
   argfxz(topxz);                                      /// none: continued
 }
 
-
 // Invalid syntax. This was invalid syntax before the addition of trailing
 // commas too, and should stay that way.
 void topBadEmpty(,) {}                           /// 1: compile-time error
@@ -199,6 +198,7 @@
 void set topSetBadEnd(a,,) {}                    /// 25: compile-time error
 void set topSetBadMiddle(a,, b) {}               /// 26: compile-time error
 class Bad {
+  Bad() {}
   Bad.empty(,) {}                                /// 27: compile-time error
   Bad.start(, a) {}                              /// 28: compile-time error
   Bad.end(a,,) {}                                /// 29: compile-time error
@@ -399,3 +399,164 @@
 typedef void BadNamEnd({a,,});                   /// 208: compile-time error
 typedef void BadNamStart({a},);                  /// 209: compile-time error
 typedef void BadNamMiddle({a,, b});              /// 210: compile-time error
+
+void testBadCalls() {
+  topBadEmpty();                                 /// 1: continued
+  topBadStart();                                 /// 2: continued
+  topBadEnd();                                   /// 3: continued
+  topBadMiddle();                                /// 4: continued
+  topBadPosEmpty();                              /// 5: continued
+  topBadPosEmpty();                              /// 6: continued
+  topBadPosEmpty();                              /// 7: continued
+  topBadPosEmpty();                              /// 8: continued
+  topBadPosStart();                              /// 9: continued
+  topBadPosStart();                              /// 10: continued
+  topBadPosEnd();                                /// 11: continued
+  topBadPosStart();                              /// 12: continued
+  topBadPosMiddle();                             /// 13: continued
+  topBadNamEmpty();                              /// 14: continued
+  topBadNamEmpty();                              /// 15: continued
+  topBadNamEmpty();                              /// 16: continued
+  topBadNamEmpty();                              /// 17: continued
+  topBadNamStart();                              /// 18: continued
+  topBadNamStart();                              /// 19: continued
+  topBadNamEnd();                                /// 20: continued
+  topBadNamStart();                              /// 21: continued
+  topBadNamMiddle();                             /// 22: continued
+  topSetBadEmpty = 1;                            /// 23: continued
+  topSetBadStart = 1;                            /// 24: continued
+  topSetBadEnd = 1;                              /// 25: continued
+  topSetBadMiddle = 1;                           /// 26: continued
+  new Bad.empty();                               /// 27: continued
+  new Bad.start();                               /// 28: continued
+  new Bad.end();                                 /// 29: continued
+  new Bad.middle();                              /// 30: continued
+  new Bad.posEmpty();                            /// 31: continued
+  new Bad.posEmpty();                            /// 32: continued
+  new Bad.posEmpty();                            /// 33: continued
+  new Bad.posEmpty();                            /// 34: continued
+  new Bad.posStart();                            /// 35: continued
+  new Bad.posStart();                            /// 36: continued
+  new Bad.posEnd();                              /// 37: continued
+  new Bad.posStart();                            /// 38: continued
+  new Bad.PosMiddle();                           /// 39: continued
+  new Bad.namEmpty();                            /// 40: continued
+  new Bad.namEmpty();                            /// 41: continued
+  new Bad.namEmpty();                            /// 42: continued
+  new Bad.namEmpty();                            /// 43: continued
+  new Bad.namStart();                            /// 44: continued
+  new Bad.namStart();                            /// 45: continued
+  new Bad.namEnd();                              /// 46: continued
+  new Bad.namStart();                            /// 47: continued
+  new Bad.namMiddle();                           /// 48: continued
+  Bad.staticBadEmpty();                          /// 49: continued
+  Bad.staticBadStart();                          /// 50: continued
+  Bad.staticBadEnd();                            /// 51: continued
+  Bad.staticBadMiddle();                         /// 52: continued
+  Bad.staticBadPosEmpty();                       /// 53: continued
+  Bad.staticBadPosEmpty();                       /// 54: continued
+  Bad.staticBadPosEmpty();                       /// 55: continued
+  Bad.staticBadPosEmpty();                       /// 56: continued
+  Bad.staticBadPosStart();                       /// 57: continued
+  Bad.staticBadPosStart();                       /// 58: continued
+  Bad.staticBadPosEnd();                         /// 59: continued
+  Bad.staticBadPosStart();                       /// 60: continued
+  Bad.staticBadPosMiddle();                      /// 61: continued
+  Bad.staticBadNamEmpty();                       /// 62: continued
+  Bad.staticBadNamEmpty();                       /// 63: continued
+  Bad.staticBadNamEmpty();                       /// 64: continued
+  Bad.staticBadNamEmpty();                       /// 65: continued
+  Bad.staticBadNamStart();                       /// 66: continued
+  Bad.staticBadNamStart();                       /// 67: continued
+  Bad.staticBadNamEnd();                         /// 68: continued
+  Bad.staticBadNamStart();                       /// 69: continued
+  Bad.staticBadNamMiddle();                      /// 70: continued
+  Bad.staticSetBadEmpty = 1;                     /// 71: continued
+  Bad.staticSetBadStart = 1;                     /// 72: continued
+  Bad.staticSetBadEnd = 1;                       /// 73: continued
+  Bad.staticSetBadMiddle = 1;                    /// 74: continued
+
+  var bad = new Bad();
+  bad.instanceBadEmpty();                        /// 75: continued
+  bad.instanceBadStart();                        /// 76: continued
+  bad.instanceBadEnd();                          /// 77: continued
+  bad.instanceBadMiddle();                       /// 78: continued
+  bad.instanceBadPosEmpty();                     /// 79: continued
+  bad.instanceBadPosEmpty();                     /// 80: continued
+  bad.instanceBadPosEmpty();                     /// 81: continued
+  bad.instanceBadPosEmpty();                     /// 82: continued
+  bad.instanceBadPosStart();                     /// 83: continued
+  bad.instanceBadPosStart();                     /// 84: continued
+  bad.instanceBadPosEnd();                       /// 85: continued
+  bad.instanceBadPosStart();                     /// 86: continued
+  bad.instanceBadPosMiddle();                    /// 87: continued
+  bad.instanceBadNamEmpty();                     /// 88: continued
+  bad.instanceBadNamEmpty();                     /// 89: continued
+  bad.instanceBadNamEmpty();                     /// 90: continued
+  bad.instanceBadNamEmpty();                     /// 91: continued
+  bad.instanceBadNamStart();                     /// 92: continued
+  bad.instanceBadNamStart();                     /// 93: continued
+  bad.instanceBadNamEnd();                       /// 94: continued
+  bad.instanceBadNamStart();                     /// 95: continued
+  bad.instanceBadNamMiddle();                    /// 96: continued
+  bad.instanceSetBadEmpty = 1;                   /// 97: continued
+  bad.instanceSetBadStart = 1;                   /// 98: continued
+  bad.instanceSetBadEnd = 1;                     /// 99: continued
+  bad.instanceSetBadMiddle = 1;                  /// 100: continued
+  bad * bad;                                     /// 101: continued
+  bad * bad;                                     /// 102: continued
+  bad * bad;                                     /// 103: continued
+  bad[1] = 1;                                    /// 104: continued
+  bad[1] = 1;                                    /// 105: continued
+  bad[1] = 1;                                    /// 106: continued
+  bad[1] = 1;                                    /// 107: continued
+
+  // This covers tests 108-166
+  bad.method();
+
+  bad.f(() {});                                  /// 167: compile-time error
+  bad.f(() {});                                  /// 168: compile-time error
+  bad.f(() {});                                  /// 169: compile-time error
+  bad.f(() {});                                  /// 170: compile-time error
+  bad.f(() {});                                  /// 171: compile-time error
+  bad.f(() {});                                  /// 172: compile-time error
+  bad.f(() {});                                  /// 173: compile-time error
+  bad.f(() {});                                  /// 174: compile-time error
+  bad.f(() {});                                  /// 175: compile-time error
+  bad.f(() {});                                  /// 176: compile-time error
+  bad.f(() {});                                  /// 177: compile-time error
+  bad.f(() {});                                  /// 178: compile-time error
+  bad.f(() {});                                  /// 179: compile-time error
+  bad.f(() {});                                  /// 180: compile-time error
+  bad.f(() {});                                  /// 181: compile-time error
+  bad.f(() {});                                  /// 182: compile-time error
+  bad.f(() {});                                  /// 183: compile-time error
+  bad.f(() {});                                  /// 184: compile-time error
+  bad.f(() {});                                  /// 185: compile-time error
+  bad.f(() {});                                  /// 186: compile-time error
+  bad.f(() {});                                  /// 187: compile-time error
+  bad.f(() {});                                  /// 188: compile-time error
+
+  BadEmpty x;                                    /// 189: compile-time error
+  BadStart x;                                    /// 190: compile-time error
+  BadEnd x;                                      /// 191: compile-time error
+  BadMiddle x;                                   /// 192: compile-time error
+  BadPosEmpty x;                                 /// 193: compile-time error
+  BadPosEmpty x;                                 /// 194: compile-time error
+  BadPosEmpty x;                                 /// 195: compile-time error
+  BadPosEmpty x;                                 /// 196: compile-time error
+  BadPosStart x;                                 /// 197: compile-time error
+  BadPosStart x;                                 /// 198: compile-time error
+  BadPosEnd x;                                   /// 199: compile-time error
+  BadPosStart x;                                 /// 200: compile-time error
+  BadPosMiddle x;                                /// 201: compile-time error
+  BadNamEmpty x;                                 /// 202: compile-time error
+  BadNamEmpty x;                                 /// 203: compile-time error
+  BadNamEmpty x;                                 /// 204: compile-time error
+  BadNamEmpty x;                                 /// 205: compile-time error
+  BadNamStart x;                                 /// 206: compile-time error
+  BadNamStart x;                                 /// 207: compile-time error
+  BadNamEnd x;                                   /// 208: compile-time error
+  BadNamStart x;                                 /// 209: compile-time error
+  BadNamMiddle x;                                /// 210: compile-time error
+}
diff --git a/tests/language/compile_time_constant_e_test.dart b/tests/language/compile_time_constant_e_test.dart
index 7ab0ea2..77b20e9 100644
--- a/tests/language/compile_time_constant_e_test.dart
+++ b/tests/language/compile_time_constant_e_test.dart
@@ -19,7 +19,6 @@
 }
 
 const a1 = const A(99, 100);
-const a1n = const A.n(99, 100);
 const a2 = const A.named(z: 99, t: 100);
 const a3 = const A.named2(t: 1, z: 2, y: 3, x: 4);
 const a4 = const A();
diff --git a/tests/language/disassemble_test.dart b/tests/language/disassemble_test.dart
index 8e53224..bdee5fff 100644
--- a/tests/language/disassemble_test.dart
+++ b/tests/language/disassemble_test.dart
@@ -4,6 +4,7 @@
 // Dart test program for testing isolate communication with
 // typed objects.
 // VMOptions=--disassemble
+// VMOptions=--disassemble --print-variable-descriptors --no-background-compilation
 
 // Tests proper object recognition in disassembler.
 
diff --git a/tests/language/factory5_test.dart b/tests/language/factory5_test.dart
index ff2013b..6155625 100644
--- a/tests/language/factory5_test.dart
+++ b/tests/language/factory5_test.dart
@@ -6,9 +6,8 @@
   factory Link.create() = LinkFactory<T>.create;
 }
 
-class LinkFactory<T> {
+class LinkFactory<T> implements Link<T> {
   factory LinkFactory.create() { return null; }
-  factory LinkFactory.Foo() = Foo<T>;  /// 00: static type warning
 }
 
 main() {
diff --git a/tests/language/factory6_test.dart b/tests/language/factory6_test.dart
new file mode 100644
index 0000000..0f998ff
--- /dev/null
+++ b/tests/language/factory6_test.dart
@@ -0,0 +1,17 @@
+// 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';
+
+abstract class Link<T> {
+  factory Link.Foo() = LinkFactory<T>.Foo;  /// 00: static type warning
+}
+
+class LinkFactory<T> {
+  factory LinkFactory.Foo() = Foo<T>;  /// 00: continued
+}
+
+main() {
+  Expect.throws(() => new Link<int>.Foo()); /// 00: continued
+}
diff --git a/tests/language/generic_local_functions_test.dart b/tests/language/generic_local_functions_test.dart
index 1ec1227..47496a6 100644
--- a/tests/language/generic_local_functions_test.dart
+++ b/tests/language/generic_local_functions_test.dart
@@ -12,13 +12,13 @@
 import "package:expect/expect.dart";
 
 // Declare a generic function parameter.
-String f(int g<X, Y>(Map<X, Y> arg)) => null;
+int f(Y g<X, Y>(Map<X, Y> arg, X x)) => g<int, int>(<int, int>{1: 42}, 1);
 
 main() {
   // Declare a generic local function
-  int h<X extends Y, Y>(Map<X, Y> arg) => null;
+  Y h<X, Y>(Map<X, Y> m, X x) => m[x];
   // Pass a generic local function as an argument.
-  f(h);
+  Expect.equals(f(h), 42);
   // Pass a function expression as an argument.
-  f(<X, Y super X>(Map<X, Y> arg) => 42);
+  Expect.equals(f(<X, Y>(Map<X, Y> m, X x) => m[x]), 42);
 }
diff --git a/tests/language/language.status b/tests/language/language.status
index 03fd476..61b35c9 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -5,12 +5,6 @@
 # This directory contains tests that are intended to show the
 # current state of the language.
 
-# Trailing commas are so far supported by:
-# - The VM (vm, dartium, drt, precompiler+dart_precompiled)
-# Remaining targets still fail on arg_param_trailing_comma_test/none.
-[($compiler != none && $compiler != precompiler) || ($runtime != vm && $runtime != dartium && $runtime != drt && $runtime != dart_precompiled)]
-arg_param_trailing_comma_test/none: Fail # Issue 26644
-
 [ ($compiler == none || $compiler == precompiler || $compiler == dart2app || $compiler == dart2appjit) ]
 tearoff_constructor_basic_test: Skip # Crashes in checked mode -- hausner investigating
 
@@ -197,6 +191,9 @@
 ct_const2_test: Skip # Incompatible flag: --compile_all
 hello_dart_test: Skip # Incompatible flag: --compile_all
 
+[ $runtime == dart_app ]
+number_identity_test: RuntimeError # Issue 26873
+
 [ $compiler == precompiler ]
 implicit_closure_test: Skip # Incompatible flag: --use_slow_path
 deopt_inlined_function_lazy_test: Skip # Incompatible flag: --deoptimize-alot
@@ -252,6 +249,37 @@
 issue23244_test: Skip # Issue #26373
 
 [ $hot_reload ]
-deferred_load_inval_code_test: RuntimeError
-regress_26453_test: Pass, Fail, Crash
-vm/regress_16873_test: Pass, Crash
+bound_closure_equality_test: Pass, Fail # Closure identity
+static_closure_identical_test: Pass, Fail # Closure identity
+cha_deopt1_test: Crash # Requires deferred libraries
+cha_deopt2_test: Crash # Requires deferred libraries
+cha_deopt3_test: Crash # Requires deferred libraries
+deferred_call_empty_before_load_test: Crash # Requires deferred libraries
+deferred_closurize_load_library_test: Crash # Requires deferred libraries
+deferred_constant_list_test: Crash # Requires deferred libraries
+deferred_constraints_constants_test: Crash # Requires deferred libraries
+deferred_constraints_type_annotation_test: Crash # Requires deferred libraries
+deferred_function_type_test: Crash # Requires deferred libraries
+deferred_global_test: Crash # Requires deferred libraries
+deferred_import_core_test: Crash # Requires deferred libraries
+deferred_inlined_test: Crash # Requires deferred libraries
+deferred_inheritance_constraints_test: Crash # Requires deferred libraries
+deferred_load_constants_test: Crash # Requires deferred libraries
+deferred_load_inval_code_test: Crash # Requires deferred libraries
+deferred_load_library_wrong_args_test: Crash # Requires deferred libraries
+deferred_mixin_test: Crash # Requires deferred libraries
+deferred_no_such_method_test: Crash # Requires deferred libraries
+deferred_not_loaded_check_test: Crash # Requires deferred libraries
+deferred_only_constant_test: Crash # Requires deferred libraries
+deferred_optimized_test: Crash # Requires deferred libraries
+deferred_redirecting_factory_test: Crash # Requires deferred libraries
+deferred_regression_22995_test: Crash # Requires deferred libraries
+deferred_shadow_load_library_test: Crash # Requires deferred libraries
+deferred_shared_and_unshared_classes_test: Crash # Requires deferred libraries
+deferred_static_seperate_test: Crash # Requires deferred libraries
+deferred_super_dependency_test: Pass, Crash # Requires deferred libraries
+deferred_type_dependency_test: Crash # Requires deferred libraries
+issue_1751477_test: Crash # Requires deferred libraries
+regress_23408_test: Crash # Requires deferred libraries
+regress_22443_test: Crash # Requires deferred libraries
+tearoff_basic_test: Crash # Requires deferred libraries
diff --git a/tests/language/language_analyzer2.status b/tests/language/language_analyzer2.status
index 63ac9b5..492e396 100644
--- a/tests/language/language_analyzer2.status
+++ b/tests/language/language_analyzer2.status
@@ -85,9 +85,6 @@
 # test issue 11579, assignment, no setter
 getter_no_setter_test/none: fail
 
-# test issue 11584, positional arguments cannot be used for named parameters
-compile_time_constant_e_test: fail # Test Issue 11584
-
 # test issue 11585, static warning, not negative test
 constructor3_negative_test: fail
 constructor_call_wrong_argument_count_negative_test: fail
@@ -126,9 +123,6 @@
 # test issue 12191, ambiguous import is always warning now
 prefix3_negative_test: fail # Issue 12191
 
-# test issue 12289, assignment in assert statement
-type_error_test: fail # Issue 12289
-
 # test issue 12381, It is compile-time error to invoke not existing function
 issue11724_test: fail # Issue 12381
 
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index aec3d55..8001ee7 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -5,6 +5,7 @@
 [ $compiler == dart2js ]
 getter_setter_in_lib_test: Fail # Issue 23288
 method_name_test: Fail # issue 25574
+setter4_test: CompileTimeError # issue 13639
 
 async_star_cancel_while_paused_test: RuntimeError # Issue 22853
 tearoff_basic_test: Skip # Tear-off not supported
@@ -102,8 +103,7 @@
 ref_before_declaration_test/05: MissingCompileTimeError
 ref_before_declaration_test/06: MissingCompileTimeError
 
-regress_22976_test/01: CompileTimeError # Issue 23132
-regress_22976_test/02: CompileTimeError # Issue 23132
+regress_22976_test: CompileTimeError # Issue 23132
 
 if_null_assignment_behavior_test/13: Crash # Issue 23491
 if_null_assignment_behavior_test/14: Crash # Issue 23491
@@ -243,14 +243,6 @@
 stack_trace_test: Fail, OK # Stack trace not preserved in minified code.
 regress_21795_test: RuntimeError # Issue 12605
 
-[ $compiler == dart2js && $runtime == d8 && $system == windows ]
-# Detection of d8 runtime does not work on Windows so the runtime result is
-# unreliable; at the time of writing, 32 passed, 31 failed with runtime error.
-# Marked with Pass,RuntimeError to avoid undetected compile-time failures.
-*deferred*: Pass,RuntimeError # Issue 17458
-cha_deopt*: Pass,RuntimeError # Issue 17458
-regress_22443_test: Pass,RuntimeError # Issue 17458
-
 [ $compiler == dart2js && $cps_ir == false ]
 accessor_conflict_export2_test: Crash # Issue 25626
 accessor_conflict_export_test: Crash # Issue 25626
@@ -337,3 +329,9 @@
 
 [ $compiler == dart2js && $cps_ir && $checked ]
 *: Skip # `assert` not implemented
+
+[ $compiler == dart2js && $host_checked ]
+regress_26855_test/1: Crash # Issue 26867
+regress_26855_test/2: Crash # Issue 26867
+regress_26855_test/3: Crash # Issue 26867
+regress_26855_test/4: Crash # Issue 26867
diff --git a/tests/language/regress_22976_test.dart b/tests/language/regress_22976_test.dart
index 67d6957..ea29319 100644
--- a/tests/language/regress_22976_test.dart
+++ b/tests/language/regress_22976_test.dart
@@ -9,6 +9,8 @@
 class C<S, T> implements B<S>, A<T> {}
 
 main() {
-  A<int> a0 = new C<int, String>(); /// 01: ok
-  A<int> a1 = new C<String, int>(); /// 02: ok
+  C<int, String> c1 = new C<int, String>();
+  C<String, int> c2 = new C<String, int>();
+  A<int> a0 = c1; /// 01: ok
+  A<int> a1 = c2; /// 02: ok
 }
diff --git a/tests/language/regress_26855_test.dart b/tests/language/regress_26855_test.dart
new file mode 100644
index 0000000..3d6c963
--- /dev/null
+++ b/tests/language/regress_26855_test.dart
@@ -0,0 +1,26 @@
+// 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.
+
+void f0(this.x) {}  /// 0: compile-time error
+
+void f1(int g(this.x)) {}  /// 1: compile-time error
+
+void f2(int g(int this.x)) {}  /// 2: compile-time error
+
+class C {
+  C();
+  var x;
+  void f3(int g(this.x)) {}  /// 3: compile-time error
+  C.f4(int g(this.x));  /// 4: compile-time error
+}
+
+main() {
+  f0(null);  /// 0: continued
+  f1(null);  /// 1: continued
+  f2(null);  /// 2: continued
+  C c = new C();
+  c.f3(null);  /// 3: continued
+  new C.f4(null);  /// 4: continued
+}
+
diff --git a/tests/language/setter4_test.dart b/tests/language/setter4_test.dart
index 8428a7a..0fea7fe 100644
--- a/tests/language/setter4_test.dart
+++ b/tests/language/setter4_test.dart
@@ -4,14 +4,23 @@
 // Dart test to catch error reporting bugs in class fields declarations.
 // Should be an error because we have a setter overriding a function name.
 
+import 'package:expect/expect.dart';
+
 class A {
+  int i;
   int a() {
     return 1;
   }
   void set a(var val) {
-    int i = val;
+    i = val;
   }
 }
 
 main() {
+  var a = new A();
+  Expect.isNull(a.i);
+  Expect.equals(a.a(), 1);
+  a.a = 2;
+  Expect.equals(a.a(), 1);
+  Expect.equals(a.i, 2);
 }
diff --git a/tests/lib/analyzer/analyze_library.status b/tests/lib/analyzer/analyze_library.status
index b86abdc..98b521c 100644
--- a/tests/lib/analyzer/analyze_library.status
+++ b/tests/lib/analyzer/analyze_library.status
@@ -9,6 +9,7 @@
 lib/html/html_common/html_common_dart2js: CompileTimeError # Issue 16522
 lib/indexed_db/dart2js/indexed_db_dart2js: CompileTimeError # Issue 16522
 lib/js/dart2js/js_dart2js: CompileTimeError # Issue 16522
+lib/js_util/dart2js/js_util_dart2js: CompileTimeError # Issue 16522
 lib/svg/dart2js/svg_dart2js: CompileTimeError # Issue 16522
 lib/typed_data/dart2js/native_typed_data_dart2js: CompileTimeError # Issue 16522
 lib/typed_data/dart2js/typed_data_dart2js: CompileTimeError # Issue 16522
@@ -25,4 +26,5 @@
 lib/web_audio/dartium/web_audio_dartium: StaticWarning # Issue 21647
 lib/svg/dartium/svg_dartium: StaticWarning # Issue 21647
 lib/_blink/dartium/_blink_dartium: StaticWarning # Undefined Creates and Returns classes
-lib/js/dartium/js_dartium: StaticWarning # Undefined Creates and Returns classes
\ No newline at end of file
+lib/js/dartium/js_dartium: StaticWarning # Undefined Creates and Returns classes
+lib/js_util/dartium/js_util_dartium: StaticWarning # Issue 21647
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 8d3dcee..37f4f1e 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -375,6 +375,28 @@
 mirrors/accessor_cache_overflow_test: Skip
 
 [ $hot_reload ]
-convert/chunked_conversion_utf88_test: Pass, Timeout
-convert/streamed_conversion_json_utf8_decode_test: Fail, Crash
-convert/utf85_test: Fail, Crash
+async/stream_transformer_test: Pass, Fail # Closure identity
+mirrors/closurization_equivalence_test: SkipByDesign # Method equality
+mirrors/fake_function_with_call_test: SkipByDesign # Method equality
+
+async/multiple_timer_test: Pass, Fail # Timing related
+
+mirrors/generic_bounded_by_type_parameter_test/02: Fail # Type equality - Issue 26869
+mirrors/typedef_reflected_type_test/01: Fail # Type equality - Issue 26869
+mirrors/generic_bounded_test/02: Fail # Type equality - Issue 26869
+mirrors/generic_bounded_by_type_parameter_test/02: Fail # Type equality - Issue 26869
+mirrors/typedef_reflected_type_test/01: Fail # Type equality - Issue 26869
+
+mirrors/library_enumeration_deferred_loading_test: Crash # Deferred loading
+mirrors/library_imports_deferred_test: Crash # Deferred loading
+mirrors/library_import_deferred_loading_test: Crash # Deferred loading
+mirrors/typedef_deferred_library_test: Crash # Deferred loading
+mirrors/deferred_mirrors_update_test: Crash # Deferred loading
+mirrors/deferred_mirrors_metadata_test: Crash # Deferred loading
+mirrors/deferred_mirrors_metatarget_test: Crash # Deferred loading
+mirrors/load_library_test: Crash # Deferred loading
+
+mirrors/metadata_scope_test/none: Fail # Constant equality - Issue 26868
+
+typed_data/float32x4_unbox_regress_test: Pass, Crash # Issue 26888
+math/double_pow_test: Pass, Fail # Issue 26887
diff --git a/tests/standalone/io/http_basic_test.dart b/tests/standalone/io/http_basic_test.dart
index f30a32b..266dd8f 100644
--- a/tests/standalone/io/http_basic_test.dart
+++ b/tests/standalone/io/http_basic_test.dart
@@ -2,10 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 //
-// VMOptions=
-// VMOptions=--short_socket_read
-// VMOptions=--short_socket_write
-// VMOptions=--short_socket_read --short_socket_write
+// VMOptions=--trace_shutdown
+// VMOptions=--trace_shutdown --short_socket_read
+// VMOptions=--trace_shutdown --short_socket_write
+// VMOptions=--trace_shutdown --short_socket_read --short_socket_write
 
 import "package:expect/expect.dart";
 import "dart:isolate";
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index bcad73f..ff14249 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -319,13 +319,18 @@
 oom_error_stacktrace_test: Skip # Issue #26377
 out_of_memory_test: Skip # Issue #26377
 
-[ $runtime == dart_precompiled ]
+[ $runtime == vm || $runtime == dart_app || $runtime == dart_precompiled ]
 deferred_transitive_import_error_test: Skip # Contains intentional errors.
 
 [ $hot_reload ]
-io/bytes_builder_test: RuntimeError
-io/file_input_stream_test: Crash
-io/file_test: Pass, Crash
-io/web_socket_protocol_processor_test: Pass, Crash
-map_insert_remove_oom_test: Crash
-priority_queue_stress_test: Crash
+deferred_transitive_import_error_test: Crash # Uses deferred imports.
+package/*: SkipByDesign # Launches VMs in interesting ways.
+
+[ $builder_tag == no_ipv6 ]
+io/http_bind_test: Skip
+io/raw_datagram_socket_test: Skip
+io/socket_source_address_test: Skip
+io/socket_bind_test: Skip
+io/http_proxy_advanced_test: Skip
+io/http_ipv6_test: Skip
+io/socket_ipv6_test: Skip
diff --git a/tests/utils/dummy_compiler_test.dart b/tests/utils/dummy_compiler_test.dart
index 608e099..c8becb3 100644
--- a/tests/utils/dummy_compiler_test.dart
+++ b/tests/utils/dummy_compiler_test.dart
@@ -1,8 +1,6 @@
 // Copyright (c) 2012, 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=
-// VMOptions=--print-object-histogram
 
 // Smoke test of the dart2js compiler API.
 library dummy_compiler;
diff --git a/tests/utils/utils.status b/tests/utils/utils.status
index b1dc829..66ec0d2 100644
--- a/tests/utils/utils.status
+++ b/tests/utils/utils.status
@@ -20,3 +20,7 @@
 [ $compiler == dart2js && $cps_ir && $host_checked ]
 dummy_compiler_test: Crash # Issue 24485
 recursive_import_test: Crash # Issue 24485
+
+[ $hot_reload ]
+recursive_import_test: Skip # Running dart2js under frequent reloads is slow.
+dummy_compiler_test: Skip # Running dart2js under frequent reloads is slow.
diff --git a/tools/VERSION b/tools/VERSION
index bc466cc..8dbdf92 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -25,7 +25,7 @@
 #
 CHANNEL dev
 MAJOR 1
-MINOR 18
+MINOR 19
 PATCH 0
-PRERELEASE 4
-PRERELEASE_PATCH 4
+PRERELEASE 0
+PRERELEASE_PATCH 0
diff --git a/tools/build.py b/tools/build.py
index 1f9eb8b..055b19a 100755
--- a/tools/build.py
+++ b/tools/build.py
@@ -88,7 +88,7 @@
 
 def ProcessOptions(options, args):
   if options.arch == 'all':
-    options.arch = 'ia32,x64,simarm,simarm64,simmips,simdbc'
+    options.arch = 'ia32,x64,simarm,simarm64,simmips,simdbc64'
   if options.mode == 'all':
     options.mode = 'debug,release,product'
   if options.os == 'all':
diff --git a/tools/create_sdk.py b/tools/create_sdk.py
index 65f585e..dad929b 100755
--- a/tools/create_sdk.py
+++ b/tools/create_sdk.py
@@ -59,6 +59,7 @@
 # ......io/
 # ......isolate/
 # ......js/
+# ......js_util/
 # ......math/
 # ......mirrors/
 # ......typed_data/
@@ -254,7 +255,7 @@
                   join('html', 'dart2js'), join('html', 'dartium'),
                   join('html', 'html_common'),
                   join('indexed_db', 'dart2js'), join('indexed_db', 'dartium'),
-                  'js', 'math', 'mirrors', 'profiler', 'typed_data',
+                  'js', 'js_util', 'math', 'mirrors', 'profiler', 'typed_data',
                   join('svg', 'dart2js'), join('svg', 'dartium'),
                   join('web_audio', 'dart2js'), join('web_audio', 'dartium'),
                   join('web_gl', 'dart2js'), join('web_gl', 'dartium'),
diff --git a/tools/dartium/generate_patches.sh b/tools/dartium/generate_patches.sh
index 40dc895..11c73b8 100755
--- a/tools/dartium/generate_patches.sh
+++ b/tools/dartium/generate_patches.sh
@@ -26,17 +26,17 @@
 #       build Dartium, run this script and build Dartium again with the newly
 #       generated patches. 
 
-LOCATION_DARTIUM="../../../out/Release"
-DARTIUM="$LOCATION_DARTIUM"
+if [[ "$1" != "" ]] ; then
+  DARTIUM="$1"
+else
+  LOCATION_DARTIUM="../../../out/Release"
+  DARTIUM="$LOCATION_DARTIUM"
+fi
 
 DART_APP_LOCATION="file://"$PWD"/generate_app/generate_cached_patches.html"
 DARTIUM_ARGS=" --user-data-dir=out --disable-web-security --no-sandbox --enable-blink-features=dartGenCachedPatches"
 CACHED_PATCHES_FILE=""$PWD"/../../sdk/lib/js/dartium/cached_patches.dart"
 
-if [[ "$1" != "" ]] ; then
-  DARTIM="$1"
-fi
-
 cmd=""$DARTIUM"/chrome "$DARTIUM_ARGS" "$DART_APP_LOCATION" |
   (sed -n '/START_OF_CACHED_PATCHES/,/END_OF_CACHED_PATCHES/p') > "$CACHED_PATCHES_FILE""
 
diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS
index a12cdc3..9c2c9a4 100644
--- a/tools/deps/dartium.deps/DEPS
+++ b/tools/deps/dartium.deps/DEPS
@@ -9,7 +9,7 @@
 
 vars.update({
   "dartium_chromium_commit": "67a7ba9669f7bb0300ef35085d4e6bb98b1966cc",
-  "dartium_webkit_commit": "d3db7d1b53979ca91cbf8f3117971f49d0fddf13",
+  "dartium_webkit_commit": "6d435325ef16ceb54f23f5ec6414650ce5ef79ef",
   "chromium_base_revision": "338390",
 
   # We use mirrors of all github repos to guarantee reproducibility and
diff --git a/tools/dom/scripts/dartdomgenerator.py b/tools/dom/scripts/dartdomgenerator.py
index c0315df2..6459e45 100755
--- a/tools/dom/scripts/dartdomgenerator.py
+++ b/tools/dom/scripts/dartdomgenerator.py
@@ -287,6 +287,9 @@
   parser.add_option('--gen-interop', dest='dart_js_interop',
                     action='store_true', default=False,
                     help='Use Javascript objects (dart:js) accessing the DOM in _blink')
+  parser.add_option('--no-cached-patches', dest='no_cached_patches',
+                    action='store_true', default=False,
+                    help='Do not generate the sdk/lib/js/cached_patches.dart file')
 
   (options, args) = parser.parse_args()
 
@@ -346,13 +349,14 @@
           os.path.join(dartium_output_dir, '%s_dartium.dart' % library_name),
           os.path.join('..', '..', '..', 'sdk', 'lib', library_name, 'dartium'))
 
-    # Blow away the cached_patches.dart needs to be re-generated for Dartium
-    # see tools/dartium/generate_patches.sh
-    cached_patches_filename = os.path.join('..', '..', '..', 'sdk', 'lib', 'js', 'dartium',
-                                           'cached_patches.dart')
-    cached_patches = open(cached_patches_filename, 'w')
-    cached_patches.write(CACHED_PATCHES);
-    cached_patches.close()
+    if (not(options.no_cached_patches)):
+      # Blow away the cached_patches.dart needs to be re-generated for Dartium
+      # see tools/dartium/generate_patches.sh
+      cached_patches_filename = os.path.join('..', '..', '..', 'sdk', 'lib', 'js', 'dartium',
+                                             'cached_patches.dart')
+      cached_patches = open(cached_patches_filename, 'w')
+      cached_patches.write(CACHED_PATCHES);
+      cached_patches.close()
 
   if '_blink' in systems:
     _logger.info('Generating dartium _blink file.')
diff --git a/tools/dom/scripts/generator.py b/tools/dom/scripts/generator.py
index db47521..9e15a96 100644
--- a/tools/dom/scripts/generator.py
+++ b/tools/dom/scripts/generator.py
@@ -321,14 +321,47 @@
 
     'TransitionEvent': 'TransitionEvent,WebKitTransitionEvent',
 
-    'WebGLLoseContext': 'WebGLLoseContext,WebGLExtensionLoseContext',
-
     'CSSKeyframeRule':
         'CSSKeyframeRule,MozCSSKeyframeRule,WebKitCSSKeyframeRule',
 
     'CSSKeyframesRule':
         'CSSKeyframesRule,MozCSSKeyframesRule,WebKitCSSKeyframesRule',
 
+    # webgl extensions are sometimes named directly after the getExtension
+    # parameter (e.g on Firefox).
+
+    'ANGLEInstancedArrays': 'ANGLEInstancedArrays,ANGLE_instanced_arrays',
+    'EXTsRGB': 'EXTsRGB,EXT_sRGB',
+    'EXTBlendMinMax': 'EXTBlendMinMax,EXT_blend_minmax',
+    'EXTFragDepth': 'EXTFragDepth,EXT_frag_depth',
+    'EXTShaderTextureLOD': 'EXTShaderTextureLOD,EXT_shader_texture_lod',
+    'EXTTextureFilterAnisotropic':
+        'EXTTextureFilterAnisotropic,EXT_texture_filter_anisotropic',
+    'OESElementIndexUint': 'OESElementIndexUint,OES_element_index_uint',
+    'OESStandardDerivatives': 'OESStandardDerivatives,OES_standard_derivatives',
+    'OESTextureFloat': 'OESTextureFloat,OES_texture_float',
+    'OESTextureFloatLinear': 'OESTextureFloatLinear,OES_texture_float_linear',
+    'OESTextureHalfFloat': 'OESTextureHalfFloat,OES_texture_half_float',
+    'OESTextureHalfFloatLinear':
+        'OESTextureHalfFloatLinear,OES_texture_half_float_linear',
+    'OESVertexArrayObject':
+        'OESVertexArrayObject,OES_vertex_array_object',
+    'WebGLCompressedTextureATC':
+        'WebGLCompressedTextureATC,WEBGL_compressed_texture_atc',
+    'WebGLCompressedTextureETC1':
+        'WebGLCompressedTextureETC1,WEBGL_compressed_texture_etc1',
+    'WebGLCompressedTexturePVRTC':
+        'WebGLCompressedTexturePVRTC,WEBGL_compressed_texture_pvrtc',
+    'WebGLCompressedTextureS3TC':
+        'WebGLCompressedTextureS3TC,WEBGL_compressed_texture_s3tc',
+    'WebGLDebugRendererInfo': 'WebGLDebugRendererInfo,WEBGL_debug_renderer_info',
+    'WebGLDebugShaders': 'WebGLDebugShaders,WEBGL_debug_shaders',
+    'WebGLDepthTexture': 'WebGLDepthTexture,WEBGL_depth_texture',
+    'WebGLDrawBuffers': 'WebGLDrawBuffers,WEBGL_draw_buffers',
+    'WebGLLoseContext':
+        'WebGLLoseContext,WebGLExtensionLoseContext,WEBGL_lose_context',
+
+
 }, dart2jsOnly=True)
 
 def IsRegisteredType(type_name):
@@ -698,7 +731,7 @@
               # Events fired need use a JSFunction not a anonymous closure to
               # insure the event can really be removed.
               parameters.append('js.allowInterop(%s)' % p.name)
-# These commented out cases don't actually generate any code.              
+# These commented out cases don't actually generate any code.
 #          elif dart_js_interop and type_id == 'FontFaceSetForEachCallback':
               # forEach is supported in the DOM for FontFaceSet as it iterates
               # over the Javascript Object the callback parameters are also
diff --git a/tools/dom/scripts/go.sh b/tools/dom/scripts/go.sh
index a830a9b..99c4e72 100755
--- a/tools/dom/scripts/go.sh
+++ b/tools/dom/scripts/go.sh
@@ -20,6 +20,12 @@
 #
 #   ./go.sh dart2js,htmldartium
 #
+# To re-gen all sdk/lib files (outside of a Dartium enlistment the file
+# 'sdk/lib/js/cached_patches.dart' might not need to be generated).  To run
+# go.sh w/o the patches files used --no-cached-patches switch e.g.,
+#
+#  ./go.sh --no-cached-patches
+#
 # The following gives a picture of the changes due to 'work'
 #
 #   git checkout master               # select client without changes
@@ -33,8 +39,20 @@
 SYSTEMS="$ALLSYSTEMS"
 
 if [[ "$1" != "" ]] ; then
-  SYSTEMS="$1"
+  if [[ "$1" =~ ^-- ]]; then
+      ARG_OPTION="$1"
+  else
+      SYSTEMS="$1"
+  fi
+fi
+
+if [[ "$2" != "" ]] ; then
+  if [[ "$2" =~ ^-- ]]; then
+      ARG_OPTION="$2"
+  else
+      SYSTEMS="$2"
+  fi
 fi
 
 reset && \
-./dartdomgenerator.py --systems="$SYSTEMS" --logging=40 --update-dom-metadata --gen-interop
+./dartdomgenerator.py --systems="$SYSTEMS" --logging=40 --update-dom-metadata --gen-interop "$ARG_OPTION"
diff --git a/tools/fuchsia_link.py b/tools/fuchsia_link.py
index c3c537b..74936b0 100755
--- a/tools/fuchsia_link.py
+++ b/tools/fuchsia_link.py
@@ -105,8 +105,8 @@
 
   if link_target == 'target':
     # Add and remove libraries as listed in configurations_fuchsia.gypi
-    libs_to_rm = ['-lrt', '-lpthread', '-ldl']
-    libs_to_add = [fuchsia_libgcc, '-lc',]
+    libs_to_rm = ['-lrt', '-lpthread']
+    libs_to_add = [fuchsia_libgcc, '-lc', '-ldl', '-lm']
 
     # Add crtn_fuchsia to end if we are linking an executable.
     if link_type == 'executable':
diff --git a/tools/gyp/configurations_msvs.gypi b/tools/gyp/configurations_msvs.gypi
index 68a08c5..10e3c47 100644
--- a/tools/gyp/configurations_msvs.gypi
+++ b/tools/gyp/configurations_msvs.gypi
@@ -116,6 +116,7 @@
             'Optimization': '2',
             'InlineFunctionExpansion': '2',
             'EnableIntrinsicFunctions': 'true',
+            'EnableFunctionLevelLinking': 'true',
             'FavorSizeOrSpeed': '0',
             'ExceptionHandling': '0',
             'RuntimeTypeInfo': 'false',
diff --git a/tools/gypi_to_gn.py b/tools/gypi_to_gn.py
old mode 100644
new mode 100755
index a107f94..1aa092c
--- a/tools/gypi_to_gn.py
+++ b/tools/gypi_to_gn.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
 # Copyright 2014 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
diff --git a/tools/make_version.py b/tools/make_version.py
old mode 100644
new mode 100755
index cf96fe2..157c955
--- a/tools/make_version.py
+++ b/tools/make_version.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
 # Copyright (c) 2011, 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.
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index 76a0e55..1747731 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -180,10 +180,6 @@
     }
     if (hotReload) {
       args.add('--hot-reload-test-mode');
-      // Remove the following once known bugs with background compilation
-      // and OSR are fixed.
-      args.add('--no-background-compilation');
-      args.add('--no-osr');
     }
     return args
       ..addAll(vmOptions)
diff --git a/tools/testing/dart/multitest.dart b/tools/testing/dart/multitest.dart
index d39bc9a..eb85c1a 100644
--- a/tools/testing/dart/multitest.dart
+++ b/tools/testing/dart/multitest.dart
@@ -221,7 +221,11 @@
 }
 
 Future doMultitest(
-    Path filePath, String outputDir, Path suiteDir, CreateTest doTest) {
+    Path filePath,
+    String outputDir,
+    Path suiteDir,
+    CreateTest doTest,
+    bool hotReload) {
   void writeFile(String filepath, String content) {
     final File file = new File(filepath);
 
@@ -273,6 +277,13 @@
       bool isNegativeIfChecked = outcome.contains('dynamic type error');
       bool hasCompileErrorIfChecked =
           outcome.contains('checked mode compile-time error');
+      if (hotReload) {
+        if (hasCompileError || hasCompileErrorIfChecked) {
+          // Running a test that expects a compilation error with hot reloading
+          // is redundant with a regular run of the test.
+          continue;
+        }
+      }
       doTest(multitestFilename, filePath, hasCompileError, hasRuntimeErrors,
           isNegativeIfChecked: isNegativeIfChecked,
           hasCompileErrorIfChecked: hasCompileErrorIfChecked,
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index da2c5d0..ee9c107 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -703,7 +703,7 @@
   List<Map> _expandConfigurations(Map configuration) {
     // Expand the pseudo-values such as 'all'.
     if (configuration['arch'] == 'all') {
-      configuration['arch'] = 'ia32,x64,simarm,simarm64,simmips,simdbc';
+      configuration['arch'] = 'ia32,x64,simarm,simarm64,simmips,simdbc64';
     }
     if (configuration['mode'] == 'all') {
       configuration['mode'] = 'debug,release,product';
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index c73dc7c..5dfbd39 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -300,6 +300,15 @@
       return;
     }
 
+    if (configuration['hot_reload']) {
+      // Handle reload special cases.
+      if (expectations.contains(Expectation.COMPILETIME_ERROR)) {
+        // Running a test that expects a compilation error with hot reloading
+        // is redundant with a regular run of the test.
+        return;
+      }
+    }
+
     // Update Summary report
     if (configuration['report']) {
       if (testCase.expectCompileError &&
@@ -837,7 +846,11 @@
     CreateTest createTestCase = makeTestCaseCreator(optionsFromFile);
 
     if (optionsFromFile['isMultitest']) {
-      group.add(doMultitest(filePath, buildDir, suiteDir, createTestCase));
+      group.add(doMultitest(filePath,
+                            buildDir,
+                            suiteDir,
+                            createTestCase,
+                            configuration['hot_reload']));
     } else {
       createTestCase(filePath, filePath, optionsFromFile['hasCompileError'],
           optionsFromFile['hasRuntimeError'],